Jump to content

  • Log In with Google      Sign In   
  • Create Account


#Actualvoodoodrul

Posted 03 July 2013 - 06:39 PM

So I have started the process of moving all my rendering out to a single VBO on WorldChunk. 

 

However, I'm pretty baffled as to how I can push all the vertex data into a single FloatBuffer. It's a pretty basic question about OpenGL, but maybe if we talk through it it will make more sense. 

 

The way I was rendering my scene before relied on glTranslatef() to do all the heavy lifting to get my vertex data in position. The World.render() would iterate over the WorldChunks and call render() on those. WorldChunk.render() would glTranslatef(x,y,z) into the chunk's position. Then WorldChunks.render() would iterate over the Blocks and in turn each block would glTranslatef(x,y,z) to get the block into place. The nice thing about this is that I could draw faces without worrying about vertex data from an earlier face draw. 

 

Now I need to replicate the same process on raw vertex data stored in a buffer. What I do now is let WorldChunk.generate() occur in its own thread - not using any OpenGL calls during this compile pass. The function needs to draw only those faces that are exposed and visible. I do this by determining which faces are exposed and pushing *only those faces* onto an ArrayList<FloatBuffer>. Once the list is done, I push all those individual FloatBuffers onto a single new FloatBuffer vbuffer. 

 

WorldChunk

--------------------

private void generate() {

     .....

     buildMesh();

}

 

 

public void buildMesh() {
        this.dynamicVertexData = new ArrayList<FloatBuffer>();

        for (int i = 0; i < sizeX; i++) {
            for (int j = 0; j < sizeY; j++) {
                for (int k = 0; k < sizeZ; k++) {
                    if (blocks[i][j][k] != 0) {
                            Block.render(i, j, k, 1, EXPOSED_FACES, wireframe, this);  //Writes each face as its own FloatBuffer in dynamicVertexData
                    }
                }
            }
        }

        this.vbuffer = Util.getFloatBuffer(this.dynamicVertexData.size() * 18);
        //Convert all the individual floatbuffers into one megalithic float buffer
        for (int i = 0; i < this.dynamicVertexData.size(); i++) {
            if (this.dynamicVertexData.size() > 0) {
                this.vbuffer.put(this.dynamicVertexData.get(i));
            }
        }
        this.vbuffer.flip();
}


    private void buildVBO() {
        vboVertexHandle = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboVertexHandle);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.vbuffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }


    public void drawMesh(boolean wireframe) {
        GL11.glPushMatrix();
        GL11.glTranslatef(this.worldPositionX, 0, this.worldPositionZ);
        GL11.glPolygonMode(GL11.GL_FRONT, GL11.GL_FILL);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vboVertexHandle);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);

        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);

        //Draw now
        if (this.dynamicVertexData.size() > 0) {
            GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, this.dynamicVertexData.size() * 6);
        }
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glPopMatrix();
    }

Block
---------------------------


    public static FloatBuffer verticiesFront(float x, float y, float z) {
        return Util.getFloatBuffer(new float[]{
                    (x * size), (y * size), (z * size), -(x * size), (y * size), (z * size), -(x * size), -(y * size), (z * size), // v0-v1-v2 (front)
                    -(x * size), -(y * size), (z * size), (x * size), -(y * size), (z * size), (x * size), (y * size), (z * size), // v2-v3-v0
                });
    }
.....

render(int x, int y, int z, int type, boolean[] faces, WorldChunk chunk) 

if (faces[0] || faces[1] || faces[2] || faces[3] || faces[4] || faces[5]) {
            if (faces[0]) {
                chunk.dynamicVertexData.add(verticiesFront(x, y, z));
            }
            if (faces[1]) {
                chunk.dynamicVertexData.add(verticiesRight(x, y, z));
            }
            if (faces[2]) {
                chunk.dynamicVertexData.add(verticiesTop(x, y, z));
            }
            if (faces[3]) {
                chunk.dynamicVertexData.add(verticiesLeft(x, y, z));
            }
            if (faces[4]) {
                chunk.dynamicVertexData.add(verticiesBottom(x, y, z));
            }
            if (faces[5]) {
                chunk.dynamicVertexData.add(verticiesBack(x, y, z));
            }
        }

 

Essentially I will use the same process of pushing points x,y,z into the buffer, one at a time, but I need to make sure that those x,y,z are effectively translated as they would be with glTranslatef(x,y,z).

 

Do I just need to find a way to translate the points or will I have bigger problems? 

 

For example, imagine a chunk 16x16x16 chunk with only 5 exposed faces for some odd reason. They are scattered throughout the chunk. When I declare a face in the vertex buffer/mesh, I need it to be entirely self-contained - the preceding point from a face should not break the next face to draw. How can I accomplish this? 

 

When you draw the points, you can never "pick up your pencil" really. I need to draw a face, stop drawing, and then draw again somewhere else, all the while keeping that information in the vertex buffer. 

 

Maybe I am greatly over complicating this. Can I draw using my old method and somehow extract the raw vertex data from OpenGL *after* I have done all the glTranslatef() calls and my mesh is complete inside OpenGL's current frame? It would be slower on the first pass, due to all the push/translate/pop, but once everything is in place, I'd love to just snap a copy of it. 


#3voodoodrul

Posted 02 July 2013 - 08:40 PM

So I have started the process of moving all my rendering out to a single VBO on WorldChunk. 

 

However, I'm pretty baffled as to how I can push all the vertex data into a single FloatBuffer. It's a pretty basic question about OpenGL, but maybe if we talk through it it will make more sense. 

 

The way I was rendering my scene before relied on glTranslatef() to do all the heavy lifting to get my vertex data in position. The World.render() would iterate over the WorldChunks and call render() on those. WorldChunk.render() would glTranslatef(x,y,z) into the chunk's position. Then WorldChunks.render() would iterate over the Blocks and in turn each block would glTranslatef(x,y,z) to get the block into place. The nice thing about this is that I could draw faces without worrying about vertex data from an earlier face draw. 

 

Now I need to replicate the same process on raw vertex data stored in a buffer. What I do now is let WorldChunk.generate() occur in its own thread - not using any OpenGL calls during this compile pass. The function needs to draw only those faces that are exposed and visible. I do this by determining which faces are exposed and pushing *only those faces* onto an ArrayList<FloatBuffer>. Once the list is done, I push all those individual FloatBuffers onto a single new FloatBuffer vbuffer. 

 

WorldChunk

--------------------

private void generate() {

     .....

     buildMesh();

}

 

 

public void buildMesh() {
        this.dynamicVertexData = new ArrayList<FloatBuffer>();
 
        for (int i = 0; i < sizeX; i++) {
            for (int j = 0; j < sizeY; j++) {
                for (int k = 0; k < sizeZ; k++) {
                    if (blocks[i][j][k] != 0) {
                            Block.render(i, j, k, 1, EXPOSED_FACES, wireframe, this);  //Writes each face as its own FloatBuffer in dynamicVertexData
                    }
                }
            }
        }

 

        this.vbuffer = Util.getFloatBuffer(this.dynamicVertexData.size() * 18);
        //Convert all the individual floatbuffers into one megalithic float buffer
        for (int i = 0; i < this.dynamicVertexData.size(); i++) {
            if (this.dynamicVertexData.size() > 0) {
                this.vbuffer.put(this.dynamicVertexData.get(i));
            }
        }
        this.vbuffer.flip();
}
 

    private void buildVBO() {
        vboVertexHandle = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboVertexHandle);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.vbuffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
 

    public void drawMesh(boolean wireframe) {
        GL11.glPushMatrix();
        GL11.glTranslatef(this.worldPositionX, 0, this.worldPositionZ);
        GL11.glPolygonMode(GL11.GL_FRONT, GL11.GL_FILL);
 
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vboVertexHandle);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
 
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
 
        //Draw now
        if (this.dynamicVertexData.size() > 0) {
            GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, this.dynamicVertexData.size() * 6);
        }
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glPopMatrix();
    }
 
Block
---------------------------
 

    public static FloatBuffer verticiesFront(float x, float y, float z) {
        return Util.getFloatBuffer(new float[]{
                    (x * size), (y * size), (z * size), -(x * size), (y * size), (z * size), -(x * size), -(y * size), (z * size), // v0-v1-v2 (front)
                    -(x * size), -(y * size), (z * size), (x * size), -(y * size), (z * size), (x * size), (y * size), (z * size), // v2-v3-v0
                });
    }
.....
 
render(int x, int y, int z, int type, boolean[] faces, WorldChunk chunk) 

if (faces[0] || faces[1] || faces[2] || faces[3] || faces[4] || faces[5]) {
            if (faces[0]) {
                chunk.dynamicVertexData.add(verticiesFront(x, y, z));
            }
            if (faces[1]) {
                chunk.dynamicVertexData.add(verticiesRight(x, y, z));
            }
            if (faces[2]) {
                chunk.dynamicVertexData.add(verticiesTop(x, y, z));
            }
            if (faces[3]) {
                chunk.dynamicVertexData.add(verticiesLeft(x, y, z));
            }
            if (faces[4]) {
                chunk.dynamicVertexData.add(verticiesBottom(x, y, z));
            }
            if (faces[5]) {
                chunk.dynamicVertexData.add(verticiesBack(x, y, z));
            }
        }
 

 

Essentially I will use the same process of pushing points x,y,z into the buffer, one at a time, but I need to make sure that those x,y,z are effectively translated as they would be with glTranslatef(x,y,z).

 

Do I just need to find a way to translate the points or will I have bigger problems? 

 

For example, imagine a chunk 16x16x16 chunk with only 5 exposed faces for some odd reason. They are scattered throughout the chunk. When I declare a face in the vertex buffer/mesh, I need it to be entirely self-contained - the preceding point from a face should not break the next face to draw. How can I accomplish this? 

 

When you draw the points, you can never "pick up your pencil" really. I need to draw a face, stop drawing, and then draw again somewhere else, all the while keeping that information in the vertex buffer. 

 

Maybe I am greatly over complicating this. Can I draw using my old method and somehow extract the raw vertex data from OpenGL *after* I have done all the glTranslatef() calls and my mesh is complete inside OpenGL's current frame? It would be slower on the first pass, due to all the push/translate/pop, but once everything is in place, I'd love to just snap a copy of it. 


#2voodoodrul

Posted 02 July 2013 - 08:26 PM

So I have started the process of moving all my rendering out to a single VBO on WorldChunk. 

 

However, I'm pretty baffled as to how I can push all the vertex data into a single FloatBuffer. It's a pretty basic question about OpenGL, but maybe if we talk through it it will make more sense. 

 

The way I was rendering my scene before relied on glTranslatef() to do all the heavy lifting to get my vertex data in position. The World.render() would iterate over the WorldChunks and call render() on those. WorldChunk.render() would glTranslatef(x,y,z) into the chunk's position. Then WorldChunks.render() would iterate over the Blocks and in turn each block would glTranslatef(x,y,z) to get the block into place. The nice thing about this is that I could draw faces without worrying about vertex data from an earlier face draw. 

 

Now I need to replicate the same process on raw vertex data stored in a buffer. What I do now is let WorldChunk.generate() occur in its own thread - not using any OpenGL calls during this compile pass. The function needs to draw only those faces that are exposed and visible. I do this by determining which faces are exposed and pushing *only those faces* onto an ArrayList<FloatBuffer>. Once the list is done, I push all those individual FloatBuffers onto a single new FloatBuffer vbuffer. 

 

WorldChunk

--------------------

private void generate() {

     .....

     buildMesh();

}

 

 

public void buildMesh() {
        this.dynamicVertexData = new ArrayList<FloatBuffer>();
 
        for (int i = 0; i < sizeX; i++) {
            for (int j = 0; j < sizeY; j++) {
                for (int k = 0; k < sizeZ; k++) {
                    if (blocks[i][j][k] != 0) {
                            Block.render(i, j, k, 1, EXPOSED_FACES, wireframe, this);  //Writes each face as its own FloatBuffer in dynamicVertexData
                    }
                }
            }
        }

 

        this.vbuffer = Util.getFloatBuffer(this.dynamicVertexData.size() * 18);
        //Convert all the individual floatbuffers into one megalithic float buffer
        for (int i = 0; i < this.dynamicVertexData.size(); i++) {
            if (this.dynamicVertexData.size() > 0) {
                this.vbuffer.put(this.dynamicVertexData.get(i));
            }
        }
        this.vbuffer.flip();
}
 

    private void buildVBO() {
        vboVertexHandle = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboVertexHandle);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.vbuffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
 

    public void drawMesh(boolean wireframe) {
        GL11.glPushMatrix();
        GL11.glTranslatef(this.worldPositionX, 0, this.worldPositionZ);
        GL11.glPolygonMode(GL11.GL_FRONT, GL11.GL_FILL);
 
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vboVertexHandle);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
 
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
 
        //Draw now
        if (this.dynamicVertexData.size() > 0) {
            GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, this.dynamicVertexData.size() * 6);
        }
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glPopMatrix();
    }
 
Block
---------------------------
 

    public static FloatBuffer verticiesFront(float x, float y, float z) {
        return Util.getFloatBuffer(new float[]{
                    (x * size), (y * size), (z * size), -(x * size), (y * size), (z * size), -(x * size), -(y * size), (z * size), // v0-v1-v2 (front)
                    -(x * size), -(y * size), (z * size), (x * size), -(y * size), (z * size), (x * size), (y * size), (z * size), // v2-v3-v0
                });
    }
.....
 
render(int x, int y, int z, int type, boolean[] faces, WorldChunk chunk) 

if (faces[0] || faces[1] || faces[2] || faces[3] || faces[4] || faces[5]) {
            if (faces[0]) {
                chunk.dynamicVertexData.add(verticiesFront(x, y, z));
            }
            if (faces[1]) {
                chunk.dynamicVertexData.add(verticiesRight(x, y, z));
            }
            if (faces[2]) {
                chunk.dynamicVertexData.add(verticiesTop(x, y, z));
            }
            if (faces[3]) {
                chunk.dynamicVertexData.add(verticiesLeft(x, y, z));
            }
            if (faces[4]) {
                chunk.dynamicVertexData.add(verticiesBottom(x, y, z));
            }
            if (faces[5]) {
                chunk.dynamicVertexData.add(verticiesBack(x, y, z));
            }
        }
 

 

Essentially I will use the same process of pushing points x,y,z into the buffer, one at a time, but I need to make sure that those x,y,z are effectively translated as they would be with glTranslatef(x,y,z).

 

Do I just need to find a way to translate the points or will I have bigger problems? 

 

For example, imagine a chunk 16x16x16 chunk with only 5 exposed faces for some odd reason. They are scattered throughout the chunk. When I declare a face in the vertex buffer/mesh, I need it to be entirely self-contained - the preceding point from a face should not break the next face to draw. How can I accomplish this? 

 

When you draw the points, you can never "pick up your pencil" really. I need to draw a face, stop drawing, and then draw again somewhere else, all the while keeping that information in the vertex buffer. 


#1voodoodrul

Posted 02 July 2013 - 08:22 PM

So I have started the process of moving all my rendering out to a single VBO on WorldChunk. 

 

However, I'm pretty baffled as to how I can push all the vertex data into a single FloatBuffer. It's a pretty basic question about OpenGL, but maybe if we talk through it it will make more sense. 

 

The way I was rendering my scene before relied on glTranslatef() to do all the heavy lifting to get my vertex data in position. The World.render() would iterate over the WorldChunks and call render() on those. WorldChunk.render() would glTranslatef(x,y,z) into the chunk's position. Then WorldChunks.render() would iterate over the Blocks and in turn each block would glTranslatef(x,y,z) to get the block into place. The nice thing about this is that I could draw faces without worrying about vertex data from an earlier face draw. 

 

Now I need to replicate the same process on raw vertex data stored in a buffer. What I do now is let WorldChunk.generate() occur in its own thread - not using any OpenGL calls during this compile pass. The function needs to draw only those faces that are exposed and visible. I do this by determining which faces are exposed and pushing *only those faces* onto an ArrayList<FloatBuffer>. Once the list is done, I push all those individual FloatBuffers onto a single new FloatBuffer vbuffer. 

 

WorldChunk

--------------------

private void generate() {

     .....

     buildMesh();

}

 

 

public void buildMesh() {
        this.dynamicVertexData = new ArrayList<FloatBuffer>();
 
        for (int i = 0; i < sizeX; i++) {
            for (int j = 0; j < sizeY; j++) {
                for (int k = 0; k < sizeZ; k++) {
                    if (blocks[i][j][k] != 0) {
                            Block.render(i, j, k, 1, EXPOSED_FACES, wireframe, this);  //Writes each face as its own FloatBuffer in dynamicVertexData
                    }
                }
            }
        }

 

        this.vbuffer = Util.getFloatBuffer(this.dynamicVertexData.size() * 18);
        //Convert all the individual floatbuffers into one megalithic float buffer
        for (int i = 0; i < this.dynamicVertexData.size(); i++) {
            if (this.dynamicVertexData.size() > 0) {
                this.vbuffer.put(this.dynamicVertexData.get(i));
            }
        }
        this.vbuffer.flip();
}
 

    private void buildVBO() {
        vboVertexHandle = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboVertexHandle);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.vbuffer, GL15.GL_STATIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
 

    public void drawMesh(boolean wireframe) {
        GL11.glPushMatrix();
        GL11.glTranslatef(this.worldPositionX, 0, this.worldPositionZ);
        GL11.glPolygonMode(GL11.GL_FRONT, GL11.GL_FILL);
 
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.vboVertexHandle);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
 
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
 
        //Draw now
        if (this.dynamicVertexData.size() > 0) {
            GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, this.dynamicVertexData.size() * 6);
        }
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glPopMatrix();
    }
 
Block
---------------------------
 

    public static FloatBuffer verticiesFront(float x, float y, float z) {
        return Util.getFloatBuffer(new float[]{
                    (x * size), (y * size), (z * size), -(x * size), (y * size), (z * size), -(x * size), -(y * size), (z * size), // v0-v1-v2 (front)
                    -(x * size), -(y * size), (z * size), (x * size), -(y * size), (z * size), (x * size), (y * size), (z * size), // v2-v3-v0
                });
    }
.....
 
render(int x, int y, int z, int type, boolean[] faces, WorldChunk chunk) 

if (faces[0] || faces[1] || faces[2] || faces[3] || faces[4] || faces[5]) {
            if (faces[0]) {
                chunk.dynamicVertexData.add(verticiesFront(x, y, z));
            }
            if (faces[1]) {
                chunk.dynamicVertexData.add(verticiesRight(x, y, z));
            }
            if (faces[2]) {
                chunk.dynamicVertexData.add(verticiesTop(x, y, z));
            }
            if (faces[3]) {
                chunk.dynamicVertexData.add(verticiesLeft(x, y, z));
            }
            if (faces[4]) {
                chunk.dynamicVertexData.add(verticiesBottom(x, y, z));
            }
            if (faces[5]) {
                chunk.dynamicVertexData.add(verticiesBack(x, y, z));
            }
        }
 

 

Essentially I will use the same process of pushing points x,y,z into the buffer, one at a time, but I need to make sure that those x,y,z are effectively translated as they would be with glTranslatef(x,y,z).

 

Do I just need to find a way to translate the points or will I have bigger problems? 

 

For example, imagine a chunk 16x16x16 chunk with only 5 exposed faces for some odd reason. They are scattered throughout the chunk. When I declare a face, I need it to be entirely self-contained - the preceding point from a face should not break the next face to draw. How can I accomplish this? 

 

When you draw the points, you can never "pick up your pencil" really. I need to draw a face, stop drawing, and then draw again somewhere else, all the while keeping that information in the vertex buffer. 

 

 

 


PARTNERS