Hi guys, I have a little maths problem and I’d like some help.
I decided to have a go at LWJGL, and after some basic setting up stuff, I’m now trying to implement a view culling algorithm. I have some OpenGL tutorials in my hands, but no code, so this is what I tried to do:
private final static int RIGHT_PLANE = 0;
private final static int LEFT_PLANE = 4;
private final static int TOP_PLANE = 8;
private final static int BOTTOM_PLANE = 12;
private final static int NEAR_PLANE = 16;
private final static int FAR_PLANE = 20;
private double[] frustrum;
// Computes the frustrum plane equations
public void computeFrustrum() {
gl.loadIdentity();
// Camera Transformation
gl.translatef(0.0f, 0.0f, camZ);
gl.rotatef(camRotX, 1.0f, 0.0f, 0.0f);
// Interest Transformation
gl.rotatef(intRotY, 0.0f, 1.0f, 0.0f);
gl.translatef(intX, intY, intZ);
// Get ModelView Matrix
BufferCache.loadMatrix(GL.MODELVIEW_MATRIX);
matrix.set(BufferCache.matrix);
// Multiply by Projection Matrix
matrix.mul(EngineGraph.PROJECT_MATRIX);
// Right
frustrum[0] = matrix.m03-matrix.m00;
frustrum[1] = matrix.m13-matrix.m10;
frustrum[2] = matrix.m23-matrix.m20;
frustrum[3] = matrix.m33-matrix.m30;
// Left
frustrum[4] = matrix.m03+matrix.m00;
frustrum[5] = matrix.m13+matrix.m10;
frustrum[6] = matrix.m23+matrix.m20;
frustrum[7] = matrix.m33+matrix.m30;
// Top
frustrum[8] = matrix.m03-matrix.m01;
frustrum[9] = matrix.m13-matrix.m11;
frustrum[10] = matrix.m23-matrix.m21;
frustrum[11] = matrix.m33-matrix.m31;
// Bottom
frustrum[12] = matrix.m01+matrix.m03;
frustrum[13] = matrix.m11+matrix.m13;
frustrum[14] = matrix.m21+matrix.m23;
frustrum[15] = matrix.m31+matrix.m33;
// Near
frustrum[16] = matrix.m02-matrix.m03;
frustrum[17] = matrix.m12-matrix.m13;
frustrum[18] = matrix.m22-matrix.m23;
frustrum[19] = matrix.m32-matrix.m33;
// Far
frustrum[20] = matrix.m03-matrix.m02;
frustrum[21] = matrix.m13-matrix.m12;
frustrum[22] = matrix.m23-matrix.m22;
frustrum[23] = matrix.m33-matrix.m32;
}
// Returns true when point is within the view
public boolean isVisible(float x, float y, float z) {
if ( visibleInPlane(RIGHT_PLANE, x, y, z)
&& visibleInPlane(LEFT_PLANE, x, y, z)
&& visibleInPlane(TOP_PLANE, x, y, z)
&& visibleInPlane(BOTTOM_PLANE, x, y, z)
&& !visibleInPlane(NEAR_PLANE, x, y, z)
&& visibleInPlane(FAR_PLANE, x, y, z) )
return true;
else
return false;
}
// Returns true if the point is "inside" the plane
private boolean visibleInPlane(int plane, float x, float y, float z) {
double xc = frustrum[plane++] * x;
double yc = frustrum[plane++] * y;
double zc = frustrum[plane++] * z;
double wc = frustrum[plane];
if ( -wc < xc && xc < wc && -wc < yc && yc < wc && -wc < zc && zc < wc )
return true;
else
return false;
}
It works pretty nice, but I don’t know why I have to put that ! in front of the near plane comparison (it works that way, I just can’t understand why it doesn’t without it ???). And there is a problem with the bottom plane. When the view looks straight down the y axis or straight forward, down the z axis, it works correctly, but at other angles it fails. It returns false even when the point is just below the middle of the screen, or lower depending on the view angle.
I’m not very good at math, but I think I implemented what I read in the tutorials properly. I just can’t see where the problem is. Any hints people?
- Any comments on the algo itself will be appreciated (I’m not even sure if it is a “decent” way to do it). And of course suggestions for making it better.
Spasi