• Create Account

Banner advertising on our site currently available from just \$5!

### #Actualvoodoodrul

Posted 04 July 2013 - 10:41 AM

This "degeneration" seems way too complicated, I'm not even sure what you're trying to achieve with that. Are you trying to copy the needed faces to other array or what?

Without the degeneration, I would have visible triangles drawn between disconnected faces of a block. If I have 3 blocks to draw, like this:

block1 -> front + back + right

block2 -> right + back + top

block3 -> front + left

Imagine trying to compute a closed, single connected triangle fan from that. It would be tricky. You'd need to start your first face on block 1, then stop drawing (degenerate vertex) and move the vertex array "pointer" to a back face corner and start drawing the back face. When you are done with that, you'll need to stop drawing (with a degenerate) and get a vertex pointer over to a corner on block2's right face (another degenerate), then commit to actually start drawing again with yet another degenerate vertex on block2's right face.

It sounds overly complicated, but I don't believe it to be - I think this is how optimal meshes are output and even Blender, when I draw a mesh like this, will output a similar mesh. Computing truly optimal meshes, however, is proven to be an NP-complete problem.

I did get it functional with something that looks like this:

            new float[]{
//Vertex         Normals      Colors                            Texcoord
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0, //Degenerate reset
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0,
x, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 0,
x, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 1, // v0-v1-v2front
x, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 1,
x + 1, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 1,
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0, // v2-v3-v0
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0, //End this face
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0,}, //Degenerate reset
//Right face
new float[]{
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0, //Degenerate reset
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0,
x + 1, y, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 1,
x + 1, y, z, 1, 0, 0, color[0], color[1], color[2], 1, 1, // v0-v3-v4right
x + 1, y, z, 1, 0, 0, color[0], color[1], color[2], 1, 1,
x + 1, y + 1, z, 1, 0, 0, color[0], color[1], color[2], 1, 0,
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0, // v4-v5-v0
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0,//End this face
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0,}, //Degenerate reset


As you can see, there are several degens in there. Every time a face is drawn, I move the vertex "pointer" from a known bogus vertex - (Float.NaN, Float.NaN, Float.NaN) and start drawing a new face with a real x,y,z. At the end of each face I restore the degenerate back to (Float.NaN, Float.NaN, Float.NaN) - I need to ensure that no matter where I am in drawing blocks, I won't send OpenGL a bunch of duplicate values. If I used 0,0,0 for example, and I tried to draw a block actually at 0,0,0, this scheme would not work because OpenGL would be fed even more degenerates and toggle drawing of those verticies off. The easiest thing to do is start and stop each face with degenerate verticies that you know will never actually need to be drawn and that won't collide with any actual drawn vertex in your mesh.

This all works fine at the moment with a few caveats. Performance is excellent - I get over 300fps on an intel hd 4000 integrated card and over 2000fps on my GTX690 with about 20 million blocks in scene. Of course those 20 million blocks become relatively few faces to actually draw since most are completely concealed - maybe a couple hundred thousand faces actually being drawn.

I have one lingering problem that only occurs on Radeon cards. Notice these rogue faces:

Each chunk is outlined in the red wires. Notice the "thrashing" of garbage vertex data near the origin of the chunk:

Whereas Intel and Nvidia cards render the scene as expected:

### #2voodoodrul

Posted 04 July 2013 - 10:15 AM

This "degeneration" seems way too complicated, I'm not even sure what you're trying to achieve with that. Are you trying to copy the needed faces to other array or what?

Without the degeneration, I would have visible triangles drawn between disconnected faces of a block. If I have 3 blocks to draw, like this:

block1 -> front + back + right

block2 -> right + back + top

block3 -> front + left

Imagine trying to compute a closed, single connected triangle fan from that. It would be tricky. You'd need to start your first face on block 1, then stop drawing (degenerate vertex) and move the vertex array "pointer" to a back face corner and start drawing the back face. When you are done with that, you'll need to stop drawing (with a degenerate) and get a vertex pointer over to a corner on block2's right face (another degenerate), then commit to actually start drawing again with yet another degenerate vertex on block2's right face.

It sounds overly complicated, but I don't believe it to be - I think this is how optimal meshes are output and even Blender, when I draw a mesh like this, will output a similar mesh. Computing truly optimal meshes, however, is proven to be an NP-complete problem.

I did get it functional with something that looks like this:

            new float[]{
//Vertex         Normals      Colors                            Texcoord
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0, //Degenerate reset
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0,
x, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 0,
x, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 1, // v0-v1-v2front
x, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 1,
x + 1, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 1,
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0, // v2-v3-v0
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0, //End this face
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0,}, //Degenerate reset
//Right face
new float[]{
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0, //Degenerate reset
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0,
x + 1, y, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 1,
x + 1, y, z, 1, 0, 0, color[0], color[1], color[2], 1, 1, // v0-v3-v4right
x + 1, y, z, 1, 0, 0, color[0], color[1], color[2], 1, 1,
x + 1, y + 1, z, 1, 0, 0, color[0], color[1], color[2], 1, 0,
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0, // v4-v5-v0
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0,//End this face
Float.NaN, Float.NaN, Float.NaN, 0, 0, 0, 0, 0, 0, 0, 0,}, //Degenerate reset


As you can see, there are several degens in there. Every time a face is drawn, I move the vertex "pointer" from a known bogus vertex - (Float.NaN, Float.NaN, Float.NaN) and start drawing a new face with a real x,y,z. At the end of each face I restore the degenerate back to (Float.NaN, Float.NaN, Float.NaN) - I need to ensure that no matter where I am in drawing blocks, I won't send OpenGL a bunch of duplicate values. If I used 0,0,0 for example, and I tried to draw a block actually at 0,0,0, this scheme would not work because OpenGL would be fed even more degenerates and toggle drawing of those verticies off. The easiest thing to do is start and stop each face with degenerate verticies that you know will never actually need to be drawn and that won't collide with any actual drawn vertex in your mesh.

This all works fine at the moment with a few caveats. Performance is excellent - I get over 300fps on an intel hd 4000 integrated card and over 2000fps on my GTX690 with about 20 million blocks in scene. Of course those 20 million blocks become relatively few faces to actually draw since most are completely concealed - maybe a couple hundred thousand faces actually being drawn.

### #1voodoodrul

Posted 04 July 2013 - 09:34 AM

This "degeneration" seems way too complicated, I'm not even sure what you're trying to achieve with that. Are you trying to copy the needed faces to other array or what?

Without the degeneration, I would have visible triangles drawn between disconnected faces of a block. If I have 3 blocks to draw, like this:

block1 -> front + back + right

block2 -> right + back + top

block3 -> front + left

Imagine trying to compute a closed, single connected triangle fan from that. It would be tricky. You'd need to start your first face on block 1, then stop drawing (degenerate vertex) and move the vertex array "pointer" to a back face corner and start drawing the back face. When you are done with that, you'll need to stop drawing (with a degenerate) and get a vertex pointer over to a corner on block2's right face (another degenerate), then commit to actually start drawing again with yet another degenerate vertex on block2's right face.

It sounds overly complicated, but I don't believe it to be - I think this is how optimal meshes are output and even Blender, when I draw a mesh like this, will output a similar mesh. Computing truly optimal meshes, however, is proven to be an NP-complete problem.

I did get it functional with something that looks like this:

            new float[]{
//Vertex         Normals      Colors                            Texcoord
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //Degenerate reset
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0,
x, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 0,
x, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 1, // v0-v1-v2front
x, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 0, 1,
x + 1, y, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 1,
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0, // v2-v3-v0
x + 1, y + 1, z + 1, 0, 0, 1, color[0], color[1], color[2], 1, 0, //End this face
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, //Degenerate reset
//Right face
new float[]{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //Degenerate reset
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0,
x + 1, y, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 1,
x + 1, y, z, 1, 0, 0, color[0], color[1], color[2], 1, 1, // v0-v3-v4right
x + 1, y, z, 1, 0, 0, color[0], color[1], color[2], 1, 1,
x + 1, y + 1, z, 1, 0, 0, color[0], color[1], color[2], 1, 0,
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0, // v4-v5-v0
x + 1, y + 1, z + 1, 1, 0, 0, color[0], color[1], color[2], 0, 0,//End this face
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, //Degenerate reset


As you can see, there are several degens in there. Every time a face is drawn, I move the vertex "pointer" from 0,0,0 and start drawing. I restore the degenerate back to 0,0,0  at the end of that face - I need to ensure that no matter where I am in drawing chunks, I won't send OpenGL a bunch of duplicate values. If I tried to draw a block actually at 0,0,0, this scheme would not work because OpenGL would be fed even more degenerates and toggle drawing of those verticies off. The easiest thing to do is start and stop each face with degenerate verticies that you know will never actually need to be drawn.

This all works fine at the moment with a few caveats. Performance is excellent - I get over 300fps on an intel hd 4000 integrated card and over 2000fps on my GTX690 with about 20 million blocks in scene. Of course those 20 million blocks become relatively few faces to actually draw since most are completely concealed - maybe a couple hundred thousand faces actually being drawn.

PARTNERS