/// <summary> /// Add the collision data for an object. This involves looking /// for a physics file that matches the mesh file's name, and /// loading the information from that file to build collision /// volumes. /// </summary> /// <param name="objNode">the object for which we are adding the collision data</param> public void AddCollisionObject(ObjectNode objNode) { if (worldManager.CollisionHelper == null) { return; } if (!objNode.UseCollisionObject) { return; } // Create a set of collision shapes for the object List <CollisionShape> shapes = new List <CollisionShape>(); string meshName = objNode.Entity.Mesh.Name; PhysicsData pd = new PhysicsData(); PhysicsSerializer ps = new PhysicsSerializer(); bool static_object = true; if ((objNode.ObjectType == ObjectNodeType.Npc) || (objNode.ObjectType == ObjectNodeType.User)) { static_object = false; } if (meshName.EndsWith(".mesh")) { string physicsName = meshName.Substring(0, meshName.Length - 5) + ".physics"; try { Stream stream = ResourceManager.FindCommonResourceData(physicsName); ps.ImportPhysics(pd, stream); foreach (SubEntity subEntity in objNode.Entity.SubEntities) { if (subEntity.IsVisible) { string submeshName = subEntity.SubMesh.Name; List <CollisionShape> subEntityShapes = pd.GetCollisionShapes(submeshName); foreach (CollisionShape subShape in subEntityShapes) { // static objects will be transformed here, but movable objects // are transformed on the fly if (static_object) { subShape.Transform(objNode.SceneNode.DerivedScale, objNode.SceneNode.DerivedOrientation, objNode.SceneNode.DerivedPosition); } shapes.Add(subShape); log.DebugFormat("Added collision shape for oid {0}, subShape {1}, subMesh {2}", objNode.Oid, subShape, submeshName); } } } // Now populate the region volumes foreach (KeyValuePair <string, List <CollisionShape> > entry in pd.CollisionShapes) { string regionName = RegionVolumes.ExtractRegionName(entry.Key); if (regionName != "") { // We must record this region - - must be // a static object Debug.Assert(static_object); List <CollisionShape> subShapes = new List <CollisionShape>(); foreach (CollisionShape subShape in entry.Value) { subShape.Transform(objNode.SceneNode.DerivedScale, objNode.SceneNode.DerivedOrientation, objNode.SceneNode.DerivedPosition); subShapes.Add(subShape); } RegionVolumes.Instance.AddRegionShapes(objNode.Oid, regionName, subShapes); } } } catch (Exception) { // Unable to load physics data -- use a sphere or no collision data? log.InfoFormat("Unable to load physics data: {0}", physicsName); //// For now, I'm going to put in spheres. Later I should do something real. //CollisionShape shape = new CollisionSphere(Vector3.Zero, Client.OneMeter); //if (static_object) // // static objects will be transformed here, but movable objects // // are transformed on the fly // shape.Transform(objNode.SceneNode.DerivedScale, // objNode.SceneNode.DerivedOrientation, // objNode.SceneNode.DerivedPosition); //shapes.Add(shape); } } if (static_object) { foreach (CollisionShape shape in shapes) { worldManager.CollisionHelper.AddCollisionShape(shape, objNode.Oid); } objNode.CollisionShapes = shapes; } else { MovingObject mo = new MovingObject(worldManager.CollisionHelper); foreach (CollisionShape shape in shapes) { worldManager.CollisionHelper.AddPartToMovingObject(mo, shape); } objNode.Collider = mo; objNode.Collider.Transform(objNode.SceneNode.DerivedScale, objNode.SceneNode.DerivedOrientation, objNode.SceneNode.DerivedPosition); } }
public static void ExtractCollisionShapes(Mesh mesh, string path) { PhysicsData physicsData = null; List <string> deleteEm = new List <string>(); int count = mesh.SubMeshCount; for (int i = 0; i < count; i++) { SubMesh subMesh = mesh.GetSubMesh(i); CollisionShape shape = null; string targetName = null; bool cv = String.Compare(subMesh.Name.Substring(0, 5), "mvcv_", false) == 0; bool rg = String.Compare(subMesh.Name.Substring(0, 5), "mvrg_", false) == 0; int firstIndex = 0; if (cv) { firstIndex = 5; } else if (rg) { string rest = subMesh.Name.Substring(5); firstIndex = rest.IndexOf("_") + 1 + 5; } if (cv || rg) { // It's probably a collision volume - - check the // shape type to make sure if (String.Compare(subMesh.Name.Substring(firstIndex, 4), "obb_", false) == 0) { shape = ExtractBox(subMesh); } else if (String.Compare(subMesh.Name.Substring(firstIndex, 5), "aabb_", false) == 0) { shape = ExtractBox(subMesh); } else if (String.Compare(subMesh.Name.Substring(firstIndex, 7), "sphere_", false) == 0) { shape = ExtractSphere(subMesh); } else if (String.Compare(subMesh.Name.Substring(firstIndex, 8), "capsule_", false) == 0) { shape = ExtractCapsule(subMesh); } if (shape != null) { targetName = GetTargetSubmesh(mesh, subMesh.Name); } } if (shape != null) { deleteEm.Add(subMesh.Name); if (physicsData == null) { physicsData = new PhysicsData(); } physicsData.AddCollisionShape(targetName, shape); } } for (int i = 0; i < deleteEm.Count; i++) { mesh.RemoveSubMesh(deleteEm[i]); } if (physicsData != null) { PhysicsSerializer serializer = new PhysicsSerializer(); serializer.ExportPhysics(physicsData, path + ".physics"); } if (DoLog) { CloseLog(); } }