Create a Level from a Model

Discuss topics related to BEPUphysics or physics engine development.
Post Reply
Dart
Posts: 5
Joined: Sun Apr 24, 2011 5:40 pm

Create a Level from a Model

Post by Dart »

I just finished making this. Figured I'd post it for whoever.

This script goes through all the meshes in a model and creates a Box entity with the same position, orientation, and scale as the mesh. (So it's designed for levels made with cubes/rectangles.)

Code: Select all

foreach (ModelMesh mesh in Models.LEVEL01.Meshes)
{
Vector3 _scale = Vector3.Zero;
Quaternion _rot = Quaternion.Identity;
Vector3 _position = Vector3.Zero;

// Note: This will return the wrong scale. The correct scale is calculated later.
transforms[mesh.ParentBone.Index].Decompose(out _scale, out _rot, out _position);

// Note: Not my code, though I made very slight modifications to it.
// Credit: http://www.toymaker.info/Games/XNA/html/xna_bounding_box.html
#region Get Proper Scale

//Create variables to hold min and max xyz values for the mesh. Initialise them to extremes
Vector3 meshMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);
Vector3 meshMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);

// There may be multiple parts in a mesh (different materials etc.) so loop through each
foreach (ModelMeshPart part in mesh.MeshParts)
{
// The stride is how big, in bytes, one vertex is in the vertex buffer
// We have to use this as we do not know the make up of the vertex
int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

byte[] vertexData = new byte[stride * part.NumVertices];
part.VertexBuffer.GetData(part.VertexOffset * stride, vertexData, 0, part.NumVertices, 1); // fixed 13/4/11

// Find minimum and maximum xyz values for this mesh part
// We know the position will always be the first 3 float values of the vertex data
Vector3 vertPosition = new Vector3();
for (int ndx = 0; ndx < vertexData.Length; ndx += stride)
{
vertPosition.X = BitConverter.ToSingle(vertexData, ndx);
vertPosition.Y = BitConverter.ToSingle(vertexData, ndx + sizeof(float));
vertPosition.Z = BitConverter.ToSingle(vertexData, ndx + sizeof(float) * 2);

// update our running values from this vertex
meshMin = Vector3.Min(meshMin, vertPosition);
meshMax = Vector3.Max(meshMax, vertPosition);
}
}

_scale = meshMax - meshMin;

#endregion

// Create simple the box
Box b = box[mesh.ParentBone.Index] = new Box(Vector3.Zero, 0, 0, 0);

// Box's position
b.Position = new Vector3(_position.X, _position.Y, _position.Z);
b.Position += Vector3.Transform(new Vector3(0, _scale.Y * (_rot == Quaternion.Identity ? -1 : 1) / 2, 0), _rot);

// Box's orientation
b.Orientation = _rot;

// Box's scale
b.Length = _scale.Z * 2;
b.Width = _scale.X * 2;
b.Height = _scale.Y;

space.Add(b);
}
Notes: You may need to alter the Box's scale and position based on your models scale.
There is one bug, but I have no idea what causes it. Sometimes boxes wont be lined up, to fix it just rotate the model by 180 degrees vertically.

A model in 3DS Max made out of blocks. (You could use any shape. But the script would still turn it into a Box)
Image

In game. (Debug shapes being drawn overtop of the model)
Image
Kataan
Posts: 10
Joined: Tue Mar 22, 2011 10:57 am

Re: Create a Level from a Model

Post by Kataan »

Thanks Dart,

Very kind of you to share. :)
Post Reply