Game Development Community

Rotation from two points

by Trevor "PointDestruction" · in Technical Issues · 02/26/2004 (3:15 pm) · 12 replies

Hhmm - I cant seem to figure out how to get a rotation from point A to point B.

I know how to get the vector between the two - but when I apply the vector to my camera's transformation, I get wierd camera angles and stuff?

Oh, this is for programming inside the engine, fyi

#1
02/26/2004 (3:49 pm)
Ultimately, i'm trying to set my camera's rotation to look at an object thats moving.
#2
02/26/2004 (5:45 pm)
You need to renormalise the camera matrix. What exactly do you mean by "apply" in this case ?

What you should be doing is this, though its not the only way:

Normalise your "look" vector and copy it into the Z row of the camera matrix
Copy a UnitY vector into the Y row
Cross product those two together, normalise the result and copy it into the X row

If your look vector is predomintantly vertical (biggest vector component is ABS(Y) ), the cross starts to get degenerate, so do a similar process using another axis instead, ie:

Copy a UnitX vector into the camera X row then cross that with the Z row and stuff it in the Y row, normalised.

Hope that helps.
#3
02/26/2004 (6:25 pm)
When you say copy a UnitY vector into the Y row - could you emphasize on that?

VectorF newDir;
newDir = mCamPos - getRenderPosition();
newDir.normalize();

mat->setRow(3 , newDir);

thats what I have so far
#4
02/26/2004 (6:42 pm)
Mat is the matrix I need to end up with - mCamPos is where the camera is located - and this is under a shapeBase function - so the getPosition(); en stuff apply to the shape
#5
02/26/2004 (11:11 pm)
MathUtils has a handy function for you...
Point3F vec = mCamPos - getRenderPosition();
   MatrixF m = MathUtils::createOrientFromDir(vec);
   m.setColumn(3,getRenderPosition());
The Matrix then should have the right transform/orientation ...
#6
02/27/2004 (4:01 am)
I guess I should've know this was a torque thing..

@Trevor: Just FYI

A matrix isn't limited to 3D nor was it invented to do 3D with. When you use matrix transforms in 3D what you're actually doing is supplying a vector remapping table that just happens to work in a matrix fashion when you want to accumulate them.

If a 3x3 matrix looks like this m[3][3] that always worries me as it implies the math library is gonna use loops to do stuff. I prefer to define a matrix in terms of what its being used for, so in this case mine would (does) look similar to this

typedef Matrix33 Vector[3];

The first row of the matrix maps the objects X vector orientation into worldspace, the second row does Y and the third does Z

Look at an identity matrix which means "do nothing" from a 3d transform point of view:

1 0 0
0 1 0
0 0 1

Top row remaps local X to world X. If you consider it to be a vector you can see that all of its magnitude is in the X direction. Similarly the second row remaps local Y to world Y. Treated as a vector you can see all its magnitude is in the Y direction. Etc.

Hope that helps to visualise whats going on
#7
02/27/2004 (5:54 am)
With

Point3F vec = mCamPos - getRenderPosition();
MatrixF m = MathUtils::createOrientFromDir(vec);
m.setColumn(3,getRenderPosition());
*mat = m;

I just get a wierd camera angle that looks at my sky and everything's really stretched.

@Paul
I sorta get it. The one thing that still confuses me: for example, take your first row on your matrix (1 0 0); how does that give the direction in x? Is it just the accumulation of each column in the x row - or is it more complex than that?
#8
02/27/2004 (5:57 am)
Nm, stefen, I got it.

This is what I ended up with:

Point3F vec = mCamPos - getRenderPosition();
vec.normalize();
vec.neg();
MatrixF m = MathUtils::createOrientFromDir(vec);
m.setColumn(3,mCamPos);
*mat = m;

Also: how do you do the code deal in posts?
#9
02/27/2004 (6:34 am)
A vector (in 3D math) defines these things. First component is the Xness, 2nd component is the Yness and the third is Zness

1 0 0 is called a unit x vector because its total magnitude is 1 (a unit) and all of it points in the x direction (ie the Xness component.

When you multiply a vector by a matrix, the new vector you get back is essentially the result of mapping its initial Xness onto the new direction from the Xrow of the matrix, and likewise for the other 2 axes.

It is a bit of a head-fuck but all you need to know is that when using matrix math it all drops out in the wash.

If you want to know which direction a matrix is 'facing', pull out the Z row of it and thats your direction vector. For example to make an object fire something forwards, grab its Z row then scale by the speed you want and thats the value to keep adding to your projectiles position.

------

The reason just putting a new vector in the z-row (as per your camera problem) still doesn't work properly is that even though all 3 vectors are normalised (you normalised the new one and the other rows should already be that way), the columns now aren't. A non scaling matrix has to have all 3 rows normalised and all 3 columns too. You can't just normalise the columns after the rows either as then the rows will be out again and you need a feedback loop to do it properly.

The correct way to do this matrix normalise is either as I suggested (by physcially rebuilding all 3 rows in a self-referencing manner that "just works") or by a technique known as matrix ortho-normalisation which gets a little hairy and you don't want to go there. TGE may well have a function called something like this that you can call anyways - it ought to.
#10
02/27/2004 (6:44 am)
I should add though that orthonormalising a camera isn't ideal as it'll end up moving back off line slightly as the various components within the matrix balance out.

Best option is to rebuild it completely as my first suggestion. Better yet is to call the function the math guys have written that will do it for you.

Shoulda taken the blue pill! :)
#11
02/27/2004 (6:47 am)
I have no clue about TGE but just looking at this example:

Point3F vec = mCamPos - getRenderPosition();
MatrixF m = MathUtils::createOrientFromDir(vec);

The createOrientFromDir() function probably expects a normalised direction vector.
#12
02/27/2004 (2:44 pm)
Ya, that helps a little paul. Quite a head-fuck, but whatever. Thx for your guys' help - it's working great and dandy now :P