View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# [SlimDX] Mesh utility functions (source included)

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

2 replies to this topic

### #1Gage64  Members

Posted 25 September 2009 - 04:38 AM

Currently I have functions to:

* Compute a bounding sphere/box
* Compute texture coordinates

Here's the code:

public static BoundingSphere ComputeBoundingSphere(Mesh mesh)
{
List<Vector3> verts = new List<Vector3>(mesh.VertexCount);

while (ds.Position < ds.Length)
{
long oldPos = ds.Position;

ds.Position = oldPos + mesh.BytesPerVertex;
}

mesh.UnlockVertexBuffer();

return BoundingSphere.FromPoints(verts.ToArray());
}

public static BoundingBox ComputeBoundingBox(Mesh mesh)
{
List<Vector3> verts = new List<Vector3>(mesh.VertexCount);

while (ds.Position < ds.Length)
{
long oldPos = ds.Position;

ds.Position = oldPos + mesh.BytesPerVertex;
}

mesh.UnlockVertexBuffer();

return BoundingBox.FromPoints(verts.ToArray());
}

public static int FindElementIndex(VertexElement[] elems, DeclarationUsage usage)
{
for (int i = 0; i < elems.Length; ++i)
{
if (elems[i].Usage == usage)
return i;
}

return -1;
}

// This code uses the methods described in:
// www.mvps.org/directx/articles/spheremap.htm
public static void ComputeTexCoords(Device device, ref Mesh mesh, bool useNormals)
{
if (useNormals)
{
if ((mesh.VertexFormat & VertexFormat.Normal) == 0)
{
mesh.ComputeNormals();
}
}

// Make room for texture coordinates
// The 'newMesh' variable is not needed anymore. The extra {} ensure that it is not used accidentally
{
Mesh newMesh = mesh.Clone(device, mesh.CreationOptions, mesh.VertexFormat | VertexFormat.Texture1);
mesh.Dispose();
mesh = newMesh;
}

VertexElement[] elems = mesh.GetDeclaration();
int posElem       = FindElementIndex(elems, DeclarationUsage.Position);
int normalElem    = FindElementIndex(elems, DeclarationUsage.Normal);
int texCoordsElem = FindElementIndex(elems, DeclarationUsage.TextureCoordinate);

// Needed for positional spherical mapping
BoundingBox bbox = ComputeBoundingBox(mesh);

DataStream ds = mesh.LockVertexBuffer(LockFlags.None);

while (ds.Position < ds.Length)
{
long oldPos = ds.Position;

Vector3 vec;
if (useNormals)     // Spherical mapping with normals
{
ds.Position += elems[normalElem].Offset;
ds.Position = oldPos;
}
else                // Spherical mapping with positions
{
ds.Position += elems[posElem].Offset;
ds.Position = oldPos;

Vector3 center = (bbox.Minimum + bbox.Maximum) * 0.5f;
vec = Vector3.Normalize(pos - center);
}

float u = (float)Math.Asin(vec.X) / (float)Math.PI + 0.5f;
float v = (float)Math.Asin(vec.Y) / (float)Math.PI + 0.5f;

ds.Position += elems[texCoordsElem].Offset;
ds.Write<float>(u);
ds.Write<float>(v);

ds.Position = oldPos + mesh.BytesPerVertex;
}

mesh.UnlockVertexBuffer();
}



The functions seem to work, but I have not tested them thoroughly, so I can't say that with full certainty. If you see any errors, please let me know.

I'm also not too happy with the implementation, mostly because there's a lot of duplicate code. If you know of a better way to do this sort of thing, I would love to hear about it.

I hope this will be useful to someone.

### #2Mike.Popoloski  Members

Posted 25 September 2009 - 05:29 AM

You can cut down on a lot of that code by using a little LINQ and a few helper methods that exist in SlimDX already. This is how I'd write the function. It should be the same thing, although I wrote it on the fly so it might have a few typos:

public static Mesh ComputeTextureCoords(Device device, Mesh mesh, bool useNormals){    if (useNormals && (mesh.VertexFormat & VertexFormat.Normal) == 0)        mesh.ComputeNormals();    mesh = mesh.Clone(device, mesh.CreationOptions, mesh.VertexFormat | VertexFormat.Texture1);    var elements = mesh.GetDeclaration();    var dataStream = mesh.LockVertexBuffer(LockFlags.None);    var box = BoundingBox.FromPoints(D3DX.GetVectors(dataStream, mesh.VertexCount, mesh.BytesPerVertex));    var center = (box.Minimum + box.Maximum) * 0.5f;    dataStream.Position = elements.FirstOrDefault(e => useNormals ? e.Usage == DeclarationUsage.Normal : e.Usage == DeclarationUsage.Position).Offset;    var vectors = D3DX.GetVectors(dataStream, mesh.VertexCount, mesh.BytesPerVertex).Select(v => useNormals ? v : Vector3.Normalize(v - center));    dataStream.Position = elements.FirstOrDefault(e => e.Usage == DeclarationUsage.TextureCoordinate).Offset;    foreach (var vector in vectors)    {        dataStream.Write((float)(Math.Asin(vector.X) / Math.PI + 0.5));        dataStream.Write((float)(Math.Asin(vector.Y) / Math.PI + 0.5));        dataStream.Position += mesh.BytesPerVertex - (sizeof(float) * 2);    }    mesh.UnlockVertexBuffer();    return mesh;}

Mike Popoloski | Journal | SlimDX

### #3Gage64  Members

Posted 25 September 2009 - 05:42 AM

Thanks. I'm still not familiar with the C# 3.0 features but that does look pretty nice.

Also, I somehow managed to miss the D3DX class...

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.