Oh, sorry. I meant 8 vertices. I’m just so used to looking at them labelled 0-7. (edited the original post)
I don’t actually have code to construct a cube at this point. I have code that draws thousands of them in a minecraft-styled world, with only faces that are exposed being added to the index buffer. I’m just trying to figure out the logic behind texturing them. It was vexing me, but I think I see it now.
http://dl.dropbox.com/u/18809996/cubes.png
This uses a random intensity of a green colour element. But it appears to be per physical vertex.
So two cubes next to each other would have a total of 12 vertices. 48 indices - but then I would remove the adjoining face from each cube, leaving 40 indices. I just need to work out how to define texcoords per index-element rather than per vertex.
The whole idea of using an Index Buffer full of indices, is that you only need to define each vertex (point in space) once, then reference to their position in the Vertex buffer with your indices.
[EDIT: Code that builds the indices and texcoords is below]
This code:
The draw method is called every frame.
buildIndices is called when the current chunk is edited (perhaps once every ten seconds).
buildColours is called instead when I’m debugging.
When using buildColours, the colours are defined per vertex in physical space.
This is the result:
http://dl.dropbox.com/u/18809996/textured.png
This is the texture being bound:
http://dl.dropbox.com/u/18809996/debug.png
This is the code:
public void draw() {
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, _verticesID);
GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
// GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
// ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, _coloursID);
// GL11.glColorPointer(4, GL11.GL_FLOAT, 0, 0);
_texture.bind();
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, _texcoordsID);
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, _indicesID);
GL12.glDrawRangeElements(GL11.GL_QUADS, 0, _indices.limit(), _indices.limit(),
GL11.GL_UNSIGNED_INT, 0);
}
// This adds indices for faces that are exposed (visible)
public void buildIndices(Block[][][] in)
{
int sy = _size.getY() + 1;
int sx = _size.getX() + 1;
int sz = _size.getZ() + 1;
// create indices
_indices = BufferUtils.createIntBuffer(sy * sz * sx * 24);
_texcoords = BufferUtils.createFloatBuffer(sy * sz * sx * 24);
for(int y = 0; y < _size.getY(); y++)
{
for(int z = 0; z < _size.getZ(); z++)
{
for(int x = 0; x < _size.getX(); x++)
{
if(in[x][y][z].getMaterial() != Material.Air)
{
int w = sx;
int d = sz;
int h = sy;
int zw = z * w;
int ywd = y * w * d;
int wd = w * d;
int v0 = x + zw + ywd;
int v1 = v0 + 1;
int v2 = x + w + zw + ywd;
int v3 = v2 + 1;
int v4 = x + wd + zw + ywd;
int v5 = v4 + 1;
int v6 = x + w + wd + zw + ywd;
int v7 = v6 + 1;
float[] tl = new float[] {0.0f, 0.0f}; // Top left of the texture
float[] tr = new float[] {1.0f, 0.0f}; // top right
float[] bl = new float[] {0.0f, 1.0f}; // bottom left
float[] br = new float[] {1.0f, 1.0f}; // bottom right
// "connectivity" is a construct of bools that refer to whether or
// not another block is connected to the face in question.
// true when there is a block next door, which tells us that the
// face is not visible, so don't add its indices to the buffer.
if(!in[x][y][z].getConnectivity().getFaceState(Face.Front))
{
addIndices(new int[] { v0, v1, v5, v4});
addTexcoords(new float[][] {tl, tr, bl, br});
}
if(!in[x][y][z].getConnectivity().getFaceState(Face.Right))
{
addIndices(new int[] { v1, v3, v7, v5});
addTexcoords(new float[][] {tl, tr, bl, br});
}
if(!in[x][y][z].getConnectivity().getFaceState(Face.Back))
{
addIndices(new int[] { v3, v2, v6, v7});
addTexcoords(new float[][] {tl, tr, bl, br});
}
if(!in[x][y][z].getConnectivity().getFaceState(Face.Left))
{
addIndices(new int[] { v2, v0, v4, v6});
addTexcoords(new float[][] {tl, tr, bl, br});
}
if(!in[x][y][z].getConnectivity().getFaceState(Face.Bottom))
{
addIndices(new int[] { v2, v3, v1, v0});
addTexcoords(new float[][] {tl, tr, bl, br});
}
if(!in[x][y][z].getConnectivity().getFaceState(Face.Top))
{
addIndices(new int[] { v4, v5, v7, v6});
addTexcoords(new float[][] {tl, tr, bl, br});
}
}
}
}
}
_indices.flip();
_texcoords.flip();
VBOHandler.bufferElementData(_indicesID, _indices);
VBOHandler.bufferData(_texcoordsID, _texcoords);
}
// I've been using this to debug. It just populates the colour buffer with a random
// intensity of green... Per vertex.
public void buildColours()
{
// create colours
int vl = _vertices.limit() / 3;
_colours = BufferUtils.createFloatBuffer(vl * 4);
Random rand = new Random(System.currentTimeMillis());
for(int x = 0; x < vl; x++)
{
addColour(new float[] {0.0f, 0.8f + (rand.nextFloat() / 5), 0.0f, 0.0f} );
}
_colours.flip();
}