Radar Approach – Implementation
Prev: Testing Points II | Next: Testing Spheres |
A class to implement the frustum functionality based on the radar approach is now presented. Note that the code itself is not optimized in any way, as the goal is only to serve as the tutorial companion. As opposed to the previous implementations, this class contains only the required data to make it work.
The class header file
class FrustumR{ public: static enum {OUTSIDE, INTERSECT, INSIDE}; Vec3 cc; // camera position Vec3 X,Y,Z; // the camera referential float nearD, farD, width, height; FrustumR::FrustumR(); FrustumR::~FrustumR(); void setCamInternals(float angle, float ratio, float nearD, float farD); void setCamDef(Vec3 &p, Vec3 &l, Vec3 &u); int pointInFrustum(Vec3 &p); };
The Methods: setCamInternals
This function takes exactly the same parameters as the function gluPerspective
. Each time the perspective definitions change, for instance when a window is resized, this function should be called as well.
#define ANG2RAD 3.14159265358979323846/180.0 void FrustumR::setCamInternals(float angle, float ratio, float nearD, float farD) { // store the information this->ratio = ratio; this->nearD = nearD; this->farD = farD; // compute width and height of the near section tang = (float)tan(ANG2RAD * angle * 0.5) ; heigth = nearD * tang; width = height * ratio; }
The function stores all the information, and computes the width and height of the rectangular sections of the near plane and stores them in height (near height) and width (near width).
The Methods: setCamDef
This function takes three vectors that contain the information for the gluLookAt
function: the position of the camera, a point to where the camera is pointing and the up vector. Each time the camera position or orientation changes, this function should be called as well. Notice how the following function is much simpler than for the other methods of view frustum culling. There is no need to compute the planes anymore.
void FrustumR::setCamDef(Vec3 &p, Vec3 &l, Vec3 &u) { cc = p.copy(); // compute the Z axis of the camera referential // this axis points in the same direction from // the looking direction Z = l - p; Z.normalize(); // X axis of camera is the cross product of Z axis and given "up" vector X = Z * u; X.normalize(); // the real "up" vector is the cross product of X and Z Y = X * Z; }
The Methods: pointInFrustum
Testing a point is also much simpler and more efficient:
int FrustumR::pointInFrustum(Vec3 &p) { float pcz,pcx,pcy,aux; // compute vector from camera position to p Vec3 v = p-camPos; // compute and test the Z coordinate pcz = v.innerProduct(-Z); if (pcz > farD || pcz < nearD) return(OUTSIDE); // compute and test the Y coordinate pcy = v.innerProduct(Y); aux = pcz * tang; if (pcy > aux || pcy < -aux) return(OUTSIDE); // compute and test the X coordinate pcx = v.innerProduct(X); aux = aux * ratio; if (pcx > aux || pcx < -aux) return(OUTSIDE); return(INSIDE); }
Prev: Testing Points II | Next: Testing Spheres |
4 Responses to “Radar Approach – Implementation”
Leave a Reply Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
In you setCamDef(Vec3 &p, Vec3 &l, Vec3 &u) method you should write somewhere that there are cross product multiplications, when you compute X and Y
// X axis of camera with given “up” vector and Z axis |->here shuld be cross
X = Z * u;
X.normalize();
// the real “up” vector is the dot product of X and Z |->here shuld be cross
Y = X * Z;
Yes, I meant cross, not dot. Fixed it. Thanks for pointing it out.
Am I correct in assuming that
pcz = v.innerProduct(-Z);
is -Z because of right-handedness of your example?
So If I were to try this in left-handed I should use Z instead of -Z
Actually, that is already OpenGL code.