public void ReadSphere(string objectId, Matrix4 transform, XmlNode node, PhysicsData physicsData) { Vector3 scaleDelta = transform.Scale - Vector3.UnitScale; if (scaleDelta.Length > PhysicsSerializer.ScaleEpsilon) { log.Error("Scale is not currently supported for sphere shapes"); } float radius = 0; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "radius": radius = float.Parse(childNode.InnerText); break; default: DebugMessage(childNode); break; } } Vector3 center = unitConversion * transform.Translation; radius *= unitConversion; CollisionShape collisionShape = new CollisionSphere(center, radius); physicsData.AddCollisionShape(objectId, collisionShape); }
public void ReadCapsule(string objectId, Matrix4 transform, XmlNode node, PhysicsData physicsData) { Quaternion rot = MathHelpers.GetRotation(transform); Matrix4 tmpTransform = rot.Inverse().ToRotationMatrix() * transform; Vector3 scaleDelta = tmpTransform.Scale - Vector3.UnitScale; if (scaleDelta.Length > PhysicsSerializer.ScaleEpsilon) { log.Error("Scale is not currently supported for capsule shapes"); } float height = 0; float[] radius = new float[2]; Vector3 halfExtents = Vector3.Zero; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "height": height = float.Parse(childNode.InnerText); break; case "radius": { string[] values = childNode.InnerText.Split((char[])null, StringSplitOptions.RemoveEmptyEntries); Debug.Assert(values.Length == 2); for (int i = 0; i < 2; ++i) { radius[i] = float.Parse(values[i]); } } break; default: DebugMessage(childNode); break; } } // We only support capsules where the two radii match if (radius[0] != radius[1]) { log.Error("Different radii for capsules are not currently supported"); } Vector3 center = unitConversion * transform.Translation; Vector3 halfExtent = unitConversion * (.5f * height * (rot * Vector3.UnitY)); radius[0] *= unitConversion; radius[1] *= unitConversion; CollisionShape collisionShape; collisionShape = new CollisionCapsule(center - halfExtent, center + halfExtent, radius[0]); physicsData.AddCollisionShape(objectId, collisionShape); }
public void ReadBox(string objectId, Matrix4 transform, XmlNode node, PhysicsData physicsData) { Quaternion rot = MathHelpers.GetRotation(transform); Matrix4 tmpTransform = rot.Inverse().ToRotationMatrix() * transform; Vector3 scaleDelta = tmpTransform.Scale - Vector3.UnitScale; if (scaleDelta.Length > PhysicsSerializer.ScaleEpsilon) { log.Error("Scale is not currently supported for box shapes"); } Vector3 halfExtents = Vector3.Zero; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "half_extents": ReadVector(ref halfExtents, childNode); break; default: DebugMessage(childNode); break; } } Vector3 center = unitConversion * transform.Translation; halfExtents *= unitConversion; CollisionShape collisionShape; float angle = 0; Vector3 axis = Vector3.Zero; rot.ToAngleAxis(ref angle, ref axis); // I could build AABB shapes for boxes that are aligned, but then // I can't drop instances in the world with arbitrary rotations. // Instead, just always use an OBB. //if (angle < PhysicsSerializer.RotateEpsilon) { // collisionShape = new CollisionAABB(center - halfExtents, center + halfExtents); //} else { // TODO: I'm not sure I understand the OBB constructor Vector3[] axes = new Vector3[3]; axes[0] = rot.XAxis; axes[1] = rot.YAxis; axes[2] = rot.ZAxis; collisionShape = new CollisionOBB(center, axes, halfExtents); physicsData.AddCollisionShape(objectId, collisionShape); }
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 ); } }
public void ReadSphere(string objectId, Matrix4 transform, XmlNode node, PhysicsData physicsData) { Vector3 scaleDelta = transform.Scale - Vector3.UnitScale; if (scaleDelta.Length > PhysicsSerializer.ScaleEpsilon) log.Error("Scale is not currently supported for sphere shapes"); float radius = 0; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "radius": radius = float.Parse(childNode.InnerText); break; default: DebugMessage(childNode); break; } } Vector3 center = unitConversion * transform.Translation; radius *= unitConversion; CollisionShape collisionShape = new CollisionSphere(center, radius); physicsData.AddCollisionShape(objectId, collisionShape); }
public void ReadCapsule(string objectId, Matrix4 transform, XmlNode node, PhysicsData physicsData) { Quaternion rot = MathHelpers.GetRotation(transform); Matrix4 tmpTransform = rot.Inverse().ToRotationMatrix() * transform; Vector3 scaleDelta = tmpTransform.Scale - Vector3.UnitScale; if (scaleDelta.Length > PhysicsSerializer.ScaleEpsilon) log.Error("Scale is not currently supported for capsule shapes"); float height = 0; float[] radius = new float[2]; Vector3 halfExtents = Vector3.Zero; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "height": height = float.Parse(childNode.InnerText); break; case "radius": { string[] values = childNode.InnerText.Split((char[])null, StringSplitOptions.RemoveEmptyEntries); Debug.Assert(values.Length == 2); for (int i = 0; i < 2; ++i) radius[i] = float.Parse(values[i]); } break; default: DebugMessage(childNode); break; } } // We only support capsules where the two radii match if (radius[0] != radius[1]) log.Error("Different radii for capsules are not currently supported"); Vector3 center = unitConversion * transform.Translation; Vector3 halfExtent = unitConversion * (.5f * height * (rot * Vector3.UnitY)); radius[0] *= unitConversion; radius[1] *= unitConversion; CollisionShape collisionShape; collisionShape = new CollisionCapsule(center - halfExtent, center + halfExtent, radius[0]); physicsData.AddCollisionShape(objectId, collisionShape); }
public void ReadBox(string objectId, Matrix4 transform, XmlNode node, PhysicsData physicsData) { Quaternion rot = MathHelpers.GetRotation(transform); Matrix4 tmpTransform = rot.Inverse().ToRotationMatrix() * transform; Vector3 scaleDelta = tmpTransform.Scale - Vector3.UnitScale; if (scaleDelta.Length > PhysicsSerializer.ScaleEpsilon) log.Error("Scale is not currently supported for box shapes"); Vector3 halfExtents = Vector3.Zero; foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "half_extents": ReadVector(ref halfExtents, childNode); break; default: DebugMessage(childNode); break; } } Vector3 center = unitConversion * transform.Translation; halfExtents *= unitConversion; CollisionShape collisionShape; float angle = 0; Vector3 axis = Vector3.Zero; rot.ToAngleAxis(ref angle, ref axis); // I could build AABB shapes for boxes that are aligned, but then // I can't drop instances in the world with arbitrary rotations. // Instead, just always use an OBB. //if (angle < PhysicsSerializer.RotateEpsilon) { // collisionShape = new CollisionAABB(center - halfExtents, center + halfExtents); //} else { // TODO: I'm not sure I understand the OBB constructor Vector3[] axes = new Vector3[3]; axes[0] = rot.XAxis; axes[1] = rot.YAxis; axes[2] = rot.ZAxis; collisionShape = new CollisionOBB(center, axes, halfExtents); physicsData.AddCollisionShape(objectId, collisionShape); }