View Frustum Culling for LWJGL and GL4Java

On my hosting, now!

http://suicidesolutions.com/

at codes section. Damn I frame, so I can’t link straight, otherwise you’ll get my nasty 404 error page. Anyway have fun. They are not noob friendly so if you don’t know what you are doing, you’ll most likely fail.

I will also update the site with more user friendly LWGL tutorials. No offence CHMAN ;D

Edit: Wrong call, something is still wrong with the LWGL one, but the GL4Java one works for sure.

LoL ;D
I’m hapy to see that there will be others site on lwjgl. Tell me when your site will contain some tuts, i will add a link to my site ! :slight_smile:

++
Chman

I’ve been porting some code that does frustum culling, from the Game Tutorials site. I was wondering why this bit of code doesn’t work as I expect.


float[] proj = new float[16];
float[] modl = new float[16];
float[] clip = new float[16];

FloatBuffer projBuf;
FloatBuffer modlBuf;

public CFrustum() {
  projBuf = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asFloatBuffer();
  projBuf.put(proj);
  modlBuf = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asFloatBuffer();
  modlBuf.put(modl);
}


void CalculateFrustum(GL gl) {
  gl.getFloatv(GL.PROJECTION_MATRIX,Sys.getDirectBufferAddress(projBuf));
  gl.getFloatv(GL.MODELVIEW_MATRIX,Sys.getDirectBufferAddress(modlBuf));


  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];

...

}

My question is this, currently as the code stands my modl and proj arrays are empty so when I do my calulations and normalise my planes etc I get NAN (not a number) as the results, which is useless later when I do my checking in boxInFrustum(…) .

If I insert the following code into my calculateFrustum(…) method after the gl.getFloatV calls, everything works.


for (int i=0; i<16; i++) {
  proj[i] = projBuf.get(i);
  modl[i] = modlBuf.get(i);
}

I was wondering why my float[] arrays proj and modl aren’t populated directly when the FloatBuffer is used in the getFloatv opengl method.

Am I using these buffers incorrectly or is there a bug?

Thanks,

Andy.

Yes, you’re using them incorrectly; you have to copy the data out of the buffer into the float arrays. What you want is my new struct keyword which would go some way to wrapping native buffers with Java objects. It needs lots of votes at JDC, but it still hasn’t appeared yet…

The RFE is 4820062 - when it finally does turn up.

Cas :slight_smile:

So in my situation what would be the correct way, if I insert the following code everything works


for (int i=0; i<16 i++) {
  proj[i] = projBuf.get(i);
  modl[i] = modlBuf.get(i);
}

How would you do things differently?

Thanks,

Andy.

That is the correct way.
The best way is of course to use the bulk array get and put commands:


modlBuf.get(modl);
projBuf.get(proj);

[quote]Edit: Wrong call, something is still wrong with the LWGL one, but the GL4Java one works for sure.
[/quote]
Could it be the normalization; I get the feeling something should get divided by ‘magnitude’ in there…?

/M

Yes, after extracting all the planes they need to be normalised, eg. a, b, c, and d need to be divided by the magnitude of the vector a, b, c. I think.

Cas :slight_smile:

I have all the normalisation stuff in there, it was just the nio buffers I was having problems with.

Cas, when I replace my for loop code with the projBuf.get(proj); example you gave, I get BufferUnderflowExceptions, I’ll have to investigate the reason why otherwise I’ll have to go back to my for loop solution.

Thanks,

Andy.

Gah! You programmers never read the bloody docs! Before you can read from the start of a buffer you’ve got to rewind() it first.

Cas :slight_smile:

Cas,

You’re right! I just came here to let you know I’ve found the solution, and here you are already. If I add the following code, it all works again.


    projBuf.rewind();
    modlBuf.rewind();

    projBuf.get(proj);
    modlBuf.get(modl);

Thanks,

Andy.

I’m back, and I have a rather strange problem that I’m hoping someone can help me with.

I’ve recently started a new project and based it on code I’ve had working under LWJGL 0.6, I’m now using 0.8 (I’ve also switched from Java 1.4.2 to 1.5b).

The problem is this when I rotate my camera, the edges of my frustum come into view and I can see what was previous clipped.

My camera update code looks like this


GL.glMatrixMode(GL.GL_MODELVIEW);
GL.glLoadIdentity();
GLU.gluLookAt(m_Position.x, m_Position.y, m_Position.z, m_CurrentLookAt.x, m_CurrentLookAt.y, m_CurrentLookAt.z, m_LookUp.x, m_LookUp.y, m_LookUp.z);

and the first part of my calculate frustum code is as follows


GL.glGetFloat( GL.GL_PROJECTION_MATRIX, projBuf);
GL.glGetFloat( GL.GL_MODELVIEW_MATRIX, modlBuf);

projBuf.rewind();
modlBuf.rewind();

projBuf.get(proj);
modlBuf.get(modl);

I call them in my render loop


camera.update(); // does a glLookAt() current view
calculateFrustum(); // as described in this thread.

// render code with fustrum testing goes here.


So what I see is the same view (terrain in this case) frustum culled but then rotated into view.

I’m not explaining this very well, so here is a screenshot, my terrain in this shot has been rendered and I’ve rotated the view, and instead of getting the rest of my terrain, I get empty space. my current x, y coordinates put me i the center of my heightmap, not in a corner.

http://games.swizel-studios.com/images/screenshots/terrain00.png

Anyone got any ideas what I might be doing wrong, it’s probibly something really stupid, I have code that I can show if that’ll help.

Thanks,

Andy.

Try actually rendering your frustum. It should be more or less invisible - just a square border at the edge of the screen. If you can see any more of it your frustum is b0rked.

To render your frustum, simply draw lines between the corners of the frustum to draw a “cube”. The edges of the frustum are at 0,0,0 -> screen width, screen height,furthest depth.

Cas :slight_smile:

I’ve finally worked out the problem, in LWJGL v0.8 I have to change my calculateFrustum() code in the following way


GL.glGetFloat( GL.GL_PROJECTION_MATRIX, projBuf);
GL.glGetFloat( GL.GL_MODELVIEW_MATRIX, modlBuf);

projBuf.rewind();
modlBuf.rewind();

projBuf.get(proj);
modlBuf.get(modl);

becomes


projBuf.rewind();
modlBuf.rewind();

GL.glGetFloat( GL.GL_PROJECTION_MATRIX, projBuf);
GL.glGetFloat( GL.GL_MODELVIEW_MATRIX, modlBuf);

projBuf.rewind();
modlBuf.rewind();

projBuf.get(proj);
modlBuf.get(modl);

What I was seeing is the same project and matrix values being returned, and I took a guess that the buffers may be being appended to, so I was always reading out the same first 16 values from each.

It would have been nice to get some sort of ArrayIndexOutOfBounds type exception since I only declared the buffers of being size 64, or to have the glGetFloat do an automatic rewind for me.

Regards,

Andy.

'sfunny you should say that… buffer checks are going into 0.9.

Cas :slight_smile:

[quote]buffer checks are going into 0.9
[/quote]
Thats great new. I had a bug where I forgot to rewind a buffer befor sending it to a opengl get function. It trashed the memory wich caused random vm crashes. Had no idee what was going on at the time, and was very difficult to debug :’(