///
/// A data structure to hold a list of CollisionMesh objects with quick access geometry data.
///
public class CollisionModel : AccessibleModel
{
///
/// number of divisions to apply to the octree
///
private uint maxTreeDivisions;
///
/// the threshold limit for leaf node volume
///
private float minTreeNodeVolume;
///
/// constructor with a default XNA model located in the specified file location
///
/// a name for the object
/// the game object
///
/// the maximum number of times to subdivide the octree
/// the path to a model file to load into this accessible model
public CollisionModel(string newName, TwelveCylinderGame newGame,
float newLeafNodeVolume, uint newMaxTreeDivisions, string newModelFile)
: base(newName, newGame, newModelFile)
{
minTreeNodeVolume = newLeafNodeVolume;
maxTreeDivisions = newMaxTreeDivisions;
createCollisionTrees(minTreeNodeVolume);
}
///
/// Creates an array of meshes from the (XNA class) input Model.
/// This method overrides its parent's method and creates CollisionMesh
/// objects instead of AccessibleMesh objects.
///
/// the XNA Model object
protected override void initFromModel(Model newModel)
{
meshCount = newModel.Meshes.Count;
triangleCount = 0;
vertexCount = 0;
mMeshes = new CollisionMesh[meshCount];
for (int i = 0; i < meshCount; i++)
{
//create collision mesh objects which make up this collision model...
mMeshes[i] = new CollisionMesh(newModel.Meshes[i].Name, curGame, newModel.Meshes[i]);
this.addChild(mMeshes[i]); //loads world position data
//sum number of primitives
triangleCount += mMeshes[i].FaceCount;
vertexCount += mMeshes[i].VertexCount;
}
}
///
/// create collision tree definitions for each mesh in this model
///
protected virtual void createCollisionTrees(float newLeafNodeVolume)
{
foreach(CollisionMesh mesh in mMeshes)
mesh.createCollisionTree(maxTreeDivisions, newLeafNodeVolume);
}
//encapsulators omitted
///
/// gets the collision mesh at the specified index
///
/// a mesh index
/// the collision mesh
public CollisionMesh getCollisionMesh(int index)
{
return (mMeshes[index] as CollisionMesh);
}
///
/// find the first (if any) collision between the
/// specified moving box and this CollisionModel
///
/// input description of the moving box to test for collisions
/// output distance from box's starting position to collision point
/// output position at which the collision occured
/// output normal of the surface at the collision point
/// returns true if an intersection occured
public bool BoxIntersect(MovingBoxData boxData, out float collisionDistance,
out Vector3 collisionPosition, out Vector3 collisionNormal)
{
collisionDistance = boxData.OffsetLength;
collisionPosition = boxData.WorldEnd;
collisionNormal = Vector3.Zero;
if (mMeshes == null || mMeshes.Length == 0)
return false;
bool collision = false;
float distance;
Vector3 position;
Vector3 normal;
//find first collision occurence
foreach (CollisionMesh mesh in mMeshes)
{
if (mesh.Tree.BoxIntersect(boxData, out distance, out position, out normal))
{
//intersection found
if (distance < collisionDistance)
{
//current intersect distance
//is less than any previous
collisionDistance = distance; //output distance
collisionPosition = position; //output position
collisionNormal = normal; //output normal at collision point
collision = true;
}
}
}
return collision;
}
//point intersection omitted...
}