Creating a mesh with multiple subsetsBy Rim van Wersch, March 12 2006 |
A mesh object can be used to hold all geometric data of a game object. The original SDK documentation already shows how to create a mesh with a single subset, but for defining multiple subsets (or attribute ranges) some more work is needed. This little snippet shows how to set up a simple cube with two subsets.
int numberVerts = 8; short[] indices = { ? ? ? ? ? ? ? ? ? ? ? ?0,1,2, // Front Face ? ? ? ? ? ? ? ? ? ? ? ?1,3,2, // Front Face ? ? ? ? ? ? ? ? ? ? ? ?4,5,6, // Back Face ? ? ? ? ? ? ? ? ? ? ? ?6,5,7, // Back Face ? ? ? ? ? ? ? ? ? ? ? ?0,5,4, // Top Face ? ? ? ? ? ? ? ? ? ? ? ?0,2,5, // Top Face ? ? ? ? ? ? ? ? ? ? ? ?1,6,7, // Bottom Face ? ? ? ? ? ? ? ? ? ? ? ?1,7,3, // Bottom Face ? ? ? ? ? ? ? ? ? ? ? ?0,6,1, // Left Face ? ? ? ? ? ? ? ? ? ? ? ?4,6,0, // Left Face ? ? ? ? ? ? ? ? ? ? ? ?2,3,7, // Right Face ? ? ? ? ? ? ? ? ? ? ? ?5,2,7 // Right Face ? ? ? ? ? ? ? ? ? ?}; // create the mesh object Mesh mesh = new Mesh(indices.Length / 3, numberVerts, MeshFlags.Managed, ? ?CustomVertex.PositionColored.Format, device); // set vertex buffer data using(VertexBuffer vb = mesh.VertexBuffer) { ? ?GraphicsStream data = vb.Lock(0, 0, LockFlags.None); ? ?data.Write(new CustomVertex.PositionColored(-1.0f, 1.0f, 1.0f, 0x00ff00ff)); ? ?data.Write(new CustomVertex.PositionColored(-1.0f, -1.0f, 1.0f, 0x00ffff00)); ? ?data.Write(new CustomVertex.PositionColored(1.0f, 1.0f, 1.0f, 0x0000ffff)); ? ?data.Write(new CustomVertex.PositionColored(1.0f, -1.0f, 1.0f, 0x00ff0000)); ? ?data.Write(new CustomVertex.PositionColored(-1.0f, 1.0f, -1.0f, 0x000000ff)); ? ?data.Write(new CustomVertex.PositionColored(1.0f, 1.0f, -1.0f, 0x0000ff00)); ? ?data.Write(new CustomVertex.PositionColored(-1.0f, -1.0f, -1.0f, 0x00ffffff)); ? ?data.Write(new CustomVertex.PositionColored(1.0f, -1.0f, -1.0f, 0x00000000)); ? ?vb.Unlock(); } // set index buffer data using (IndexBuffer ib = mesh.IndexBuffer) { ? ?ib.SetData(indices, 0, LockFlags.None); } // Set attribute buffer data, setting the attribute // ID (subset #) for each face in the attribute buffer int[] attribBuffer = mesh.LockAttributeBufferArray(LockFlags.None); ? ? // first 6 faces will be subset 0 for( int i = 0; i < 6; i++) { ? ?attribBuffer[i] = 0; } // last 6 faces will be subset 1 for( int i = 0; i < 6; i++) { ? ?attribBuffer[i + 6] = 1; } // unlock and update the buffer mesh.UnlockAttributeBuffer(attribBuffer); // Here we manually create the attribute table for the mesh, // notice that this does NOT affect the vertices, but only // updates the internal attribute table for future reference. AttributeRange subset1 = new AttributeRange(); subset1.AttributeId = 0; ? ? ? ? ? ? subset1.FaceStart = 0; subset1.FaceCount = 6; subset1.VertexCount = 36; subset1.VertexStart = 0; AttributeRange subset2 = new AttributeRange(); subset2.AttributeId = 1; ? ? ? ? ? ? subset2.FaceStart = 6; subset2.FaceCount = 6; subset2.VertexCount = 36; subset2.VertexStart = 0; mesh.SetAttributeTable( ? ?new AttributeRange[] ? ?{ ? ? ? ?subset1, ? ? ? ?subset2 ? ?}); // Updating the attribute table can also be done automatically // by optimizing the mesh in place, like this: /* ? ?int[] adj = new int[indices.Length]; ? ?mesh.GenerateAdjacency(0.1f, adj); ? ?mesh.OptimizeInPlace( MeshFlags.OptimizeAttributeSort, adj); */ System.Diagnostics.Debug.WriteLine("New number of subsets in mesh: " + mesh.NumberAttributes);
Further reading
?