Uncategorized

Per Mesh Bounding Box tutorial

This article will show you how to build a dictionary of bounding boxes and link them in the code.

Why ? Because many times, the model you want to use in your game is quite complex and it’s build upon many meshes. And you may need to know, for example, if a certain part is clicked. If you have axis oriented objects (maybe walls, floors, etc) this solution can help you.

Solution: It’s quite simple. Since I don’t have much time for posting I’ll just post both, the processor and the code needed to access the boxes. Also, I’ll leave some tips.

First, this is the code for the processor:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

namespace PerMeshBoundingBox
{
    [ContentProcessor(DisplayName = "CustomModelProcessor")]
    public class CustomModelProcessor :
        ModelProcessor
    {
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            ModelContent output = base.Process(input, context);

            // stores a bounding box per mesh inside the model - we link the bounding box to the mesh using it's name
            Dictionary<string, BoundingBox> boundingBoxes = new Dictionary<string, BoundingBox>();

            foreach (NodeContent currentNodeContent in input.Children)
            {
                // data needed to build a bounding box
                float minX = float.MaxValue;
                float minY = float.MaxValue;
                float minZ = float.MaxValue;
                float maxX = float.MinValue;
                float maxY = float.MinValue;
                float maxZ = float.MinValue;

                if (currentNodeContent is MeshContent)
                {
                    MeshContent meshContent = (MeshContent)currentNodeContent;

                    foreach (Vector3 basev in meshContent.Positions)
                    {
                        Vector3 v = basev;
                        if (v.X < minX)
                            minX = v.X;

                        if (v.Y < minY)
                            minY = v.Y;

                        if (v.Z < minZ)
                            minZ = v.Z;

                        if (v.X > maxX)
                            maxX = v.X;

                        if (v.Y > maxY)
                            maxY = v.Y;

                        if (v.Z > maxZ)
                            maxZ = v.Z;
                    }

                    // creates a new bounding box associated to the mesh name
                    string meshName = currentNodeContent.Name;
                    BoundingBox boundingBox = 
                        new BoundingBox(new Vector3((float)minX, (float)minY, -(float)minZ),
                            new Vector3((float)maxX, (float)maxY, -(float)maxZ));

                    boundingBoxes.Add(meshName, boundingBox);
                }
            }
            // stores the bounding box inside the tag property
            output.Tag = boundingBoxes;

            return output;
        }
    }
}

This processor will store a dictionary of bounding boxes inside the Tag property of a model. What’s important here is that each bounding box is linked to the mesh using the mesh name.

The code needed to grab the boxes can be something like this:

Dictionary<string, BoundingBox> sceneBoundingBoxes = 
                (Dictionary<string, BoundingBox>)model.Tag;            

And what’s most important. You have to transform each box according to the mesh bones.

Matrix transforms = Matrix.CreateTranslation(position);

Matrix[] bones = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(bones);

foreach (ModelMesh mesh in model.Meshes)
{                
    BoundingBox currentBoundingBox = sceneBoundingBoxes[mesh.Name];
    currentBoundingBox.Max = 
        Vector3.Transform(currentBoundingBox.Max, bones[mesh.ParentBone.Index] * transforms);
    currentBoundingBox.Min = 
        Vector3.Transform(currentBoundingBox.Min, bones[mesh.ParentBone.Index] * transforms);
}  

The code above this line just transform the bounding box according some position (for example, some place where you are placing a model). Note you can add any transform you want.

IMPORTANT

Just as I pointed in the last tutorial, This WONT WORK if you are not applying the transformations to the model in your design program. In blender, before exporting, you have to select the models you are exporting and click CONTROL + A + 1 (what the tutorial on how to export models to blender).

2 thoughts on “Per Mesh Bounding Box tutorial”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s