/// <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> private void AddCollisionObject(Entity modelEntity, SceneNode modelSceneNode, long oid, string physicsName) { // Create a set of collision shapes for the object List<CollisionShape> shapes = new List<CollisionShape>(); PhysicsData pd = new PhysicsData(); PhysicsSerializer ps = new PhysicsSerializer(); try { Stream stream = ResourceManager.FindCommonResourceData(physicsName); ps.ImportPhysics(pd, stream); for (int i=0; i<modelEntity.SubEntityCount; i++) { SubEntity subEntity = modelEntity.GetSubEntity(i); 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 subShape.Transform(modelSceneNode.DerivedScale, modelSceneNode.DerivedOrientation, modelSceneNode.DerivedPosition); shapes.Add(subShape); log.InfoFormat("Added collision shape: {0} for {1}", subShape, submeshName); } } } } catch (Exception e) { // Unable to load physics data -- use a sphere or no collision data? log.WarnFormat("Unable to load physics data: {0}", e); } foreach (CollisionShape shape in shapes) collisionManager.AddCollisionShape(shape, oid); }
/// <summary> /// Return the untransformed collision shapes associated /// with a mesh. If they are already encached, return them, /// else look for a physics file that matches the mesh /// file's name, and load the information from that file to /// build the collision shapes. /// </summary> public List<CollisionShape> FindMeshCollisionShapes(string meshName, Entity entity) { if (collisionManager == null) { Axiom.Core.LogManager.Instance.Write("DisplayObject.collisionManager is null!"); return null; } List<CollisionShape> shapes; if (!WorldEditor.Instance.MeshCollisionShapes.TryGetValue(meshName, out shapes)) { string physicsName = Path.GetFileNameWithoutExtension(meshName) + ".physics"; // Create a set of collision shapes for the object shapes = new List<CollisionShape>(); PhysicsData pd = new PhysicsData(); PhysicsSerializer ps = new PhysicsSerializer(); try { Stream stream = ResourceManager.FindCommonResourceData(physicsName); ps.ImportPhysics(pd, stream); for (int i = 0; i < entity.SubEntityCount; i++) { SubEntity subEntity = entity.GetSubEntity(i); if (subEntity.IsVisible) { string submeshName = subEntity.SubMesh.Name; List<CollisionShape> subEntityShapes = pd.GetCollisionShapes(submeshName); foreach (CollisionShape subShape in subEntityShapes) { // Clone the shape, and add to the list of // untransformed shapes shapes.Add(subShape); } } } } catch (Exception e) { // Unable to load physics data -- use a sphere or no collision data? Axiom.Core.LogManager.Instance.Write("Unable to load physics data: " + e); shapes = new List<CollisionShape>(); } WorldEditor.Instance.MeshCollisionShapes[meshName] = shapes; } List<CollisionShape> newShapes = new List<CollisionShape>(); foreach (CollisionShape shape in shapes) newShapes.Add(shape.Clone()); return newShapes; }
private static void TestPhysics( string srcDir, string dstDir, string name ) { float OneMeter = 1000; PhysicsData pd = new PhysicsData(); Vector3 center = new Vector3( 10 * OneMeter, 1 * OneMeter, 1 * OneMeter ); Vector3[] obbAxes = new Vector3[ 3 ]; obbAxes[ 0 ] = new Vector3( 1, 0, -1 ); obbAxes[ 0 ].Normalize(); obbAxes[ 1 ] = Vector3.UnitY; obbAxes[ 2 ] = new Vector3( 1, 0, 1 ); obbAxes[ 2 ].Normalize(); Vector3 obbExtents = new Vector3( 2.5f * OneMeter, 1 * OneMeter, 1 * OneMeter ); CollisionOBB obb = new CollisionOBB( center, obbAxes, obbExtents ); pd.AddCollisionShape( "submesh01", obb ); CollisionAABB aabb = new CollisionAABB( center - obbExtents, center + obbExtents ); pd.AddCollisionShape( "submesh01", aabb ); CollisionSphere sphere = new CollisionSphere( center, 2 * OneMeter ); pd.AddCollisionShape( "submesh01", sphere ); Vector3 capExtents = new Vector3( -1 * OneMeter, 0, 0 ); CollisionCapsule capsule = new CollisionCapsule( center + capExtents, center - capExtents, .5f * OneMeter ); pd.AddCollisionShape( "submesh01", capsule ); PhysicsSerializer ps = new PhysicsSerializer(); ps.ExportPhysics( pd, name ); pd = new PhysicsData(); ps.ImportPhysics( pd, name ); foreach( string objectId in pd.GetCollisionObjects() ) { log.InfoFormat( "Collision shapes for: {0}", objectId ); List<CollisionShape> collisionShapes = pd.GetCollisionShapes( objectId ); foreach( CollisionShape shape in collisionShapes ) log.InfoFormat( "Shape: {0}", shape ); } }
/// <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); } }