Here's how I did it, allowing a single flattened cube texture (with 6 different sides) to map onto the individual sides of the cube.
1. Created a variant of populateAsSolidBox (see CC3MeshNode.m) that has the texture coordinate mappings. I wasn't sure how to do this with indexed vertices (since they share vertices) and still have the texture mappings work right, so I removed the whole indexing part and just supplied the 36 individual vertices based on the vertices referred to in solidBoxIndexData. (There probably is a more efficient way, but this works, and I'm an OpenGL newbie, and we don't need to deal with 6 extra rectangle nodes to add some texture)
2. Supplied a single texture file, that looks like a cube opened up and rolled out, so that there are all the different sides.
Here's the png file:
http://f.cl.ly/items/0Y0h1t3l421A2S152K3j/color_cube.png
3. Applied that texture to the cube's material.
Here's the code:
This is a method I added to CC3MeshNode.m (for simplicity only, you should do all the proper object oriented stuff, so that you can upgrade your cocos3d more easily)
static const float solidBoxNormals[8][3] = {
{-1, -1, -1},
{-1, -1, 1},
{-1, 1, -1},
{-1, 1, 1},
{1, -1, -1},
{1, -1, 1},
{1, 1, -1},
{1, 1, 1}
};
-(void) populateAsSolidBox2: (CC3BoundingBox) box {
NSString* itemName;
CC3TexturedVertex* vertices; // Array of custom structures to hold the interleaved vertex data
CC3Vector boxMin = box.minimum;
CC3Vector boxMax = box.maximum;
GLuint vertexCount = 36;
// Create vertexLocation array.
itemName = [NSString stringWithFormat: @"%@-Locations", self.name];
CC3VertexLocations* locArray = [CC3VertexLocations vertexArrayWithName: itemName];
locArray.elementStride = sizeof(CC3TexturedVertex); // Set stride before allocating elements.
locArray.elementOffset = 0; // Offset to location element in vertex structure
vertices = [locArray allocateElements: vertexCount];
locArray.drawingMode = GL_TRIANGLES;
// Extract all 8 corner vertices from the box.
vertices[0].location = cc3v(boxMin.x, boxMin.y, boxMax.z);
vertices[1].location = cc3v(boxMax.x, boxMin.y, boxMax.z);
vertices[2].location = cc3v(boxMax.x, boxMax.y, boxMax.z);
vertices[3].location = cc3v(boxMax.x, boxMax.y, boxMax.z);
vertices[4].location = cc3v(boxMin.x, boxMax.y, boxMax.z);
vertices[5].location = cc3v(boxMin.x, boxMin.y, boxMax.z);
vertices[6].location = cc3v(boxMin.x, boxMin.y, boxMin.z);
vertices[7].location = cc3v(boxMin.x, boxMin.y, boxMax.z);
vertices[8].location = cc3v(boxMin.x, boxMax.y, boxMax.z);
vertices[9].location = cc3v(boxMin.x, boxMax.y, boxMax.z);
vertices[10].location = cc3v(boxMin.x, boxMax.y, boxMin.z);
vertices[11].location = cc3v(boxMin.x, boxMin.y, boxMin.z);
vertices[12].location = cc3v(boxMax.x, boxMin.y, boxMin.z);
vertices[13].location = cc3v(boxMin.x, boxMin.y, boxMin.z);
vertices[14].location = cc3v(boxMin.x, boxMax.y, boxMin.z);
vertices[15].location = cc3v(boxMin.x, boxMax.y, boxMin.z);
vertices[16].location = cc3v(boxMax.x, boxMax.y, boxMin.z);
vertices[17].location = cc3v(boxMax.x, boxMin.y, boxMin.z);
vertices[18].location = cc3v(boxMax.x, boxMin.y, boxMax.z);
vertices[19].location = cc3v(boxMax.x, boxMin.y, boxMin.z);
vertices[20].location = cc3v(boxMax.x, boxMax.y, boxMin.z);
vertices[21].location = cc3v(boxMax.x, boxMax.y, boxMin.z);
vertices[22].location = cc3v(boxMax.x, boxMax.y, boxMax.z);
vertices[23].location = cc3v(boxMax.x, boxMin.y, boxMax.z);
vertices[24].location = cc3v(boxMin.x, boxMax.y, boxMax.z);
vertices[25].location = cc3v(boxMax.x, boxMax.y, boxMax.z);
vertices[26].location = cc3v(boxMax.x, boxMax.y, boxMin.z);
vertices[27].location = cc3v(boxMax.x, boxMax.y, boxMin.z);
vertices[28].location = cc3v(boxMin.x, boxMax.y, boxMin.z);
vertices[29].location = cc3v(boxMin.x, boxMax.y, boxMax.z);
vertices[30].location = cc3v(boxMin.x, boxMin.y, boxMin.z);
vertices[31].location = cc3v(boxMax.x, boxMin.y, boxMin.z);
vertices[32].location = cc3v(boxMax.x, boxMin.y, boxMax.z);
vertices[33].location = cc3v(boxMax.x, boxMin.y, boxMax.z);
vertices[34].location = cc3v(boxMin.x, boxMin.y, boxMax.z);
vertices[35].location = cc3v(boxMin.x, boxMin.y, boxMin.z);
// Create the normal array interleaved on the same element array
itemName = [NSString stringWithFormat: @"%@-Normals", self.name];
CC3VertexNormals* normArray = [CC3VertexNormals vertexArrayWithName: itemName];
normArray.elements = vertices;
normArray.elementStride = locArray.elementStride; // Interleaved...so same stride
normArray.elementCount = vertexCount;
normArray.elementOffset = sizeof(CC3Vector); // Offset to normal element in vertex structure
// Since this is a box, and all sides meet at right angles, all components
// of all normals will have a value of either positive or negative (1 / sqrt(3)).
GLfloat oort = 1.0f / M_SQRT3; // One-over-root-three
// Populate normals up the positive Z-axis
for(int i=0; i < vertexCount; i++)
{
const float *oorts = solidBoxNormals[solidBoxIndexData[i]];
vertices[i].normal = cc3v(oorts[0]*oort, oorts[1]*oort, oorts[2]*oort);
}
// Create mesh with interleaved vertex arrays
itemName = [NSString stringWithFormat: @"%@-Mesh", self.name];
CC3VertexArrayMesh* aMesh = [CC3VertexArrayMesh meshWithName: itemName];
aMesh.interleaveVertices = YES;
aMesh.vertexLocations = locArray;
aMesh.vertexNormals = normArray;
// Create the tex coord array interleaved on the same element array as the vertex locations
CC3VertexTextureCoordinates* tcArray = nil;
tcArray = [CC3VertexTextureCoordinates vertexArray];
tcArray.elements = locArray.elements;
tcArray.elementStride = locArray.elementStride; // Interleaved...so same stride
tcArray.elementCount = locArray.elementCount;
tcArray.elementOffset = 2 * sizeof(CC3Vector); // Offset to texcoord element in vertex structure
// Populate the texture coordinate array mapping
CC3TexturedVertex* tv = (CC3TexturedVertex *) locArray.elements;
// top
tv[0].texCoord = (ccTex2F){0.25f, 0.25f};
tv[1].texCoord = (ccTex2F){0.50f, 0.25f};
tv[2].texCoord = (ccTex2F){0.50f, 0.00f};
tv[3].texCoord = (ccTex2F){0.50f, 0.00f};
tv[4].texCoord = (ccTex2F){0.25f, 0.00f};
tv[5].texCoord = (ccTex2F){0.25f, 0.25f};
// left
tv[6].texCoord = (ccTex2F){0.25f, 0.50f};
tv[7].texCoord = (ccTex2F){0.25f, 0.25f};
tv[8].texCoord = (ccTex2F){0.00f, 0.25f};
tv[9].texCoord = (ccTex2F){0.00f, 0.25f};
tv[10].texCoord = (ccTex2F){0.00f, 0.50f};
tv[11].texCoord = (ccTex2F){0.25f, 0.50f};
// bottom
tv[12].texCoord = (ccTex2F){0.50f, 0.50f};
tv[13].texCoord = (ccTex2F){0.25f, 0.50f};
tv[14].texCoord = (ccTex2F){0.25f, 0.75f};
tv[15].texCoord = (ccTex2F){0.25f, 0.75f};
tv[16].texCoord = (ccTex2F){0.50f, 0.75f};
tv[17].texCoord = (ccTex2F){0.50f, 0.50f};
// right
tv[18].texCoord = (ccTex2F){0.50f, 0.25f};
tv[19].texCoord = (ccTex2F){0.50f, 0.50f};
tv[20].texCoord = (ccTex2F){0.75f, 0.50f};
tv[21].texCoord = (ccTex2F){0.75f, 0.50f};
tv[22].texCoord = (ccTex2F){0.75f, 0.25f};
tv[23].texCoord = (ccTex2F){0.50f, 0.25f};
// back
tv[24].texCoord = (ccTex2F){1.00f, 0.25f};
tv[25].texCoord = (ccTex2F){0.75f, 0.25f};
tv[26].texCoord = (ccTex2F){0.75f, 0.50f};
tv[27].texCoord = (ccTex2F){0.75f, 0.50f};
tv[28].texCoord = (ccTex2F){1.00f, 0.50f};
tv[29].texCoord = (ccTex2F){1.00f, 0.25f};
// front
tv[30].texCoord = (ccTex2F){0.25f, 0.50f};
tv[31].texCoord = (ccTex2F){0.50f, 0.50f};
tv[32].texCoord = (ccTex2F){0.50f, 0.25f};
tv[33].texCoord = (ccTex2F){0.50f, 0.25f};
tv[34].texCoord = (ccTex2F){0.25f, 0.25f};
tv[35].texCoord = (ccTex2F){0.25f, 0.50f};
// Add the texture coordinates array to the mesh
aMesh.vertexTextureCoordinates = tcArray;
self.mesh = aMesh;
}
And then just add the texture to the material and assign the material to the cube.