Sign in to follow this  
MightyXL

Problem aligning a model to an arbitrary vector

Recommended Posts

I've been struggling with this problem for a while now, so any help would be greatly appreciated. Basically, I'm trying to align a model in 3D to any given vector direction. For example, the model's starting direction is (1, 0, 0) and I'd like to be able to say "face (1, 1, 1)" and the model would be drawn facing (1, 1, 1). Right now I'm using D3DXMatrixRotationAxis() to create an arbitrary axis to rotate about giving it the model's starting direction, (1, 0, 0), and the ending direction I want it to face. I then take the acos of the dot product between the starting vector and the ending vector to get the amount to rotate by. I have a check for the zero vector, so I don't think that's an issue. The issue I'm having is that sometimes I will tell the model to look (0, 0, 1) and it will look (0, 0, -1) for instance. I think the problem comes from not knowing if I should be rotating CW or CCW, but I can't for the life of me figure out how to get that information. Some code if it helps:
void CreateArrow(vector3 pos, vector3 dir)
{
  // the arrow starts facing (1, 0, 0)
  vector3 start(1, 0, 0);
  vector3 RotAxis;

  // take the cross product of the starting vector with the new vector, result in RotAxis
  D3DXVec3Cross(RotAxis, &start, &dir);

  if (RotAxis == vector3(0, 0, 0)) // check for zero vector
    RotAxis = vector3(0, 0, 1);

  // normalize to easily get the angle between vectors
  D3DXVec3Normalize(&dir, &dir);

  // get the angle between the starting vector and the new vector
  float angle = acos(D3DXVec3Dot(&start, &dir));
}


Thanks

Share this post


Link to post
Share on other sites
Quote:
The issue I'm having is that sometimes..


The basic principle looks okay, MightyXL, except for the "zero" check of the RotAxis. If RotAxis==(0,0,0), then angle = 0 and you're done.

Can you provide more info on what the values are that "sometimes" give you a result you don't like?

Share this post


Link to post
Share on other sites
It would probably be faster for you to just make a matrix and transform by it.
Starting with the direction you want it to look (at), construct the matrix

Matrix.at = at;
Matrix.up = GlobalUp (ie. 0,1,0)
Matrix.left = Matrix.at cross Matrix.up
Matrix.up = Matrix.at cross Matrix.left

then multiply that matrix into your current transform before drawing your model, and it will insure that the global at (1,0,0) of your model now faces in the direction you wanted

Share this post


Link to post
Share on other sites
Quote:
Original post by Buckeye
Quote:
The issue I'm having is that sometimes..


The basic principle looks okay, MightyXL, except for the "zero" check of the RotAxis. If RotAxis==(0,0,0), then angle = 0 and you're done.

Can you provide more info on what the values are that "sometimes" give you a result you don't like?


Thanks for the quick response.

The specific vectors that seem to be giving me trouble are (0, 0, 1) and (0, 0, -1). They point in the exact opposite directions. I stepped through my code in the debugger, and it seems to be giving me the correct results, so now I'm still confused.

I give it a direction (0, 0, 1).
It computes the cross product of (1, 0, 0) cross (0, 0, 1) = (0, -1, 0) correctly.
It then gives me an angle of 90 degrees, but for some reason the arrow ends up pointing toward the camera instead of away from it.

The camera is centered at position (0, 0, 0) looking down the z axis (0, 0, 1).

Share this post


Link to post
Share on other sites
I'm not sure what you mean by the "arrow." Are you drawing a line in space, or rendering a mesh?

If you believe in your calculation, then the problem is elsewhere - some tranformation you do or don't make, or some assumption you've made that's invalid.

For instance, is the untransformed shape of your arrow or model pointing (0,0,1) like you assume in your calc? That is, whatever you create to display as an arrow must be created pointing (0,0,1).

Maybe if you post the code you use to render the object, we could get a better idea where the problem lies.

Share this post


Link to post
Share on other sites
I'll also note that if you are sticking with your way of rotating the object, all you need to do is get the sign of your angle
by doing
sign ( (start cross dir) dot rotaxis )
and then you have angle * sign, and it should rotate you in the correct direction

Share this post


Link to post
Share on other sites
whoops. I was thinking too fast. trying to get you a "to the left or right" sign, but since you can't garentee that you are rotating
with respect to the global up, you unfortunatly can't pick something as simple as cross.y to find out the direction you are turning.

Still, i sugest you just build the new coordinate matrix as I sugested, and multiply by that.

Share this post


Link to post
Share on other sites
Another thing, MightyXL, just a guess - when you do the rotation, remember you're only changing the direction. For ordinary rotation stuff, like cameras, etc., one maintains a known "up" vector. I'm thinking that the result of a rotation-about-an-axis may or may not give you an "up" for the model you like as the model's local "up" vector will change implicitly with the rotation.

Share this post


Link to post
Share on other sites
Wow, wasn't expecting so much help, especially on the first day. Thanks again Buckeye and KulSeran.

I would like to try the method you suggested about building another matrix to transform my 3D model by, but I'm having a hard time implementing it. I think I understand the concept well enough, but unfortunately I'm fairly new to using matrices and any sort of 3D DirectX. Right now all I do is loop through all of my objects and apply the following matrix to each object:

iter is just an iterator to my list of objects.


world = Matrix::CreateScale(iter->Motion->Scale) *
Matrix::CreateRotationAxis(iter->Motion->RotAxis, iter->Motion->Angle) *
Matrix::CreateTranslation(iter->Motion->Position);
iter->Drawable->Draw(world);



I know this is more of an issue with my lack of knowledge, so I understand if it's too much to ask, but should I be putting the at, up, and left vectors into my new matrix as column vectors? I'll try to see what kind of information I can find about matrices online.

Thanks again.

Share this post


Link to post
Share on other sites
Thanks for the link Gage64, it definitely looks like a good book.

As for the problem, I was able to fix it. Turns out it was a really stupid problem. The guy who is programming the graphics engine for the project I'm working on was using a screwed up coordinate system. I was assuming we were using DirectX's default left handed coordinate system, but it seems like he was using a slightly modified right handed system.

This problem really came from a lack of communication between the two of us, but I'm grateful for all the help you guys were able to give me.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this