Advertisement

Camera and clipping planes?

Started by May 17, 2000 01:46 PM
24 comments, last by Pascalix 24 years, 6 months ago
Hi, I have a camera object defined by four vectors (up, left, right, position) in a matrix a Field Of View angle and the aspect (Width/height ratio). Now, I’m wondering how I can get the clipping planes of this viewing frustum. Ok, the near and far planes are easy but what about the other four? P.S: Does anyone know how plane equations can be transformed by a matrix? Thanks in advance, Pascalix.
Pascalix;
Compute the normals for the clipplanes in viewspace:

NormalLeft = (cos(FovX/2), 0, sin(FovX/2));
NormalRight = (-cos(FovX/2), 0, sin(FovX/2));
NormalTop = (0, -cos(FovY/2), sin(FovY/2));
NormalBottom = (0, cos(FovY/2), sin(FovY/2));

If you use a righthanded coordinate system as OpenGL does, you need to negate the z coordinate of the normals.

Then transform each of the normals by the camera matrix that you already have, except that you should set the position to (0,0,0) so that they aren't translated.

TransformMatrix = [right.x  right.y  right.z  0][   up.x     up.y     up.z  0][front.x  front.z  front.z  0][      0        0        0  1] 


(For OpenGL you need to transpose this matrix)

TransformedNormalLeft = NormalLeft*TransformMatrix

Then finally you compute the last component of the clipplanes, d, with a dotproduct like this:

dLeft = -DotProduct(CameraPosition, TransformedNormalLeft);

The plane equation for the left plane would be

(tnl = TransformedNormalLeft)

x*tnl.x + y*tnl.y + z*tnl.z + dLeft = 0

(I think my calculations are correct, you of course need to verify them )


- WitchLord

(I fixed a small error: dLeft wasn't negated before)

Edited by - WitchLord on May 24, 2000 8:03:14 AM

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement
Thank you WhichLord! I finally got it to work! By the way this is a great way for computing camera clipping planes. The sine and cosine functions need only be called when the FOV changes. Which at least in my programs is not very often. When only the camera’s position or orientation changes these need normals be only multiplied by the transpose of the camera matrix.

P.S.: I think I also figured out the maths behind this: I’m transforming from viewspace into worldspace coordinates. To transform points I would need to multiply them with the inverse of the camera matrix.
But (as I read in the Open GL blue book) normals are transformed by the inverse transpose of the matrix that of the transformation that transforms points.
So the inverse of the inverse of the camera matrix gives me the original matrix. I only need to transpose it.

Thanks again
Pascalix
Pascalix;
I would say that you're one of those people who have moved to the next level of enlightment in 3D game development

- WitchLord

Edited by - WitchLord on May 20, 2000 7:06:42 PM

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

quote:
md2ge wrote:


Hi Witchlord =)

Idea for tutorial, I've been trying to follow the code you posted as a reply, here's is the URL

http://www.gamedev.net/community/forums/topic.asp?topic_id=14022&forum_id=11&Topic_Title=Camera+and+clipping+planes%3F&forum_title=General+and+Game+Programming+Discussion&M=True&S=True

Altho I think I understand the basics of this I'm doing something wrong, I can't seem to arrive at any usefull values for plane equation, here's is what I've done in case you can spot something obvious, otherwise I'll just wait til tutorial =)

I'm only including the code for one of the planes (left plane), also in your post you didn't mention anything regarding aspect ratio, so we dont need it for any of this calculations?



Actually if you examine the code carefully you'll find two references to FOV one being FovX and the other being FovY. For a normal aspect ratio of 4:3 these aren't the same. (I don't have the energy to find paper and pen to actually compute the angles right now )

quote:

// Make a vector in worldspace
D3DXVECTOR3 w;
w.x = 0.0f;
w.y = 0.0f;
w.z = 1.0f;


D3DXMATRIX view;
app->d3d_device->GetTransform(D3DTRANSFORMSTATE_VIEW, D3DMATRIX *)view);
// Need to transpose? or Invert? or ?
D3DXMatrixTranspose(&view,&view);

view.m30=view.m31=view.m32=0.0f;



For a rotation matrix, the inversion and the transposing does the exact same thing. Since we don't have a pure rotation matrix we need to remove the translation part, either before transposing or after. If you inverted the matrix you don't need to bother removing translation part as it will be inverted along with the rest.

quote:

// Assuming an FOV of 90 I need the cos and sin of radian(45)?

D3DXVECTOR3 NormalLeft =( (float)cos(D3DXToRadian(45.0f)),0.0f, (float)sin(D3DXToRadian(45.0f)) );



Yes, when you compute the normal you should divide the angle by two. Imagine what would happen if you didn't divide the angle and you had FOV = 90.

quote:

D3DXVECTOR3 tnl; // transformed normal left
D3DXVec3TransformCoord(&tnl,&NormalLeft,&view);

// There are 3 versions of D3DXVec3Transfrom... I'm guessing this is the correct one.



It would probably be more accurate to use D3DXVec3TransformNormal() instead, since that is exactly what we are doing. However for the pure rotation matrix (that was computed above) these two would do the exact same thing.

quote:

D3DXVECTOR3 cam_pos;
// This function returns the camera position in worldspace
app->CamGetPosition(&cam_pos);

float dLeft = D3DXVec3Dot(&cam_pos,&tnl);



I made a small error here before, dLeft should be computed as:

float dLeft = -D3DXVec3Dot(&cam_pos,&tnl);

(I have fixed it in the above equation)

quote:

float pl = w.x*tnl.x + w.y*tnl.y + w.z*tnl.z + dLeft;

When w=0,0,0 then pl=dLeft

Neither of this 2 values seem to return any usefull information, so I'm either doing something wrong (which is very likely) or I don't know how to interpret this values.



Actually dLeft tells you at what distance the clip plane is from the world origo. And after inserting w in the plane equation p1 tells you at what distance from the plane the point is.

quote:

Thanks,
Rick




Your welcome

- WitchLord

Edited by - WitchLord on May 24, 2000 8:01:24 AM

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks, just comple more questions =)

Let''s say I set up the app with fov 90 and aspect 1.33, can I do this then?

fovx = toradian(45)*1.33
fovy = toradian(45)

and also for this line:

float dLeft = -D3DXVec3Dot(&cam_pos,&tnl);

for cam_pos, I can just use the 3 matrix values we zero out before (store them in cam_pos before I zero them out) right? or do I need to use a 0,0,0 value here?

And lastly, the normals are created in view space, then multiplied by the inverse of the vew matrix, so basically we putting them into world space (but without the translation part?), so when I plug in the xyz point to solve the plane equation this point needs to be in world space?

The frustrum is for some reason diffucult to me to understand, this is my current mental picture =)

It all starts with a pyramid where your eyes are, also referred to as the camera "position", in view space, this point is represented by the translation part of the view matrix, it then extends towards the screen passing thru the 4 corners all the way back to your back clipping plane. The bigger the fov is the closer the eye point gets to the screen and the wider the frustrum becomes, for an fov of 180 the eye would acctualy end up right ON the screen (???) but then this thing is no longer a pyramid more like a rectange (???)

Thanks,
Rick
Advertisement
quote: Original post by md2ge

Thanks, just comple more questions =)

Let''s say I set up the app with fov 90 and aspect 1.33, can I do this then?

fovx = toradian(45)*1.33
fovy = toradian(45)



if fovy is 90 degrees then fovx will be:

fovx = todegree(2*atan(1.33*tan(toradian(fovy/2))) = 106degr

quote:

and also for this line:

float dLeft = -D3DXVec3Dot(&cam_pos,&tnl);

for cam_pos, I can just use the 3 matrix values we zero out before (store them in cam_pos before I zero them out) right? or do I need to use a 0,0,0 value here?



The cam_pos that you send to the dotproduct must be the cameras position in world coordinates. It is not that easy to obtain the camera position from the view matrix, it can be done but it is better to store it in a variable.

quote:

And lastly, the normals are created in view space, then multiplied by the inverse of the vew matrix, so basically we putting them into world space (but without the translation part?), so when I plug in the xyz point to solve the plane equation this point needs to be in world space?



Yes the points that you check against the planes we have computed are in world coordinates.

quote:

The frustrum is for some reason diffucult to me to understand, this is my current mental picture =)

It all starts with a pyramid where your eyes are, also referred to as the camera "position", in view space, this point is represented by the translation part of the view matrix, it then extends towards the screen passing thru the 4 corners all the way back to your back clipping plane. The bigger the fov is the closer the eye point gets to the screen and the wider the frustrum becomes, for an fov of 180 the eye would acctualy end up right ON the screen (???) but then this thing is no longer a pyramid more like a rectange (???)



Correct

quote:

Thanks,
Rick




- WitchLord

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

All working great now, thanks much! What the problem was had nothing to do with this code directly ... I replaced my old (but working) camera code with the quaternion camera code that I found on the tentacle sample of D3DX, for some reason it produces apparent correct visual results however the view matrix it makes it''s not good for this I don''t know why, so I put my old camera code back in and works like charm, to simplify things I desided to work with the front normal 0,0,1 (which should be the same as the camera''s look vector) this only tells me if a point is in front of behind the camera but it should work fine when I add the rest of the normals unless I mess up the normal calculation, still a bit unclear on the fov, if you have time please answer this:

float aspect = 1.33;
float fov = toradian(90);

setup_projection( blah blah fov, aspect, blah blah)

fovy = fov/2;
fovx = 2*atan(aspect*tan(fovy) )

then use fovy and fovx to calculate the normals, exept that I dont need to divide by 2 anymore, correct? =)

Thanks,
Rick



You can use these to compute the normals:

HalfFovY = FovY/2;
HalfFovX = todegree(atan(1.33*tan(toradian(HalfFovY)));





- WitchLord

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I dont understand why you convert this back into degrees, don''t cos and sin expect the angles in radians?

Thanks,
Rick

This topic is closed to new replies.

Advertisement