Frustum Culling - Scene gets culled from wrong pov!

Started by tobiaspc, March 28, 2012, 14:41:38

Previous topic - Next topic

tobiaspc

Hello,

i´m currently implementing frustum culling and having problems with getting the projections matrix:

glMatrixMode(GL_PROJECTION);
			glLoadIdentity();// reset


so the matrix should be like this one: link

but i´m printing it out and i get only null bytes:


//Get the ModelView matrix
			ByteBuffer projMatrixBuffer = ByteBuffer.allocateDirect(16*4);
			
			glGetFloat(GL_PROJECTION, projMatrixBuffer.asFloatBuffer());
			//float[] modelViewMatrixArray = new float[16];
			for(int i = 0;i<16*4;i++)
			{
				//modelViewMatrixArray[i] = projViewMatrixBuffer.getFloat(i);
				System.out.println(projMatrixBuffer.get(i) + " i: " + i);
			}


output:
0 i: 0
0 i: 1
0 i: 2
...
0 i: 62
0 i: 63


then, i´m setting up my frustum with
float ratio = ((float)Display.getDisplayMode().getWidth())/((float)Display.getDisplayMode().getHeight());
			float fov = 45.0f;
			float near = 1;
			float far = 1000;
			float top = (float) (near*Math.tan(Math.PI/180*fov/2));
			float bottom = -top;
			float right = ratio*top;
			float left = -right;
			glFrustum(left, right, bottom, top, near, far);


and printing out the matrix again, same as above, only zeros. After that, i look through my camera:
  public void lookThrough()
    {
    	
        //roatate the pitch around the X axis
        GL11.glRotatef(pitch, 1.0f, 0.0f, 0.0f);
        //roatate the yaw around the Y axis
        GL11.glRotatef(yaw, 0.0f, 1.0f, 0.0f);
        //translate to the position vector's location
        GL11.glTranslatef(-position.x, -position.y, -position.z);
    }


and render my stuff. i can move the camera with WASD+mouse and getting a great view over my scene, but i need this matrix for frustum culling.

Any ideas?

Riven

There are two bugs:

1. you forgot to set the byteOrder: projMatrixBuffer.byteOrder(ByteOrder.nativeOrder())
2. you passed the wrong parameter to glGetFloat(GL_PROJECTION_MATRIX not GL_PROJECTION, ...)

tobiaspc

thank you! soo now i´m getting the matricies. this gets called every frame
projectionMatrixBuffer.order(ByteOrder.nativeOrder());
		glGetFloat(GL_PROJECTION_MATRIX, projectionMatrixBuffer.asFloatBuffer());
		
		for(int i = 0;i<16;i++)
		{
			projectionMatrixArray[i] = projectionMatrixBuffer.asFloatBuffer().get(i);
			//System.out.println(i + " " + projectionMatrixBuffer.asFloatBuffer().get(i) );
		}
		
		modelViewMatrixBuffer.order(ByteOrder.nativeOrder());
		glGetFloat(GL_MODELVIEW_MATRIX, modelViewMatrixBuffer.asFloatBuffer());
		
		for(int i = 0;i<16;i++)
		{
			modelViewMatrixArray[i] = modelViewMatrixBuffer.asFloatBuffer().get(i);
			//System.out.println(i + "2 " + modelViewMatrixBuffer.asFloatBuffer().get(i) );
		}


and the multiply both:
  // Combine the two matrices (multiply projection by modelview) 
		   modelViewProjectionMatrixArray[ 0] = modelViewMatrixArray[ 0] * projectionMatrixArray[ 0] + modelViewMatrixArray[ 1] * projectionMatrixArray[ 4] + modelViewMatrixArray[ 2] * projectionMatrixArray[ 8] + modelViewMatrixArray[ 3] * projectionMatrixArray[12];
		   modelViewProjectionMatrixArray[ 1] = modelViewMatrixArray[ 0] * projectionMatrixArray[ 1] + modelViewMatrixArray[ 1] * projectionMatrixArray[ 5] + modelViewMatrixArray[ 2] * projectionMatrixArray[ 9] + modelViewMatrixArray[ 3] * projectionMatrixArray[13];
		   modelViewProjectionMatrixArray[ 2] = modelViewMatrixArray[ 0] * projectionMatrixArray[ 2] + modelViewMatrixArray[ 1] * projectionMatrixArray[ 6] + modelViewMatrixArray[ 2] * projectionMatrixArray[10] + modelViewMatrixArray[ 3] * projectionMatrixArray[14];
		   modelViewProjectionMatrixArray[ 3] = modelViewMatrixArray[ 0] * projectionMatrixArray[ 3] + modelViewMatrixArray[ 1] * projectionMatrixArray[ 7] + modelViewMatrixArray[ 2] * projectionMatrixArray[11] + modelViewMatrixArray[ 3] * projectionMatrixArray[15];

		   modelViewProjectionMatrixArray[ 4] = modelViewMatrixArray[ 4] * projectionMatrixArray[ 0] + modelViewMatrixArray[ 5] * projectionMatrixArray[ 4] + modelViewMatrixArray[ 6] * projectionMatrixArray[ 8] + modelViewMatrixArray[ 7] * projectionMatrixArray[12];
		   modelViewProjectionMatrixArray[ 5] = modelViewMatrixArray[ 4] * projectionMatrixArray[ 1] + modelViewMatrixArray[ 5] * projectionMatrixArray[ 5] + modelViewMatrixArray[ 6] * projectionMatrixArray[ 9] + modelViewMatrixArray[ 7] * projectionMatrixArray[13];
		   modelViewProjectionMatrixArray[ 6] = modelViewMatrixArray[ 4] * projectionMatrixArray[ 2] + modelViewMatrixArray[ 5] * projectionMatrixArray[ 6] + modelViewMatrixArray[ 6] * projectionMatrixArray[10] + modelViewMatrixArray[ 7] * projectionMatrixArray[14];
		   modelViewProjectionMatrixArray[ 7] = modelViewMatrixArray[ 4] * projectionMatrixArray[ 3] + modelViewMatrixArray[ 5] * projectionMatrixArray[ 7] + modelViewMatrixArray[ 6] * projectionMatrixArray[11] + modelViewMatrixArray[ 7] * projectionMatrixArray[15];

		   modelViewProjectionMatrixArray[ 8] = modelViewMatrixArray[ 8] * projectionMatrixArray[ 0] + modelViewMatrixArray[ 9] * projectionMatrixArray[ 4] + modelViewMatrixArray[10] * projectionMatrixArray[ 8] + modelViewMatrixArray[11] * projectionMatrixArray[12];
		   modelViewProjectionMatrixArray[ 9] = modelViewMatrixArray[ 8] * projectionMatrixArray[ 1] + modelViewMatrixArray[ 9] * projectionMatrixArray[ 5] + modelViewMatrixArray[10] * projectionMatrixArray[ 9] + modelViewMatrixArray[11] * projectionMatrixArray[13];
		   modelViewProjectionMatrixArray[10] = modelViewMatrixArray[ 8] * projectionMatrixArray[ 2] + modelViewMatrixArray[ 9] * projectionMatrixArray[ 6] + modelViewMatrixArray[10] * projectionMatrixArray[10] + modelViewMatrixArray[11] * projectionMatrixArray[14];
		   modelViewProjectionMatrixArray[11] = modelViewMatrixArray[ 8] * projectionMatrixArray[ 3] + modelViewMatrixArray[ 9] * projectionMatrixArray[ 7] + modelViewMatrixArray[10] * projectionMatrixArray[11] + modelViewMatrixArray[11] * projectionMatrixArray[15];

		   modelViewProjectionMatrixArray[12] = modelViewMatrixArray[12] * projectionMatrixArray[ 0] + modelViewMatrixArray[13] * projectionMatrixArray[ 4] + modelViewMatrixArray[14] * projectionMatrixArray[ 8] + modelViewMatrixArray[15] * projectionMatrixArray[12];
		   modelViewProjectionMatrixArray[13] = modelViewMatrixArray[12] * projectionMatrixArray[ 1] + modelViewMatrixArray[13] * projectionMatrixArray[ 5] + modelViewMatrixArray[14] * projectionMatrixArray[ 9] + modelViewMatrixArray[15] * projectionMatrixArray[13];
		   modelViewProjectionMatrixArray[14] = modelViewMatrixArray[12] * projectionMatrixArray[ 2] + modelViewMatrixArray[13] * projectionMatrixArray[ 6] + modelViewMatrixArray[14] * projectionMatrixArray[10] + modelViewMatrixArray[15] * projectionMatrixArray[14];
		   modelViewProjectionMatrixArray[15] = modelViewMatrixArray[12] * projectionMatrixArray[ 3] + modelViewMatrixArray[13] * projectionMatrixArray[ 7] + modelViewMatrixArray[14] * projectionMatrixArray[11] + modelViewMatrixArray[15] * projectionMatrixArray[15];


printing out all three:
modelView
1D-Array(16) entries

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
-0.71648437 0.36998308 -0.5914074 0.0 0.0 0.8477705 0.53036326 0.0 0.69760317 0.379997 -0.6074143 0.0 1.8881226 -159.77505 66.84585 1.0 
projection
1D-Array(16) entries

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
1.8106601 0.0 0.0 0.0 0.0 2.4142134 0.0 0.0 0.0 0.0 -1.002002 -1.0 0.0 0.0 -2.002002 0.0 
modelViewProjection
1D-Array(16) entries

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
-1.2973096 0.8932181 0.5925914 0.5914074 0.0 2.046699 -0.53142506 -0.53036326 1.2631222 0.9173938 0.60863036 0.6074143 3.4187481 -385.73108 -68.981674 -66.84585


after that, i set the matrix in my frustum class
public static void setMatrix(float[] matrix)
	{
		for(int i = 0;i < 4;i++)
		{
			for(int i2 = 0;i2 < 4;i2++)
			{
				//System.out.println(matrix[i*4 + i2]);
				MVPMatrix[i][i2] = matrix[i*4 + i2];
				//System.out.println(MVPMatrix2[i][i2]);
				//System.out.println("i: " + i + " i2: " + i2 + " formula: " + ((i*4) + i2));
			}	
		}
		updatePlanes(matrix);
	}


updatePlanes() extracs the planes:
public static void updatePlanes(float[] matrix)
	{
		// The equation for a plane is: Ax + By + Cz + D = 0, where A, B and C define the plane's normal vector, D is the distance from the origin to the plane,
		// and x, y and z are any points on the plane.. You can plug any point into the equation and if the result is 0 then the point lies on the plane. If the
		// result is greater than 0 then the point is in front of the plane, and if it's negative the point is behind the plane.
		/* Extract the numbers for the RIGHT plane */
		
		   frustumPlanes[0][0] = matrix[ 3] - matrix[ 0];
		   frustumPlanes[0][1] = matrix[ 7] - matrix[ 4];
		   frustumPlanes[0][2] = matrix[11] - matrix[ 8];
		   frustumPlanes[0][3] = matrix[15] - matrix[12];

		   /* Normalize the result */
		   float t = (float) Math.sqrt( frustumPlanes[0][0] * frustumPlanes[0][0] + frustumPlanes[0][1] * frustumPlanes[0][1] + frustumPlanes[0][2] * frustumPlanes[0][2] );
		   frustumPlanes[0][0] /= t;
		   frustumPlanes[0][1] /= t;
		   frustumPlanes[0][2] /= t;
		   frustumPlanes[0][3] /= t;

		   /* Extract the numbers for the LEFT plane */
		   frustumPlanes[1][0] = matrix[ 3] + matrix[ 0];
		   frustumPlanes[1][1] = matrix[ 7] + matrix[ 4];
		   frustumPlanes[1][2] = matrix[11] + matrix[ 8];
		   frustumPlanes[1][3] = matrix[15] + matrix[12];

		   /* Normalize the result */
		   t = (float) Math.sqrt( frustumPlanes[1][0] * frustumPlanes[1][0] + frustumPlanes[1][1] * frustumPlanes[1][1] + frustumPlanes[1][2] * frustumPlanes[1][2] );
		   frustumPlanes[1][0] /= t;
		   frustumPlanes[1][1] /= t;
		   frustumPlanes[1][2] /= t;
		   frustumPlanes[1][3] /= t;

		   /* Extract the BOTTOM plane */
		   frustumPlanes[2][0] = matrix[ 3] + matrix[ 1];
		   frustumPlanes[2][1] = matrix[ 7] + matrix[ 5];
		   frustumPlanes[2][2] = matrix[11] + matrix[ 9];
		   frustumPlanes[2][3] = matrix[15] + matrix[13];

		   /* Normalize the result */
		   t = (float) Math.sqrt( frustumPlanes[2][0] * frustumPlanes[2][0] + frustumPlanes[2][1] * frustumPlanes[2][1] + frustumPlanes[2][2] * frustumPlanes[2][2] );
		   frustumPlanes[2][0] /= t;
		   frustumPlanes[2][1] /= t;
		   frustumPlanes[2][2] /= t;
		   frustumPlanes[2][3] /= t;

		   /* Extract the TOP plane */
		   frustumPlanes[3][0] = matrix[ 3] - matrix[ 1];
		   frustumPlanes[3][1] = matrix[ 7] - matrix[ 5];
		   frustumPlanes[3][2] = matrix[11] - matrix[ 9];
		   frustumPlanes[3][3] = matrix[15] - matrix[13];

		   /* Normalize the result */
		   t = (float) Math.sqrt( frustumPlanes[3][0] * frustumPlanes[3][0] + frustumPlanes[3][1] * frustumPlanes[3][1] + frustumPlanes[3][2] * frustumPlanes[3][2] );
		   frustumPlanes[3][0] /= t;
		   frustumPlanes[3][1] /= t;
		   frustumPlanes[3][2] /= t;
		   frustumPlanes[3][3] /= t;

		   /* Extract the FAR plane */
		   frustumPlanes[4][0] = matrix[ 3] - matrix[ 2];
		   frustumPlanes[4][1] = matrix[ 7] - matrix[ 6];
		   frustumPlanes[4][2] = matrix[11] - matrix[10];
		   frustumPlanes[4][3] = matrix[15] - matrix[14];

		   /* Normalize the result */
		   t = (float) Math.sqrt( frustumPlanes[4][0] * frustumPlanes[4][0] + frustumPlanes[4][1] * frustumPlanes[4][1] + frustumPlanes[4][2] * frustumPlanes[4][2] );
		   frustumPlanes[4][0] /= t;
		   frustumPlanes[4][1] /= t;
		   frustumPlanes[4][2] /= t;
		   frustumPlanes[4][3] /= t;

		   /* Extract the NEAR plane */
		   frustumPlanes[5][0] = matrix[ 3] + matrix[ 2];
		   frustumPlanes[5][1] = matrix[ 7] + matrix[ 6];
		   frustumPlanes[5][2] = matrix[11] + matrix[10];
		   frustumPlanes[5][3] = matrix[15] + matrix[14];

		   /* Normalize the result */
		   t = (float) Math.sqrt( frustumPlanes[5][0] * frustumPlanes[5][0] + frustumPlanes[5][1] * frustumPlanes[5][1] + frustumPlanes[5][2] * frustumPlanes[5][2] );
		   frustumPlanes[5][0] /= t;
		   frustumPlanes[5][1] /= t;
		   frustumPlanes[5][2] /= t;
		   frustumPlanes[5][3] /= t;

	}


in my render loop i test if my plane is inside:
 	    	if(renderFrustumManager.sphereInFrustum(xloop, yloop, gameTerrainGenerator.heightmap[xloop][yloop],1))
                        {


but i get weird results:


EDIT: it seems that everything gets culled from a wrong point. The point is ~at x=200 y=100 z=0.
EDIT2: left & right culling is ok, but near/far/top/bottom doesnt work...
EDIT3: finally figured out what was wrong:
had to change this:
public boolean sphereInFrustum(float x, float y, float z, float radius)
	{
		   if( frustumPlanes[0][0] * x + frustumPlanes[0][1] * y + frustumPlanes[0][2] * z + frustumPlanes[0][3] <= -radius )
		   {
		         return false;
		   }
...


to this:
public boolean sphereInFrustum(float x, float y, float z, float radius)
	{
		   if( frustumPlanes[0][0] * x + frustumPlanes[0][1] * z + frustumPlanes[0][2] * y + frustumPlanes[0][3] <= -radius )
		   {
		         return false;
		   }
...


--> flip z/y coords