Hello Guest

Frustum clipping issues

  • 2 Replies
  • 4959 Views
Frustum clipping issues
« on: March 31, 2014, 23:48:45 »
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
Code: [Select]
   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
Code: [Select]
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)
Code: [Select]
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.
« Last Edit: March 31, 2014, 23:54:05 by CJLetsGame »

*

Offline Daslee

  • ***
  • 126
Re: Frustum clipping issues
« Reply #1 on: April 01, 2014, 11:40:08 »
Do you recalculate frustum planes after calling camera.apply(); and before rendering?

Re: Frustum clipping issues
« Reply #2 on: April 01, 2014, 17:37:32 »
Yes

Code: [Select]
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();
}