Jump to content
  • Advertisement
Sign in to follow this  
Endar

Rotation from A to B

This topic is 4346 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

For my skeletal animation system, I needed to find the local transform required to draw a bone given the two points to draw it from. I wanted the bone to be more complicated than just a line, so I have a small pyramid that is drawn. It's being drawn from point A to point B where point A is the center of the base of the pyramid (square), and point B is the tip of the pyramid.
echo::util::CVector3d p1( 0.064704396f, 40.745468f, 0.0f );
echo::util::CVector3d p2( 0.064704396f, 44.231636f, 0.0f );

echo::util::CVector3d localZ( p2 - p1 );
localZ.normalize();	// the direction from the start point to end point

// assuming that the up vector for the world is (0,1,0)
echo::util::CVector3d localX;
localX = localZ.crossProduct( echo::util::CVector3d(0,1,0) );

// find the local y axis
echo::util::CVector3d localY;
localY = localX.crossProduct( localZ );

// create the matrix
// http://www.gamedev.net/community/forums/viewreply.asp?ID=2391549
echo::util::CMatrix m;

// normalize, just in case
localX.normalize();
localY.normalize();
localZ.normalize();

m(0,0) = localX.x;	m(1,0) = localY.x;	m(2,0) = localZ.x;
m(0,1) = localX.y;	m(1,1) = localY.y;	m(2,1) = localZ.y;
m(0,2) = localX.z;	m(1,2) = localY.z;	m(2,2) = localZ.z;

m.setTranslation( p1 );

I was given this code here by "someusername", and has worked for some time, but I recently noticed that with some bones (simply the distance between two joints, not an actual "bone" object) I would get some wierdness. It would draw a straight line from the start point to a point in space. It wouldn't draw the pyramid, just a straight line. No matter how I rotated the model, the line's end point would stay anchored to the same spot. I found that I was having trouble with the end matrix 'm' and some joints. More specifically when the direction vector between the two points was the same as the world's 'up' vector. This would cause me to get floating point errors, and would therefore give me an invalid matrix to transform by the world matrx to draw the bone. So, is there another way to do this? Or should I make up some sort of a special case?

Share this post


Link to post
Share on other sites
Advertisement
Any 'aim-at' algorithm that uses a fixed reference vector will have the behavior you describe. I can think of a few things you might try though:

1. Use the orientation information for each bone directly, if your keyframe format provides it. This would probably be the ideal solution.

2. Otherwise, you could create an arbitrary basis by using, instead of a fixed reference, the cardinal axis least aligned with the bone direction. The problem with this though is that the orientation will 'pop' as the bone moves around, which won't look so good.

3. A perhaps better option is to handle it as a special case, as you said. Check for the case where the bone direction is close to being aligned with the reference vector, and choose a different reference vector in this case. This will probably give you a more natural change of orientation in the pyramid as the bone moves around.

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
3. A perhaps better option is to handle it as a special case, as you said. Check for the case where the bone direction is close to being aligned with the reference vector, and choose a different reference vector in this case. This will probably give you a more natural change of orientation in the pyramid as the bone moves around.


This sounds like the best thing to do. How would I go about it? I mean, I could use (1,0,0) as a reference vector instead of the up vector (0,1,0), but wouldn't I have to change the order of the products?

Share this post


Link to post
Share on other sites
You shouldn't have to change the order of the products. Just check the absolute value of the dot product of the normalized bone direction vector and the default reference director (0,1,0), and if it's close to 1 use a different reference vector instead.

Share this post


Link to post
Share on other sites
Thanks jyk, that worked perfectly.

Perhaps if you get a chance you could explain to me more why it worked with only changing the reference vector. I know that the cross product gives you a vector perpendicular to the two operated on. And from my understanding of the code we're finding the x and y axes in the direction of the rotation (which is the z axis).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!