Re: XNA Game Studio Express How to set a texture on a model from a composite texture sheet?
Derek Nedelman
Since you'll have 52 cards, you'll want to lay the subtextures out in a grid in a larger texture. The grid will be 8x8. To simplify your runtime logic, you can precalculate all the rectangles (4 vertices) for each subtexture with the following code (where subtexturesWide = 8 and subtexturesHigh = 8)
Vertex[] quadVertices = new Vertex[4 * this.subtexturesWide * this.subtexturesHigh];
float v = 0;
int vertexIndex = 0;
for (int vIndex = 0; vIndex < this.subtexturesHigh; vIndex++)
{
float u = 0;
for (int uIndex = 0; uIndex < this.subtexturesWide; uIndex++)
{
quadVertices[vertexIndex].Set(-.5f, .5f, 0, u, v);
quadVertices[vertexIndex + 1].Set(-.5f, -.5f, 0, u, v + 1.0f / this.subtexturesHigh);
quadVertices[vertexIndex + 2].Set(.5f, -.5f, 0, u + 1.0f / this.subtexturesWide, v + 1.0f / this.subtexturesHigh);
quadVertices[vertexIndex + 3].Set(.5f, .5f, 0, u + 1.0f / this.subtexturesWide, v);
vertexIndex += 4;
u += 1.0f / this.subtexturesWide;
}
v += 1.0f / this.subtexturesHigh;
}
private struct Vertex
{
public void Set(float x, float y, float z, float u, float v)
{
this.x = x;
this.y = y;
this.z = z;
this.u = u;
this.v = v;
}
public float x, y, z;
public float u, v;
public static VertexElement[] Elements =
{
new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
new VertexElement(0, 12, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0)
};
public const int Size = 12 + 8;
}
Then, the index of the first vertex using the desired texture is cardIndex * 4 (assuming your cards go from 0 to 51), which is the index you can pass into one of the DrawPrimitive functions using the PrimitiveType.TriangleFan type.
By the way, you'll notice the above code also creates the positional coordinates for the rectangle to be drawn on the screen. You probably don't need these since you seem to already have a way of determining them.
Also, you may want to leave a 1 pixel border around your subtextures to avoid filtering issues, that is, if you're using anything other than a point min/mag filter.