Game Development Community

Rotation in GFXDevice::setFrustum()??

by Tom Spilman · in Torque Game Engine Advanced · 02/05/2007 (7:47 pm) · 5 replies

Has anyone else looked at GFXDevice::setFrustum()?

void GFXDevice::setFrustum(F32 left, 
                           F32 right, 
                           F32 bottom, 
                           F32 top, 
                           F32 nearPlane, 
                           F32 farPlane)
{
   // store values
   fLeft = left;
   fRight = right;
   fBottom = bottom;
   fTop = top;
   fNear = nearPlane;
   fFar = farPlane;
   fOrtho = false;
   
   // compute matrix
   MatrixF projection;
   
   Point4F row;
   row.x = 2.0*nearPlane / (right-left);
   row.y = 0.0;
   row.z = 0.0;
   row.w = 0.0;
   projection.setRow( 0, row );
   
   row.x = 0.0;
   row.y = 2.0 * nearPlane / (top-bottom);
   row.z = 0.0;
   row.w = 0.0;
   projection.setRow( 1, row );
   
   row.x = (left+right) / (right-left);
   row.y = (top+bottom) / (top-bottom);
   row.z = farPlane / (nearPlane-farPlane);
   row.w = -1.0;
   projection.setRow( 2, row );
   
   row.x = 0.0;
   row.y = 0.0;
   row.z = nearPlane * farPlane / (nearPlane-farPlane);
   row.w = 0.0;
   projection.setRow( 3, row );
   
   projection.transpose();
   
   MatrixF rotMat(EulerF( (M_PI / 2.0), 0.0, 0.0));
     
   projection.mul( rotMat );
    
   setProjectionMatrix( projection );
}

Everything looks pretty standard in there except we have a rotation around the X axis thrown in there at the end. What's going on in there?

The reason i ask is because i'm trying to replicate the same projection with a different z-near plane... since the rotation is done after the projection i get different camera angles with a different znear. The reason i'm doing this is so that i can render the terrain and water with an "optimal" znear based on distance to the terrain... this eliminates the z-fighting you see on shorelines.

About the author

Tom is a programmer and co-owner of Sickhead Games, LLC.


#1
02/05/2007 (11:21 pm)
Oohhhhh!!!!

This could explain why a 3rd party cloud resource (Silverlining) doesnt integrate! It sets its own coordinate system internally, but I havent managed to be able to get it to render nicely in TGEA yet.

Problem I see is, that the axes are screwed up. Billboards turn around wrong axis even though I set it up to use the correct one. According to their support its a problem in Torque and not in their end - no surprise. Dont support always say that. But this could explain it.

Havent had time to investigate yet, but the rotation above could hint at a problem right here.

(Just wanted to chime in on seeing some oddities that could relate to your potential bug report)
#2
02/05/2007 (11:25 pm)
Maybe we can get Brian, Pat, or Ben to chime in with a hint as to why it's in there. :)
#3
02/06/2007 (10:41 am)
Yeah this rotation also occurs in setOrtho. This is, most likely, some leftover from TGE. It may have to do with emulating the behavior of glSetOrtho/Frustum. No clear answers from me, on this...sorry.
#4
02/06/2007 (3:05 pm)
It works; it's best not to question this stuff. ;)

Remember, in Torque Z+ is up, Y+ is out, and X+ is right. (It's a left-handed coordinate system.)

Beyond that - don't know off hand what's up here, just seem to recall breakage happening when it got changed.
#5
02/06/2007 (5:36 pm)
We're actually using a right handed system (or starting out with one) which has -z going forward and y going up. This function is swapping the z and y axis such that +z is up and +y is forward (by rotating 90 degrees on x axis). Left handed has z going forward and y going up.

This is done in the projection matrix so that you don' t have to do this transform in all of the world matrices in the engine. It also could be done with a "view" matrix which some graphics API's support, but then again, you (or it) would have to multiply that by your world matrix whenever it is changed. Since the projection is multiplied by the world anyway, it just saves having to deal with it all over the place.