Calculating frustum planes from arbitrary position/rotation [FIXED]

Started by
1 comment, last by smidge_tech 19 years, 6 months ago
Hi all, I have a Viewer class, which represents some entity capable of seeing things within my program's world. I'm trying to add some functions to calculate and perform tests on a viewer's frustum. Each viewer has its own information like fov, near/far plane distance, and aspect ratio. I've almost got everything working the way I want it, however some weird things happen: * I've checked all the values, but the frustum appears pointing out of the viewer's back, rather than in front. * The shape of the frustum appears to change as the viewer rotates about the Y (up) axis. I'm using OpenGL, however I am working in a coordinate system where the positive direction of the Z axis points into the screen, rather than out. This might be messing up some of the transformations... I calculate the frustum planes as follows: * Define the frustum planes in camera space. * Use OpenGL to do some transformations to bring camera space to world space. * Extract the matrix, and premultiply the 4-dimensional frustum vectors by it. * Normalise. To render the frustum, I'm finding the corners of the frustum by testing the intersection of 3 of the frustum planes, e.g. to get the near-top-left corner, I find the coordinates of intersection of the near, top, and left frustum planes. Like I say, it nearly works! But not quite. Perhaps some frustum-gurus have some advice for me? I've examined the plane normals, and they are most definitely correct in all the cases I've tried. I think it might be the D values that are messing up. Here's the frustum-plane calculating code: Few things to note: * e is calculated as 1 / tan(fovX), where fovX is the horizontal fov. * aspect is 0.75, in most cases. * One of the rotation lines is rot[1] - 90 rather than rot[1] because of the way I want my angles to point. This works.

// Precalculate frustum planes, from the viewer's position and orientation.
void Viewer::updateFrustumPlanes()
{
	// In camera coordinate space, the planes are easy to specify.
	// They are stored in the order near, far, left, right, bottom, top.
	float f[6][4];
	vec4Set(f[0], 0, 0, 1, near);
	vec4Set(f[1], 0, 0, -1, -far);
	vec4Set(f[2], e, 0, 1, 0);
	vec4Set(f[3], -e, 0, 1, 0);
	vec4Set(f[4], 0, e, aspect, 0);
	vec4Set(f[5], 0, -e, aspect, 0);
	
	// Now we must transform the planes from camera space to world space.
	glPushMatrix();
	glLoadIdentity();
	// Perform the transformations.
	glRotatef(rot[0],         1.0f, 0.0f, 0.0f);
	glRotatef(rot[1] - 90.0f, 0.0f, 1.0f, 0.0f);
	glRotatef(rot[2],         0.0f, 0.0f, 1.0f);
	glTranslatef(-pos[0], -pos[1], -pos[2]);
	// Store the current matrix.
	float m[16];
	glGetFloatv(GL_MODELVIEW_MATRIX, m);
	glPopMatrix();
	
	// Treating each plane as a 4-dimensional vector, transform each one by
	// the matrix we just saved to get the planes' coordinates in world space.
	for (int i = 0; i < 6; ++i)
	{
		frustum[0] =
			m[0] * f[0] + m[1] * f[1] + m[2] * f[2] + m[3] * f[3];
		frustum[1] =
			m[4] * f[0] + m[5] * f[1] + m[6] * f[2] + m[7] * f[3];
		frustum[2] =
			m[8] * f[0] + m[9] * f[1] + m[10] * f[2] + m[11] * f[3];
		frustum[3] =
			m[12] * f[0] + m[13] * f[1] + m[14] * f[2] + m[15] * f[3];
	}
	
	// Normalise the vectors.
	for (int i = 0; i < 6; ++i)
		vec3Normalise(frustum);
}



Oh, I also posted this to flipcode too. Hope that kind of cross-posting doesn't offend anybody :). [Edited by - smidge on October 25, 2004 11:16:41 AM]
--Mr Smidge
Advertisement
Ok, I'm lazy so I didn't read the whole message, from the topic I think you want that : http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf

Extracting View Frustum Planes from the Camera matrix.
-* So many things to do, so little time to spend. *-
Quote:Original post by Ingenu
Ok, I'm lazy so I didn't read the whole message, from the topic I think you want that : http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf

Extracting View Frustum Planes from the Camera matrix.


Yes, that's not quite what I'm after - that article deals with extracting frustum planes from the existing projection matrix; however, I'm working with arbitrary camera coordinates and orientation, and don't want to have to alter the projection matrix each time I calculate something.

But not to worry, I fixed it the problem:

This:

vec4Set(f[0], 0, 0, 1, near);
vec4Set(f[1], 0, 0, -1, -far);

.. should have been this:

vec4Set(f[0], 0, 0, 1, -near);
vec4Set(f[1], 0, 0, -1, far);

(silly mistake)

And the problem with the frustum changing shape, I noticed, made the d values of the top and bottom plane scale incorrectly with the other d values (in fact, they scaled at a ratio the same as the aspect ratio).

Normalising the f plane normals before transforming fixed that. All working nicely now.
--Mr Smidge

This topic is closed to new replies.

Advertisement