Search code examples
javaopengllwjglvertex

OpenGL Vertex Arrays and GL_TRIANGLE_STRIP drawing error


I'm implementing a height map with GL_TRIANGLE_STRIPS and the LWJGL OpenGL Java Bindings. When I draw 'direct' using 'GL_BEGIN/GL_END' it works perfectly but when the heightmap is to big it works slow.

As I want to move on using VBO's I'm now learning how to use Vertex Array's. This is where I have a problem, the drawing is just wrong. It seems that the last triangle of the strip returns to the first one. Perheps a picture is better:

Good drawing: Good direct drawing

Bad Vertex array drawing: Bad vertex array drawing

My code is the following for normal drawing:

public void renderDirect() {
    //adapt the camera to the map
    float scale = 5.0f / Math.max(w - 1, l - 1);
    GL11.glScalef(scale, scale, scale);
    GL11.glTranslatef(-(float) (w - 1) / 2, 0.0f, -(float) (l - 1) / 2);

    //choose map color
    GL11.glColor3f(0.3f, 0.9f, 0.0f);

    for (int z = 0; z < l - 1; z++) {
        //Makes OpenGL draw a triangle at every three consecutive vertices
        GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
        for (int x = 0; x < w; x++) {
            Vector3f normal = getNormal(x, z);
            GL11.glNormal3f(normal.getX(), normal.getY(), normal.getZ());
            GL11.glVertex3f(x, getHeight(x, z), z);
            normal = getNormal(x, z + 1);
            GL11.glNormal3f(normal.getX(), normal.getY(), normal.getZ());
            GL11.glVertex3f(x, getHeight(x, z + 1), z + 1);
        }
        glEnd();
    }
}

My code is the following for vertex array drawing:

private void loadArrays(){
    //calculate the length of the buffers
    bLength = (l-1) * w * 6;
    //create the normal and vertex buffer array's
    dataBuffer = BufferUtils.createFloatBuffer(bLength*2);
    cBuffer = BufferUtils.createFloatBuffer(bLength);

    for (int z = 0; z < l - 1; z++) {
        //Fill up the buffers
        for (int x = 0; x < w; x++) {
            Vector3f normal = getNormal(x, z);
            dataBuffer.put(x).put(getHeight(x,z)).put(z);
            dataBuffer.put(normal.getX()).put(normal.getY()).put(normal.getZ());
            normal = getNormal(x, z + 1);
            dataBuffer.put(x).put(getHeight(x,z+1)).put(z+1);
            dataBuffer.put(normal.getX()).put(normal.getY()).put(normal.getZ());              
        }
    } 
}

int stride = 6*4;
public void renderDirect() {
    //adapt the camera to the map
    float scale = 5.0f / Math.max(w - 1, l - 1);
    GL11.glScalef(scale, scale, scale);
    GL11.glTranslatef(-(float) (w - 1) / 2, 0.0f, -(float) (l - 1) / 2);

    //choose map color
    GL11.glColor3f(0.3f, 0.9f, 0.0f);

    //Draw the vertex arrays
    glEnableClientState(GL_VERTEX_ARRAY);      
    glEnableClientState(GL_NORMAL_ARRAY); 

    dataBuffer.position(0);
    glVertexPointer(3, stride, dataBuffer);
    dataBuffer.position(3);
    glNormalPointer(stride,dataBuffer);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, bLength/3);    

    glDisableClientState(GL_VERTEX_ARRAY);      
    glDisableClientState(GL_NORMAL_ARRAY);
}    

What am I doing wrong?


Solution

  • Concatenating triangle strips back-to-back like that will not work as you expect.

    Either call glDrawArrays() in a loop adjusting the first and count parameters to draw your original N triangle strips, or add degenerate triangles to the end of each row to reset the strip starting position.

    Or just use GL_TRIANGLES :)