LWJGL Forum

Programming => OpenGL => Topic started by: CJLetsGame on March 31, 2014, 23:48:45

Title: Frustum clipping issues
Post by: CJLetsGame 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 (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.
Title: Re: Frustum clipping issues
Post by: Daslee on April 01, 2014, 11:40:08
Do you recalculate frustum planes after calling camera.apply(); and before rendering?
Title: Re: Frustum clipping issues
Post by: CJLetsGame on April 01, 2014, 17:37:32
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();
}