public void Clone() { Pose poseA = new Pose(new Vector3(1, 2, 3)); PointShape pointA = new PointShape(3, 4, 5); GeometricObject geometryA = new GeometricObject(pointA, poseA); Pose poseB = new Pose(new Vector3(1, 2, 3)); PointShape pointB = new PointShape(3, 4, 5); GeometricObject geometryB = new GeometricObject(pointB, poseB); MinkowskiSumShape minkowskiSumShape = new MinkowskiSumShape(geometryA, geometryB); MinkowskiSumShape clone = minkowskiSumShape.Clone() as MinkowskiSumShape; Assert.IsNotNull(clone); Assert.IsNotNull(clone.ObjectA); Assert.IsNotNull(clone.ObjectB); Assert.AreNotSame(geometryA, clone.ObjectA); Assert.AreNotSame(geometryB, clone.ObjectB); Assert.IsTrue(clone.ObjectA is GeometricObject); Assert.IsTrue(clone.ObjectB is GeometricObject); Assert.AreEqual(poseA, clone.ObjectA.Pose); Assert.AreEqual(poseB, clone.ObjectB.Pose); Assert.IsNotNull(clone.ObjectA.Shape); Assert.IsNotNull(clone.ObjectB.Shape); Assert.AreNotSame(pointA, clone.ObjectA.Shape); Assert.AreNotSame(pointB, clone.ObjectB.Shape); Assert.IsTrue(clone.ObjectA.Shape is PointShape); Assert.IsTrue(clone.ObjectB.Shape is PointShape); Assert.AreEqual(pointA.Position, ((PointShape)clone.ObjectA.Shape).Position); Assert.AreEqual(pointB.Position, ((PointShape)clone.ObjectB.Shape).Position); Assert.AreEqual(minkowskiSumShape.GetAabb(Pose.Identity).Minimum, clone.GetAabb(Pose.Identity).Minimum); Assert.AreEqual(minkowskiSumShape.GetAabb(Pose.Identity).Maximum, clone.GetAabb(Pose.Identity).Maximum); }
public void SerializationBinary() { Pose poseA = new Pose(new Vector3(1, 2, 3)); PointShape pointA = new PointShape(3, 4, 5); GeometricObject geometryA = new GeometricObject(pointA, poseA); Pose poseB = new Pose(new Vector3(11, 22, 33)); PointShape pointB = new PointShape(33, 44, 55); GeometricObject geometryB = new GeometricObject(pointB, poseB); var a = new MinkowskiSumShape(geometryA, geometryB); // Serialize object. var stream = new MemoryStream(); var formatter = new BinaryFormatter(); formatter.Serialize(stream, a); // Deserialize object. stream.Position = 0; var deserializer = new BinaryFormatter(); var b = (MinkowskiSumShape)deserializer.Deserialize(stream); Assert.AreEqual(a.ObjectA.Pose, b.ObjectA.Pose); Assert.AreEqual(a.ObjectB.Pose, b.ObjectB.Pose); Assert.AreEqual(((PointShape)a.ObjectA.Shape).Position, ((PointShape)b.ObjectA.Shape).Position); Assert.AreEqual(((PointShape)a.ObjectB.Shape).Position, ((PointShape)b.ObjectB.Shape).Position); }
public void GetShapeVolumeArgumentOutOfRangeException2() { var s = new SphereShape(1); var c = new MinkowskiSumShape(new GeometricObject(s), new GeometricObject(new PointShape())); c.GetVolume(0.01f, -1); }
public void Clone() { Pose poseA = new Pose(new Vector3F(1, 2, 3)); PointShape pointA = new PointShape(3, 4, 5); GeometricObject geometryA = new GeometricObject(pointA, poseA); Pose poseB = new Pose(new Vector3F(1, 2, 3)); PointShape pointB = new PointShape(3, 4, 5); GeometricObject geometryB = new GeometricObject(pointB, poseB); MinkowskiSumShape minkowskiSumShape = new MinkowskiSumShape(geometryA, geometryB); MinkowskiSumShape clone = minkowskiSumShape.Clone() as MinkowskiSumShape; Assert.IsNotNull(clone); Assert.IsNotNull(clone.ObjectA); Assert.IsNotNull(clone.ObjectB); Assert.AreNotSame(geometryA, clone.ObjectA); Assert.AreNotSame(geometryB, clone.ObjectB); Assert.IsTrue(clone.ObjectA is GeometricObject); Assert.IsTrue(clone.ObjectB is GeometricObject); Assert.AreEqual(poseA, clone.ObjectA.Pose); Assert.AreEqual(poseB, clone.ObjectB.Pose); Assert.IsNotNull(clone.ObjectA.Shape); Assert.IsNotNull(clone.ObjectB.Shape); Assert.AreNotSame(pointA, clone.ObjectA.Shape); Assert.AreNotSame(pointB, clone.ObjectB.Shape); Assert.IsTrue(clone.ObjectA.Shape is PointShape); Assert.IsTrue(clone.ObjectB.Shape is PointShape); Assert.AreEqual(pointA.Position, ((PointShape)clone.ObjectA.Shape).Position); Assert.AreEqual(pointB.Position, ((PointShape)clone.ObjectB.Shape).Position); Assert.AreEqual(minkowskiSumShape.GetAabb(Pose.Identity).Minimum, clone.GetAabb(Pose.Identity).Minimum); Assert.AreEqual(minkowskiSumShape.GetAabb(Pose.Identity).Maximum, clone.GetAabb(Pose.Identity).Maximum); }
public void ApproximateVolume() { var s = new SphereShape(1); var c = new MinkowskiSumShape(new GeometricObject(s), new GeometricObject(new PointShape())); var v = c.GetVolume(0.001f, 0); // !!! // v is AABB volume. Assert.AreEqual(2 * 2 * 2, v); }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var graphicsService = _services.GetInstance <IGraphicsService>(); var gameObjectService = _services.GetInstance <IGameObjectService>(); var content = _services.GetInstance <ContentManager>(); // Check if the game object manager has another ProceduralObject instance. var otherProceduralObject = gameObjectService.Objects .OfType <ProceduralObject>() .FirstOrDefault(o => o != this); Mesh mesh; if (otherProceduralObject != null) { // This ProceduralObject is not the first. We re-use rigid body data and // the mesh from the existing instance. var otherBody = otherProceduralObject._rigidBody; _rigidBody = new RigidBody(otherBody.Shape, otherBody.MassFrame, otherBody.Material); mesh = otherProceduralObject._meshNode.Mesh; } else { // This is the first ProceduralObject instance. // Create a a new rigid body. var shape = new MinkowskiSumShape(new GeometricObject(new SphereShape(0.05f)), new GeometricObject(new BoxShape(0.5f, 0.5f, 0.5f))); _rigidBody = new RigidBody(shape); // Create a new mesh. See SampleHelper.CreateMesh for more details. mesh = SampleHelper.CreateMesh(content, graphicsService, _rigidBody.Shape); mesh.Name = "ProceduralObject"; } // Create a scene graph node for the mesh. _meshNode = new MeshNode(mesh); // Set a random pose. var randomPosition = new Vector3( RandomHelper.Random.NextFloat(-10, 10), RandomHelper.Random.NextFloat(2, 5), RandomHelper.Random.NextFloat(-20, 0)); _rigidBody.Pose = new Pose(randomPosition, RandomHelper.Random.NextQuaternion()); _meshNode.PoseWorld = _rigidBody.Pose; // Add mesh node to scene graph. var scene = _services.GetInstance <IScene>(); scene.Children.Add(_meshNode); // Add rigid body to the physics simulation. var simulation = _services.GetInstance <Simulation>(); simulation.RigidBodies.Add(_rigidBody); }
public void SetUp() { child0 = new GeometricObject(new CircleShape(3), new Pose(new Vector3(), Quaternion.CreateRotationX(ConstantsF.PiOver2))); child1 = new GeometricObject(new LineSegmentShape(new Vector3(0, 5, 0), new Vector3(0, -5, 0)), Pose.Identity); cs = new MinkowskiSumShape { ObjectA = child0, ObjectB = child1 }; }
// Creates a lot of random objects. private void CreateRandomObjects() { var random = new Random(); var isFirstHeightField = true; int currentShape = 0; int numberOfObjects = 0; while (true) { numberOfObjects++; if (numberOfObjects > ObjectsPerType) { currentShape++; numberOfObjects = 0; } Shape shape; switch (currentShape) { case 0: // Box shape = new BoxShape(ObjectSize, ObjectSize * 2, ObjectSize * 3); break; case 1: // Capsule shape = new CapsuleShape(0.3f * ObjectSize, 2 * ObjectSize); break; case 2: // Cone shape = new ConeShape(1 * ObjectSize, 2 * ObjectSize); break; case 3: // Cylinder shape = new CylinderShape(0.4f * ObjectSize, 2 * ObjectSize); break; case 4: // Sphere shape = new SphereShape(ObjectSize); break; case 5: // Convex hull of several points. ConvexHullOfPoints hull = new ConvexHullOfPoints(); hull.Points.Add(new Vector3(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize)); hull.Points.Add(new Vector3(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize)); hull.Points.Add(new Vector3(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize)); hull.Points.Add(new Vector3(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize)); hull.Points.Add(new Vector3(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize)); shape = hull; break; case 6: // A composite shape: two boxes that form a "T" shape. var composite = new CompositeShape(); composite.Children.Add( new GeometricObject( new BoxShape(ObjectSize, 3 * ObjectSize, ObjectSize), new Pose(new Vector3(0, 0, 0)))); composite.Children.Add( new GeometricObject( new BoxShape(2 * ObjectSize, ObjectSize, ObjectSize), new Pose(new Vector3(0, 2 * ObjectSize, 0)))); shape = composite; break; case 7: shape = new CircleShape(ObjectSize); break; case 8: { var compBvh = new CompositeShape(); compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3(0, 0.5f, 0), Matrix.Identity))); compBvh.Children.Add(new GeometricObject(new BoxShape(0.8f, 0.5f, 0.5f), new Pose(new Vector3(0.5f, 0.7f, 0), Matrix.CreateRotationZ(-MathHelper.ToRadians(15))))); compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3(0, 1.15f, 0), Matrix.Identity))); compBvh.Children.Add(new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3(0.6f, 1.15f, 0), Matrix.CreateRotationX(0.3f)))); compBvh.Partition = new AabbTree<int>(); shape = compBvh; break; } case 9: CompositeShape comp = new CompositeShape(); comp.Children.Add(new GeometricObject(new BoxShape(0.5f * ObjectSize, 1 * ObjectSize, 0.5f * ObjectSize), new Pose(new Vector3(0, 0.5f * ObjectSize, 0), Quaternion.Identity))); comp.Children.Add(new GeometricObject(new BoxShape(0.8f * ObjectSize, 0.5f * ObjectSize, 0.5f * ObjectSize), new Pose(new Vector3(0.3f * ObjectSize, 0.7f * ObjectSize, 0), Quaternion.CreateRotationZ(-MathHelper.ToRadians(45))))); comp.Children.Add(new GeometricObject(new SphereShape(0.3f * ObjectSize), new Pose(new Vector3(0, 1.15f * ObjectSize, 0), Quaternion.Identity))); shape = comp; break; case 10: shape = new ConvexHullOfPoints(new[] { new Vector3(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize), new Vector3(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize), new Vector3(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize) }); break; case 11: ConvexHullOfShapes shapeHull = new ConvexHullOfShapes(); shapeHull.Children.Add(new GeometricObject(new SphereShape(0.3f * ObjectSize), new Pose(new Vector3(0, 2 * ObjectSize, 0), Matrix.Identity))); shapeHull.Children.Add(new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize), Pose.Identity)); shape = shapeHull; break; case 12: shape = Shape.Empty; break; case 13: var numberOfSamplesX = 10; var numberOfSamplesZ = 10; var samples = new float[numberOfSamplesX * numberOfSamplesZ]; for (int z = 0; z < numberOfSamplesZ; z++) for (int x = 0; x < numberOfSamplesX; x++) samples[z * numberOfSamplesX + x] = (float)(Math.Cos(z / 3f) * Math.Sin(x / 2f) * BoxSize / 6); HeightField heightField = new HeightField(0, 0, 2 * BoxSize, 2 * BoxSize, samples, numberOfSamplesX, numberOfSamplesZ); shape = heightField; break; //case 14: //shape = new LineShape(new Vector3(0.1f, 0.2f, 0.3f), new Vector3(0.1f, 0.2f, -0.3f).Normalized); //break; case 15: shape = new LineSegmentShape( new Vector3(0.1f, 0.2f, 0.3f), new Vector3(0.1f, 0.2f, 0.3f) + 3 * ObjectSize * new Vector3(0.1f, 0.2f, -0.3f)); break; case 16: shape = new MinkowskiDifferenceShape { ObjectA = new GeometricObject(new SphereShape(0.1f * ObjectSize)), ObjectB = new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize)) }; break; case 17: shape = new MinkowskiSumShape { ObjectA = new GeometricObject(new SphereShape(0.1f * ObjectSize)), ObjectB = new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize)), }; break; case 18: shape = new OrthographicViewVolume(0, ObjectSize, 0, ObjectSize, ObjectSize / 2, ObjectSize * 2); break; case 19: shape = new PerspectiveViewVolume(MathHelper.ToRadians(60f), 16f / 10, ObjectSize / 2, ObjectSize * 3); break; case 20: shape = new PointShape(0.1f, 0.3f, 0.2f); break; case 21: shape = new RayShape(new Vector3(0.2f, 0, -0.12f), new Vector3(1, 2, 3).Normalized, ObjectSize * 2); break; case 22: shape = new RayShape(new Vector3(0.2f, 0, -0.12f), new Vector3(1, 2, 3).Normalized, ObjectSize * 2) { StopsAtFirstHit = true }; break; case 23: shape = new RectangleShape(ObjectSize, ObjectSize * 2); break; case 24: shape = new TransformedShape( new GeometricObject( new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize), new Pose(new Vector3(0.1f, 1, -0.2f)))); break; case 25: shape = new TriangleShape( new Vector3(ObjectSize, 0, 0), new Vector3(0, ObjectSize, 0), new Vector3(ObjectSize, ObjectSize, ObjectSize)); break; //case 26: // { // // Create a composite object from which we get the mesh. // CompositeShape compBvh = new CompositeShape(); // compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3(0, 0.5f, 0), Matrix.Identity))); // compBvh.Children.Add( // new GeometricObject( // new BoxShape(0.8f, 0.5f, 0.5f), // new Pose(new Vector3(0.5f, 0.7f, 0), Matrix.CreateRotationZ(-(float)MathHelper.ToRadians(15))))); // compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3(0, 1.15f, 0), Matrix.Identity))); // compBvh.Children.Add( // new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3(0.6f, 1.15f, 0), Matrix.CreateRotationX(0.3f)))); // TriangleMeshShape meshBvhShape = new TriangleMeshShape { Mesh = compBvh.GetMesh(0.01f, 3) }; // meshBvhShape.Partition = new AabbTree<int>(); // shape = meshBvhShape; // break; // } //case 27: // { // // Create a composite object from which we get the mesh. // CompositeShape compBvh = new CompositeShape(); // compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3(0, 0.5f, 0), Quaternion.Identity))); // compBvh.Children.Add( // new GeometricObject( // new BoxShape(0.8f, 0.5f, 0.5f), // new Pose(new Vector3(0.5f, 0.7f, 0), Quaternion.CreateRotationZ(-(float)MathHelper.ToRadians(15))))); // compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3(0, 1.15f, 0), Quaternion.Identity))); // compBvh.Children.Add( // new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3(0.6f, 1.15f, 0), Quaternion.CreateRotationX(0.3f)))); // TriangleMeshShape meshBvhShape = new TriangleMeshShape { Mesh = compBvh.GetMesh(0.01f, 3) }; // meshBvhShape.Partition = new AabbTree<int>(); // shape = meshBvhShape; // break; // } case 28: shape = new ConvexPolyhedron(new[] { new Vector3(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize), new Vector3(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize), new Vector3(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize) }); break; case 29: return; default: currentShape++; continue; } // Create an object with the random shape, pose, color and velocity. Pose randomPose = new Pose( random.NextVector3(-BoxSize + ObjectSize * 2, BoxSize - ObjectSize * 2), random.NextQuaternion()); var newObject = new MovingGeometricObject { Pose = randomPose, Shape = shape, LinearVelocity = random.NextQuaternion().Rotate(new Vector3(MaxLinearVelocity, 0, 0)), AngularVelocity = random.NextQuaternion().Rotate(Vector3.Forward) * RandomHelper.Random.NextFloat(0, MaxAngularVelocity), }; if (RandomHelper.Random.NextBool()) newObject.LinearVelocity = Vector3.Zero; if (RandomHelper.Random.NextBool()) newObject.AngularVelocity = Vector3.Zero; if (shape is LineShape || shape is HeightField) { // Do not move lines or the height field. newObject.LinearVelocity = Vector3.Zero; newObject.AngularVelocity = Vector3.Zero; } // Create only 1 heightField! if (shape is HeightField) { if (isFirstHeightField) { isFirstHeightField = true; newObject.Pose = new Pose(new Vector3(-BoxSize, -BoxSize, -BoxSize)); } else { currentShape++; numberOfObjects = 0; continue; } } // Add collision object to collision domain. _domain.CollisionObjects.Add(new CollisionObject(newObject)); //co.Type = CollisionObjectType.Trigger; //co.Name = "Object" + shape.GetType().Name + "_" + i; } }
public ShapesSample(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", // Names are not required but helpful for debugging. MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); // ----- Add a sphere. Shape sphere = new SphereShape(0.5f); Simulation.RigidBodies.Add(new RigidBody(sphere)); // ----- Add a box. BoxShape box = new BoxShape(0.5f, 0.9f, 0.7f); Simulation.RigidBodies.Add(new RigidBody(box)); // ----- Add a capsule. CapsuleShape capsule = new CapsuleShape(0.4f, 1.2f); Simulation.RigidBodies.Add(new RigidBody(capsule)); // ----- Add a cone. ConeShape cone = new ConeShape(0.5f, 1f); Simulation.RigidBodies.Add(new RigidBody(cone)); // ----- Add a cylinder. CylinderShape cylinder = new CylinderShape(0.3f, 1f); Simulation.RigidBodies.Add(new RigidBody(cylinder)); // ----- Add a convex hull of random points. ConvexHullOfPoints convexHullOfPoints = new ConvexHullOfPoints(); for (int i = 0; i < 20; i++) { convexHullOfPoints.Points.Add(RandomHelper.Random.NextVector3F(-0.5f, 0.5f)); } Simulation.RigidBodies.Add(new RigidBody(convexHullOfPoints)); // ----- Add a convex polyhedron. // (A ConvexPolyhedron is similar to the ConvexHullOfPoints. The difference is that // the points in a ConvexHullOfPoints can be changed at runtime. A ConvexPolyhedron // cannot be changed at runtime, but it is faster.) List <Vector3F> points = new List <Vector3F>(); for (int i = 0; i < 20; i++) { points.Add(RandomHelper.Random.NextVector3F(-0.7f, 0.7f)); } ConvexPolyhedron convexPolyhedron = new ConvexPolyhedron(points); Simulation.RigidBodies.Add(new RigidBody(convexPolyhedron)); // ----- Add a composite shape (a table that consists of 5 boxes). CompositeShape composite = new CompositeShape(); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(-0.75f, 0.4f, -0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(0.75f, 0.4f, -0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(-0.75f, 0.4f, 0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(0.75f, 0.4f, 0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(1.8f, 0.1f, 1.1f), new Pose(new Vector3F(0, 0.8f, 0)))); Simulation.RigidBodies.Add(new RigidBody(composite)); // ----- Add a convex hull of multiple shapes. ConvexHullOfShapes convexHullOfShapes = new ConvexHullOfShapes(); convexHullOfShapes.Children.Add(new GeometricObject(new CylinderShape(0.2f, 0.8f), new Pose(new Vector3F(-0.4f, 0, 0)))); convexHullOfShapes.Children.Add(new GeometricObject(new CylinderShape(0.2f, 0.8f), new Pose(new Vector3F(+0.4f, 0, 0)))); Simulation.RigidBodies.Add(new RigidBody(convexHullOfShapes)); // ----- Add the Minkowski sum of two shapes. // (The Minkowski sum is a mathematical operation that combines two shapes. // Here a circle is combined with a sphere. The result is a wheel.) MinkowskiSumShape minkowskiSum = new MinkowskiSumShape(); minkowskiSum.ObjectA = new GeometricObject(new SphereShape(0.2f), Pose.Identity); minkowskiSum.ObjectB = new GeometricObject(new CircleShape(0.5f), Pose.Identity); Simulation.RigidBodies.Add(new RigidBody(minkowskiSum)); // Create another Minkowski sum. (Here a small sphere is added to a box to create a // box with rounded corners.) minkowskiSum = new MinkowskiSumShape(); minkowskiSum.ObjectA = new GeometricObject(new SphereShape(0.1f), Pose.Identity); minkowskiSum.ObjectB = new GeometricObject(new BoxShape(0.2f, 0.5f, 0.8f), Pose.Identity); Simulation.RigidBodies.Add(new RigidBody(minkowskiSum)); // ----- Add a triangle mesh. // A triangle mesh could be loaded from a file or built from an XNA model. // Here we first create a composite shape and convert the shape into a triangle // mesh. (Any Shape in DigitalRune.Geometry can be converted to a triangle mesh.) CompositeShape dumbbell = new CompositeShape(); dumbbell.Children.Add(new GeometricObject(new SphereShape(0.4f), new Pose(new Vector3F(0.6f, 0.0f, 0.0f)))); dumbbell.Children.Add(new GeometricObject(new SphereShape(0.4f), new Pose(new Vector3F(-0.6f, 0.0f, 0.0f)))); dumbbell.Children.Add(new GeometricObject(new CylinderShape(0.1f, 0.6f), new Pose(Matrix33F.CreateRotationZ(ConstantsF.PiOver2)))); TriangleMeshShape triangleMeshShape = new TriangleMeshShape(dumbbell.GetMesh(0.01f, 2)); // Optional: We can enable "contact welding". When this flag is enabled, the triangle shape // precomputes additional internal information for the mesh. The collision detection will // be able to compute better contacts (e.g. better normal vectors at triangle edges). // Pro: Collision detection can compute better contact information. // Con: Contact welding information needs a bit of memory. And the collision detection is // a bit slower. triangleMeshShape.EnableContactWelding = true; // Optional: Assign a spatial partitioning scheme to the triangle mesh. (A spatial partition // adds an additional memory overhead, but it improves collision detection speed tremendously!) triangleMeshShape.Partition = new AabbTree <int>(); Simulation.RigidBodies.Add(new RigidBody(triangleMeshShape)); // ----- Set random positions/orientations. // (Start with the second object. The first object is the ground plane which should // not be changed.) for (int i = 1; i < Simulation.RigidBodies.Count; i++) { RigidBody body = Simulation.RigidBodies[i]; Vector3F position = RandomHelper.Random.NextVector3F(-3, 3); position.Y = 3; // Position the objects 3m above ground. QuaternionF orientation = RandomHelper.Random.NextQuaternionF(); body.Pose = new Pose(position, orientation); } }
public void SetUp() { child0 = new GeometricObject(new CircleShape(3), new Pose(new Vector3F(), QuaternionF.CreateRotationX(ConstantsF.PiOver2))); child1 = new GeometricObject(new LineSegmentShape(new Vector3F(0, 5, 0), new Vector3F(0, -5, 0)), Pose.Identity); cs = new MinkowskiSumShape { ObjectA = child0, ObjectB = child1 }; }
public void SerializationBinary() { Pose poseA = new Pose(new Vector3F(1, 2, 3)); PointShape pointA = new PointShape(3, 4, 5); GeometricObject geometryA = new GeometricObject(pointA, poseA); Pose poseB = new Pose(new Vector3F(11, 22, 33)); PointShape pointB = new PointShape(33, 44, 55); GeometricObject geometryB = new GeometricObject(pointB, poseB); var a = new MinkowskiSumShape(geometryA, geometryB); // Serialize object. var stream = new MemoryStream(); var formatter = new BinaryFormatter(); formatter.Serialize(stream, a); // Deserialize object. stream.Position = 0; var deserializer = new BinaryFormatter(); var b = (MinkowskiSumShape)deserializer.Deserialize(stream); Assert.AreEqual(a.ObjectA.Pose, b.ObjectA.Pose); Assert.AreEqual(a.ObjectB.Pose, b.ObjectB.Pose); Assert.AreEqual(((PointShape)a.ObjectA.Shape).Position, ((PointShape)b.ObjectA.Shape).Position); Assert.AreEqual(((PointShape)a.ObjectB.Shape).Position, ((PointShape)b.ObjectB.Shape).Position); }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var graphicsService = _services.GetInstance <IGraphicsService>(); var gameObjectService = _services.GetInstance <IGameObjectService>(); // Check if the game object manager has another ProceduralObject instance. var otherProceduralObject = gameObjectService.Objects .OfType <ProceduralObject>() .FirstOrDefault(o => o != this); Mesh mesh; if (otherProceduralObject != null) { // This ProceduralObject is not the first. We re-use rigid body data and // the mesh from the existing instance. var otherBody = otherProceduralObject._rigidBody; _rigidBody = new RigidBody(otherBody.Shape, otherBody.MassFrame, otherBody.Material); mesh = otherProceduralObject._meshNode.Mesh; } else { // This is the first ProceduralObject instance. We create a new rigid body // and a new mesh. var shape = new MinkowskiSumShape(new GeometricObject(new SphereShape(0.05f)), new GeometricObject(new BoxShape(0.5f, 0.5f, 0.5f))); _rigidBody = new RigidBody(shape); // Create a DigitalRune.Geometry.Meshes.TriangleMesh from the RigidBody's // shape and convert this to a DigitalRune.Graphics.Mesh. var triangleMesh = _rigidBody.Shape.GetMesh(0.01f, 4); mesh = new Mesh { Name = "ProceduralObject" }; var submesh = CreateSubmeshWithTexCoords(graphicsService.GraphicsDevice, triangleMesh, MathHelper.ToRadians(70)); mesh.Submeshes.Add(submesh); // Next, we need a material. We can load a predefined material (*.drmat file) // with the content manager. //var material = content.Load<Material>("Default"); // Alternatively, we can load some effects and build the material here: Material material = new Material(); // We need an EffectBinding for each render pass. // The "Default" pass uses a BasicEffectBinding (which is an EffectBinding // for the XNA BasicEffect). // Note: The "Default" pass is not used by the DeferredLightingScreen, so // we could ignore this pass in this sample project. BasicEffectBinding defaultEffectBinding = new BasicEffectBinding(graphicsService, null) { LightingEnabled = true, TextureEnabled = true, VertexColorEnabled = false }; defaultEffectBinding.Set("Texture", graphicsService.GetDefaultTexture2DWhite()); defaultEffectBinding.Set("DiffuseColor", new Vector3(1, 1, 1)); defaultEffectBinding.Set("SpecularColor", new Vector3(1, 1, 1)); defaultEffectBinding.Set("SpecularPower", 100f); material.Add("Default", defaultEffectBinding); // EffectBinding for the "ShadowMap" pass. // Note: EffectBindings which are used in a Material must be marked with // the EffectParameterHint Material. var content = _services.GetInstance <ContentManager>(); EffectBinding shadowMapEffectBinding = new EffectBinding( graphicsService, content.Load <Effect>("DigitalRune\\Materials\\ShadowMap"), null, EffectParameterHint.Material); material.Add("ShadowMap", shadowMapEffectBinding); // EffectBinding for the "GBuffer" pass. EffectBinding gBufferEffectBinding = new EffectBinding( graphicsService, content.Load <Effect>("DigitalRune\\Materials\\GBuffer"), null, EffectParameterHint.Material); gBufferEffectBinding.Set("SpecularPower", 100f); material.Add("GBuffer", gBufferEffectBinding); // EffectBinding for the "Material" pass. EffectBinding materialEffectBinding = new EffectBinding( graphicsService, content.Load <Effect>("DigitalRune\\Materials\\Material"), null, EffectParameterHint.Material); materialEffectBinding.Set("DiffuseTexture", graphicsService.GetDefaultTexture2DWhite()); materialEffectBinding.Set("DiffuseColor", new Vector3(1, 1, 1)); materialEffectBinding.Set("SpecularColor", new Vector3(1, 1, 1)); material.Add("Material", materialEffectBinding); // Assign this material to the submesh. submesh.SetMaterial(material); } // Create a scene graph node for the mesh. _meshNode = new MeshNode(mesh); // Set a random pose. var randomPosition = new Vector3F( RandomHelper.Random.NextFloat(-10, 10), RandomHelper.Random.NextFloat(2, 5), RandomHelper.Random.NextFloat(-20, 0)); _rigidBody.Pose = new Pose(randomPosition, RandomHelper.Random.NextQuaternionF()); _meshNode.PoseWorld = _rigidBody.Pose; // Add mesh node to scene graph. var scene = _services.GetInstance <IScene>(); scene.Children.Add(_meshNode); // Add rigid body to the physics simulation. var simulation = _services.GetInstance <Simulation>(); simulation.RigidBodies.Add(_rigidBody); }
public virtual bool russianCalcTimeOfImpact(ref Matrix fromA, ref Matrix toA, ref Matrix fromB, ref Matrix toB, CastResult result) { MinkowskiSumShape convex = new MinkowskiSumShape(m_convexA, m_convexB); Matrix rayFromLocalA; Matrix rayToLocalA; rayFromLocalA = Matrix.Invert(fromA) * fromB; rayToLocalA = Matrix.Invert(toA) * toB; m_simplexSolver.Reset(); //convex.TransformB = rayFromLocalA; Matrix temp = Matrix.CreateFromQuaternion(Quaternion.CreateFromRotationMatrix(rayFromLocalA)); convex.SetTransformB(ref temp); float lambda = 0; //todo: need to verify this: //because of minkowski difference, we need the inverse direction Vector3 s = -rayFromLocalA.Translation; Vector3 r = -(rayToLocalA.Translation - rayFromLocalA.Translation); Vector3 x = s; Vector3 v; Vector3 arbitraryPoint = convex.LocalGetSupportingVertex(ref r); v = x - arbitraryPoint; int maxIter = MAX_ITERATIONS; Vector3 n = new Vector3(); float lastLambda = lambda; float dist2 = v.LengthSquared(); float epsilon = 0.0001f; Vector3 w = Vector3.Zero, p = Vector3.Zero; float VdotR; while ((dist2 > epsilon) && (maxIter-- != 0)) { p = convex.LocalGetSupportingVertex(ref v); w = x - p; float VdotW = Vector3.Dot(v, w); if (VdotW > 0) { VdotR = Vector3.Dot(v, r); if (VdotR >= -(MathUtil.SIMD_EPSILON * MathUtil.SIMD_EPSILON)) return false; else { lambda = lambda - VdotW / VdotR; x = s + lambda * r; m_simplexSolver.Reset(); //check next line w = x - p; lastLambda = lambda; n = v; } } m_simplexSolver.AddVertex(ref w, ref x, ref p); if (m_simplexSolver.Closest(ref v)) { dist2 = v.LengthSquared(); } else { dist2 = 0f; } } result.m_fraction = lambda; result.m_normal = n; return true; }