Search code examples
opengltransformationjogllight

Stop light from getting vertices transformations


I'm trying to build a scene where there's a perspective looking at a textured cube and a light.

What's supposed to happen is that the light should stay somewhere above the cube, while the cube rotates (against its center) below that light.

What actually happends is that the light also rotates when the cube rotates.

I've tried googling this and looking similar SO questions but I found nothing that helped. Following OpenGL docs I'm understanding that the light position is affected by modelview matrix transformations, but I also understood that pushing/popping the matrix before/after said transformations would make it so that the light is no longer affected by them. However I can't make it work, the light keeps on rotating no matter if I isolate the modelview transformations (for the cube) to push/pop or if I load the identity matrix afterwards.

Here's the code (it's in Java using JOGL):

//this array goes into lightPositionBuffer 
private float[] lightPosition = {0, 0, 0, 1.0f};

public void display(GLAutoDrawable gLDrawable) {
    //code for clearing screen, binding the textures, etc.

    gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
    gl.glFrontFace(GL2.GL_CCW);
    gl.glVertexPointer(3, GL.GL_FLOAT, 0, cubeVerticesBuffer);
    gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, cubeTextureCoordsBuffer);

    //rotate the cube
    gl.glPushMatrix();    
    gl.glTranslatef(cubeCenterXInitial,cubeCenterYInitial,cubeCenterZInitial);
    gl.glRotatef(rotationAmountY, 1, 0, 0);
    gl.glTranslatef(-cubeCenterXInitial,-cubeCenterYInitial,-cubeCenterZInitial);
    rotationAmountY+=1.5f;
    gl.glDrawElements(GL.GL_TRIANGLE_STRIP, cubeIndexes.length, GL.GL_UNSIGNED_BYTE, cubeIndexesBuffer);
    gl.glPopMatrix();

    gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL2.GL_TEXTURE_COORD_ARRAY);

    //Position The Light:
    gl.glPushMatrix();
    //lightPositionBuffer is a FloatBuffer containing the lightPosition float array declared above:
    gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, lightPositionBuffer);
    gl.glPopMatrix();
    //Enable Light 0
    gl.glEnable(GL2.GL_LIGHT0); 
    gl.glEnable(GL2.GL_LIGHTING);
}

Here's what's happening:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here


Solution

  • Ok I've fixed it. Here's the two important points:

    1. As luke was mentioning in his answer, there's nothing wrong with my code as far as transformations are concerned. As it is, the transofrmations only affect the mesh, the light stays in fact still.

    2. The reason why it looks like my cube has a light rotating around it (when in fact the light is still) is, in one word, NORMALS.

    In more words: it's the lack of normals declaration for my cube's faces. Yep, who knew, I didn't. When you have some faces (like triangles and quads) and a light, not declaring normals will NOT simply have your surfaces not being impacted by the light. They are in fact impacted, but it's all weird (as you can see from my screenshots in the question text).

    So basically what I did to fix it is look at Nehe's (I love those guys) lesson 07 :

    http://nehe.gamedev.net/tutorial/texture_filters_lighting__keyboard_control/15002/

    At the bottom of the page there you have the code for a ton of languages and libraries, I personally used the JOGL version but any one will do fine.

    Then I also looked at the OpenGL docs just to see how I can declare my vertices/indices/normals as arrays (rather then individually):

    http://www.songho.ca/opengl/gl_vertexarray.html