Help end child hunger

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”

  1. 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;

  2. 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

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: