Archived

This topic is now archived and is closed to further replies.

clipping planes

This topic is 5699 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

Let''s say you have a 3D perspective mode with FOV set to 45. How do you calculate the corresponding 6 clipping planes, and how do you store them? Also, how would you use them to reject points which is not in view?

Share this post


Link to post
Share on other sites
The near and far clipping planes should be clear (just store their distance to (0,0,0).

There are some ways to store the other four cliping planes. I suppose, the simples way is to store their normals (a vector that is orthogonal to the plane). With a FOV of 45 (both, horizontally and vertically), this might be (1, 0, 1), (-1, 0, 1), (0, 1, 1) and (0, -1, 1)...
If you want to test whether a point is inside, you calculate the dot product with every normal. Which is defined as
(a, b, c) * (x, y, z) = a*x + b*y + c*z
This calculates the "length" of one vector in the direction of the other (if you get what I mean...) If the result is negative, the point was on the other side of the plane, and may be rejected.
Example:
(-1, 0, 2) is inside, as (1, 0, 1)*(-1, 0, 2) = 1
(-2, 0, 2) is at the border, as (1, 0, 1)*(-2, 0, 2) = 0
(-3, 0, 2) is outside, as (1, 0, 1)*(-3, 0 , 2) = -1
This must be done for every plane, of course.

Share this post


Link to post
Share on other sites
Easier and faster is the following check:
multiply the camera viewing direction vector with each vector (camera - vertex you want to check whether in view or not). Result is cos angle between these vectors, so if this angle is < FoV angle, it is in view. You do this for xy plane (check for FoV angle) and xz plane separately (FoV angle adapted to screenwidth/height relation)

=> 2 2D multiplications per vertex for cull check

- thomas

[edited by - Renus on May 3, 2002 8:49:19 AM]

Share this post


Link to post
Share on other sites
If I am not wrong, you will get cos(angle)*length of the vector.
So you must divide through the length of your vector before you do the angle check (or multiply the angle with the length).In any way, you will have to calculate a sqrt(). Or does it work without a sqrt() in any way?

Share this post


Link to post
Share on other sites
Yes, you are right, I forgot to mention to normalize the vector (the direction vector of your camera should be already normalized). IN fact, an "original" sqrt() is not necessary, a approximated will do (see source codes of major companies on this..) This normalized vector is used for several tasks, so I had it before.

Here is my complete code of point-in-frustum:


  
bool OBViewFrustum::PointInFrustum( const vec3 vertex, bool expectInView, const vec3 normCamToObj ) const
{
if( expectInView )
{
// object was in view, so will probably still be now

// do rough test: angle between camera viewing dir and camToObj < FOV/2

// this handles appr. 90%

if( BLMath::Vec3Prod( camViewDir_, normCamToObj ) > cosHalfFov_ )
return true;
}
else
{
// object was not in view test roughly with diagonal angle

// this handles appr. 90%

if( BLMath::Vec3Prod( camViewDir_, normCamToObj ) < cosHalfFovDiagonal_ )
return false;
}

// following code is just executed if rough tests didnt succeed

// do now exact test: project vertex to camera axis'', check hori- and vert. angle separatly

float rightProj = BLMath::Fabs( BLMath::Vec3Prod( camRightDir_, normCamToObj ) );
float viewProj = BLMath::Fabs( BLMath::Vec3Prod( camViewDir_, normCamToObj ) );
if( (rightProj/viewProj) > tanHalfFovH_ ) // check horizontal angle

return false;

float upProj = BLMath::Fabs( BLMath::Vec3Prod( camUpDir_, normCamToObj ) );
return upProj < tanHalfFovH_ * viewProj; // check vertical angle

}


Compared to the 6-plane-solutions the gurus do, its much faster. Anyway, this part won''t touch the bottleneck of your engine too much, so its not worth to re-implement current solutions.



- thomas

Share this post


Link to post
Share on other sites
Thanx a lot guys, that really helped. But, also it made me come up with a related question: Do I have to recalculate my perspective clipping planes every time my camera moves or rotates? Or is it enough to inv-rotate and inv-move the whole scene, based on the camera matrix?

Share this post


Link to post
Share on other sites
This is indeed the idea of a camera matrix (I think). You noramlly do not calculate the transformation for the camera in the matrix, but its inverse. And then you multiply it with all of your vertices and thus get a pseudo-camera that is always positioned at position (0,0,0), pointing in z direction.

Renus: I believe that there is a faster way. You may change your transformation matrix so that you get a 90° FOV (by stretching your world correctly). You of course have to modify your multiplication constants after perspective projection to get the real FOV. The advantage of a 90° FOV is that you will only have a test like fabs(x) < z to test for left and right clipping plane. The same for top and bottom. This way you save 3 Multiplications and 2 Additions with no(?) additional work (except for calculating the slightly more difficult transformation matrix).
Another thing: I don´t think that your compiler changes
(rightProj/viewProj) > tanHalfFovH_
to
rightProj > tanHalfFovH_ * viewProj
which is about 10-20 times faster on a common FPU (fmul vs. fdiv), as he cannot know that viewProj is positive. Oh yes, you did it correctly in the check for vertical angle, why not for horizontal angle?

But as you mentioned: This is in most cases not the bottleneck, so you should better use a simple approach. Btw. the algo is not by me. I believe I read it in HUGI mag. (http://www.hugi.de).

Share this post


Link to post
Share on other sites
A 90° FOV seems not acceptable since it must be flexible for binoculars and similar effects.
Regarding the division your are right, thanks.

Before putting more energy in this cullcheck we should note that a good PVS algo will need no culling at all, I dont use the cull check (you may ask why I wrote it - just because I didnt design enough



- thomas

Share this post


Link to post
Share on other sites