/// /// 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... }