PDA

View Full Version : OpenGL: Look at matrix



vgo
26-05-2007, 04:19 PM
Still working on my game engine and I have yet another stupid math problem. :)

Here's what I want to do: I have a space station which has several turrets and I want these turrets to rotate to face the player. How can I do this?

Here's some code that I've tried to use, but it doesn't work properly, I have no idea where this code came from, it's probably cut & paste with some trial and error from several different sources... :roll:


function MatrixLookAt(const v1: TVector3f; const v2: TVector3f; const Up: TVector3f): TGLMatrix4f;
var
xAxis, yAxis, zAxis: TVector3f;
begin
zAxis := VectorSubtract(v1, v2);
VectorNormalize(zAxis);

xAxis := VectorCross(Up, zAxis);
VectorNormalize(xAxis);

yAxis := VectorCross(zAxis, xAxis);
VectorNormalize(yAxis);
VectorNormalize(xAxis);

Result := _GLMatrix4f;

Result[0][0] := xAxis.x;
Result[1][0] := xAxis.y;
Result[2][0] := xAxis.z;
Result[3][0] := -VectorDot(xAxis, v1);

Result[0][1] := yAxis.x;
Result[1][1] := yAxis.y;
Result[2][1] := yAxis.z;
Result[3][1] := -VectorDot(yAxis, v1);

Result[0][2] := zAxis.x;
Result[1][2] := zAxis.y;
Result[2][2] := zAxis.z;
Result[3][2] := -VectorDot(zAxis, v1);
end;


So, I put the location of the turret to the first parameter and the location of the player's ship to the second parameter, but what should I put on the third parameter? I've tried 0,1,0 and it seem to work on some cases (sort of), but usually I just get -NAN values in my matrices...

Should I check for example if the two vectors are 0,0,0 and 0,2,0, in this case the Up vector obviously can't be 0,1,0...

Is there a way to easily calculate the correct Up vector? Or is my cut & paste LookAt routine just completely wrong? :(

JSoftware
26-05-2007, 05:52 PM
My matrix lib uses this code:

function lookat(cameraPosition, cameraTarget, up: tvector4f): tmatrix4x4;
var zaxis, xaxis, yaxis: tvector4f;
begin
zaxis := normalize(sub(cameraTarget, cameraPosition));
xaxis := normalize(cross(up, zaxis));
yaxis := cross(zaxis, xaxis);

lookat := matrix4x4(xaxis.x, yaxis.x, zaxis.x, 0,
xaxis.y, yaxis.y, zaxis.y, 0,
xaxis.z, yaxis.z, zaxis.z, 0,
-dot(xaxis, cameraPosition), -dot(yaxis, cameraPosition), -dot(zaxis, cameraPosition), 1);

end;


Edit: In your example your up vector should be 0,1,0. The up vector is just indicating what direction the top of the camera should be pointing.

You would normally just use 0,1,0 unless you want your camera rotated about the local z axis(if you use a opengl like matrix order)

Edit2: I see now that the code is formulated exactly the same way... Could it be your vector functions acting wrong?

vgo
27-05-2007, 11:32 AM
I got it working, as long as the direction is not 0,(-)1,0, this case screwes up the matrix and it gets filled with -NAN values.

Here's what happens:


v1 := _Vector3f(0, 0, 0);
v2 := _Vector3f(0, 10, 0);
Up := _Vector3f(0, 1, 0);

zAxis := VectorSubtract(v1, v2);
VectorNormalize(zAxis);
// zAxis = 0, -1, 0
// Up = 0, 1, 0

xAxis := VectorCross(Up, zAxis);
// xAxis = 0, 0, -0
VectorNormalize(xAxis);
// xAxis = -NAN, -NAN, -NAN


Because the result of VectorCross(Up, zAxis) is 0,0,-0 and I try to normalize it I get -NAN,-NAN,-NAN as the end result for xAxis.

How to prevent this?

M109uk
27-05-2007, 11:56 AM
Could you put a simple check on it? e.g.



If xAxis[2] = -0 Then xAxis[2] := 0;

vgo
27-05-2007, 12:20 PM
Unfortunately it's not that simple, that way I get values like 0,0,0 for xAxis and it's not any different from 0,0,-0. :)

Maybe I need to check for the direction vector (zAxis) and change the Up vector accordingly...

JSoftware
27-05-2007, 12:46 PM
Your vector normalization needs to check if the length of the vectors is zero. If it is it must return 0,0,0 instead of NaN.

NaN will bugger up all the following equations

vgo
27-05-2007, 02:08 PM
I fixed that, but it still doesn't work if the position and target are along y-axis... :(

JSoftware
27-05-2007, 04:08 PM
In that case i would implement a check to see if the length of xAxis is either zero or very close to zero after crossing zAxis and up.

If it is too close to zero you could just set it to a default of 1,0,0.