Frustum clipping issues

Started by CJLetsGame, March 31, 2014, 23:48:45

Previous topic - Next topic

CJLetsGame

Images attached below.

The right and top bounds of the frustum seem to be working correctly, however the further left/up I look, the more the cubes that are supposed to be visible are clipped.
The first image isn't clipping any visible cubes just as expected.
Right now Im using a Frustum class(slightly modified) I found online as well as a Camera class I found online.

Frustum original:
http://www.java-gaming.org/index.php?action=pastebin&hex=83b53604950

Frustum Modified code
   public void calculateFrustum(Camera cam)
    {    
            float[] proj = new float[16];           // This will hold our projection matrix
            float[] modl = new float[16];           // This will hold our modelview matrix
            float[] clip = new float[16];           // This will hold the clipping planes


            // glGetFloat() is used to extract information about our OpenGL world.
            // Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
            // It then stores the matrix into an array of [16].
            proj_b.rewind();
            cam.getProjectionMatrix().store(proj_b);
            //GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, proj_b);
            proj_b.rewind();
            proj_b.get(proj);

            // By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
            // This also stores it in an array of [16].
            modl_b.rewind();
            //new Matrix4f().store(modl_b);
            cam.getViewMatrix().store(modl_b);
            //GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modl_b);
            modl_b.rewind(); 
            modl_b.get(modl);

            // Now that we have our modelview and projection matrix, if we combine these 2 matrices,
            // it will give us our clipping planes.  To combine 2 matrices, we multiply them.
            
            clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
            clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
            clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
            clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];

            clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
            clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
            clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
            clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];

            clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
            clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
            clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
            clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];

            clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
            clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
            clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
            clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
            
            // Now we actually want to get the sides of the frustum.  To do this we take
            // the clipping planes we received above and extract the sides from them.

            // This will extract the RIGHT side of the frustum
            m_Frustum[RIGHT][A] = clip[ 3] - clip[ 0];
            m_Frustum[RIGHT][B] = clip[ 7] - clip[ 4];
            m_Frustum[RIGHT][C] = clip[11] - clip[ 8];
            m_Frustum[RIGHT][D] = clip[15] - clip[12];

            // Now that we have a normal (A,B,C) and a distance (D) to the plane,
            // we want to normalize that normal and distance.

            // Normalize the RIGHT side
            normalizePlane(m_Frustum, RIGHT);

            // This will extract the LEFT side of the frustum
            m_Frustum[LEFT][A] = clip[ 3] + clip[ 0];
            m_Frustum[LEFT][B] = clip[ 7] + clip[ 4];
            m_Frustum[LEFT][C] = clip[11] + clip[ 8];
            m_Frustum[LEFT][D] = clip[15] + clip[12];

            // Normalize the LEFT side
            normalizePlane(m_Frustum, LEFT);

            // This will extract the BOTTOM side of the frustum
            m_Frustum[BOTTOM][A] = clip[ 3] + clip[ 1];
            m_Frustum[BOTTOM][B] = clip[ 7] + clip[ 5];
            m_Frustum[BOTTOM][C] = clip[11] + clip[ 9];
            m_Frustum[BOTTOM][D] = clip[15] + clip[13];

            // Normalize the BOTTOM side
            normalizePlane(m_Frustum, BOTTOM);

            // This will extract the TOP side of the frustum
            m_Frustum[TOP][A] = clip[ 3] - clip[ 1];
            m_Frustum[TOP][B] = clip[ 7] - clip[ 5];
            m_Frustum[TOP][C] = clip[11] - clip[ 9];
            m_Frustum[TOP][D] = clip[15] - clip[13];

            // Normalize the TOP side
            normalizePlane(m_Frustum, TOP);

            // This will extract the BACK side of the frustum
            m_Frustum[BACK][A] = clip[ 3] - clip[ 2];
            m_Frustum[BACK][B] = clip[ 7] - clip[ 6];
            m_Frustum[BACK][C] = clip[11] - clip[10];
            m_Frustum[BACK][D] = clip[15] - clip[14];

            // Normalize the BACK side
            normalizePlane(m_Frustum, BACK);

            // This will extract the FRONT side of the frustum
            m_Frustum[FRONT][A] = clip[ 3] + clip[ 2];
            m_Frustum[FRONT][B] = clip[ 7] + clip[ 6];
            m_Frustum[FRONT][C] = clip[11] + clip[10];
            m_Frustum[FRONT][D] = clip[15] + clip[14];

            // Normalize the FRONT side
            normalizePlane(m_Frustum, FRONT);
    }
}


Camera relevant code
package moonrise3d.camera;

import moonrise3d.util.MatrixUtil;

import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

public class Camera {
    private float fov;
    private float aspect;
    private float zNear;
    private float zFar;

    private Matrix4f projection;
    private Matrix4f view;

    // Camera position
    private Vector3f position;
    private Vector3f rotation;

    private Vector3f xAxis, yAxis, zAxis;

    
    public Camera(float fov, float aspect, float zNear, float zFar)
    {
        this.fov = fov;
        this.aspect = aspect;
        this.zNear = zNear;
        this.zFar = zFar;

        projection = MatrixUtil.createPerspectiveProjection(fov, aspect, zNear, zFar);
        view = MatrixUtil.createIdentityMatrix();

        position = new Vector3f(0, 0, 0);
        rotation = new Vector3f(0, 0, 0);

        xAxis = new Vector3f(1, 0, 0);
        yAxis = new Vector3f(0, 1, 0);
        zAxis = new Vector3f(0, 0, 1);

        GL11.glEnable(GL11.GL_DEPTH_TEST);
    }
    
    public void apply()
    {
        view.setIdentity();

        Matrix4f.rotate((float) Math.toRadians(rotation.x), xAxis, view, view);
        Matrix4f.rotate((float) Math.toRadians(rotation.y), yAxis, view, view);
        Matrix4f.rotate((float) Math.toRadians(rotation.z), zAxis, view, view);

        Matrix4f.translate(position, view, view);
    }

    public Matrix4f getProjectionMatrix()
    {
        return projection;
    }

    /**
     * @return the view matrix
     */
    public Matrix4f getViewMatrix()
    {
        return view;
    }
}


World Rendering(camera.apply(); is being called before this as well as setting the shader)
public void draw() {
		for (int x = 0; x < width(); x++)
		{
			for (int y = 0; y < height(); y++)
			{
				for (int z = 0; z < depth(); z++)
				{
					if (blocks[x][y][z] != null)
					{
						if (Window.frustum.cubeInFrustum(x * 8, y * 8, z * 8, 8))
						{
							Renderer3D.drawCube(x * 16, y * 16, z * 16, 16, 16, 16, BlockRegistry.getBlock(blocks[x][y][z]).texture);
						}
					}
				}
			}
		}
	}

I think the problem lies with the camera's view matrix but Im not entirely sure. If you need to see the shader code let me know.
EDIT: Looks like it depends on the angle im looking at it. If I look at one side, everything looks completely fine. Now Im thinking it's the projection matrix that's messed up somehow.

Daslee

Do you recalculate frustum planes after calling camera.apply(); and before rendering?

CJLetsGame

Yes

protected void draw() {
		//drawOld();
		camera.apply();
		//camera2.applyTranslations();
		frustum.calculateFrustum(Window.camera);
		
		basicTextureProgram.bind();
		basicTextureProgram.setUniform("projection", camera.getProjectionMatrix());
		basicTextureProgram.setUniform("view", camera.getViewMatrix());
		
		world.draw();
		
		ShaderProgram.unbind();
	}