예제 #1
0
        public void ComputeCollision()
        {
            CollisionObject a = new CollisionObject();
              CompositeShape compo = new CompositeShape();
              compo.Children.Add(new GeometricObject(new SphereShape(2), Pose.Identity));
              compo.Children.Add(new GeometricObject(new SphereShape(1), new Pose(new Vector3F(0, 3, 0))));
              a.GeometricObject = new GeometricObject(compo, Pose.Identity);

              CollisionObject b = new CollisionObject(new GeometricObject
                  {
                    Shape = new PlaneShape(new Vector3F(0, 1, 0), 1),
                    Pose = new Pose(new Vector3F(0, -1, 0)),
                  });

              ContactSet set;
              CompositeShapeAlgorithm algo = new CompositeShapeAlgorithm(new CollisionDetection());

              set = algo.GetClosestPoints(a, b);
              Assert.AreEqual(true, algo.HaveContact(a, b));
              Assert.AreEqual(true, algo.HaveContact(b, a));
              Assert.AreEqual(1, set.Count);
              Assert.AreEqual(2, set[0].PenetrationDepth);
              Assert.AreEqual(new Vector3F(0, -2, 0), set[0].PositionAWorld);

              ((GeometricObject)a.GeometricObject).Pose = new Pose(new Vector3F(0, 2, 3), a.GeometricObject.Pose.Orientation);
              set = set.Swapped;
              algo.UpdateContacts(set, 0);
              Assert.AreEqual(true, algo.HaveContact(a, b));
              Assert.AreEqual(true, algo.HaveContact(b, a));
              Assert.AreEqual(1, set.Count);
              Assert.AreEqual(0, set[0].PenetrationDepth);
              Assert.AreEqual(new Vector3F(0, 0, 3), set[0].PositionBWorld);

              ((GeometricObject)a.GeometricObject).Pose = new Pose(new Vector3F(0, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
              set = set.Swapped; // new order: (a, b)
              algo.UpdateContacts(set, 0);
              Assert.AreEqual(true, algo.HaveContact(a, b));
              Assert.AreEqual(2, set.Count);
              Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(-2, 0, 0), set[0].PositionALocal));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(-1, 3, 0), set[1].PositionALocal));
              Assert.AreEqual(new Vector3F(0, -1, 0), set[0].Normal);
              Assert.AreEqual(new Vector3F(0, -1, 0), set[1].Normal);
              Assert.AreEqual(2, set[0].PenetrationDepth);
              Assert.IsTrue(Numeric.AreEqual(1, set[1].PenetrationDepth));

              algo.UpdateClosestPoints(set, 0);
              Assert.AreEqual(1, set.Count);

              ((GeometricObject)a.GeometricObject).Pose = new Pose(new Vector3F(0, 2.1f, 0), a.GeometricObject.Pose.Orientation);
              algo.UpdateContacts(set, 0);
              Assert.AreEqual(false, algo.HaveContact(a, b));
              Assert.AreEqual(0, set.Count);
              algo.UpdateClosestPoints(set, 0);
              Assert.AreEqual(1, set.Count);
              Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F(-2, 0, 0), set[0].PositionALocal));
              Assert.AreEqual(new Vector3F(0, -1, 0), set[0].Normal);
        }
예제 #2
0
 private CompositeFixture(CompositeShape wrappedCompositeShape, CompositeMaterial wrappedCompositeMaterial, Matrix4x4 realParentPose, FixtureDescriptor descriptor)
 {
     _root = false;
     _realParentPose = realParentPose;
     _pose = descriptor.Pose;
     _realPose = GMath.mul( _pose ,_realParentPose);
     UserData = descriptor.UserData;
     _wrappedCompositeMaterial = wrappedCompositeMaterial;
     _wrappedCompositeShape = wrappedCompositeShape;
     FixtureFactory = new CompositeFixtureFixtureFactory(this);
 }
예제 #3
0
 public CompositeFixture(DR.RigidBody wrappedRigidBody, FixtureDescriptor descriptor)
 {
     _root = true;
     _pose = descriptor.Pose;
     _realPose = _pose;
     _wrappedCompositeMaterial = new CompositeMaterial();
     wrappedRigidBody.Material = _wrappedCompositeMaterial;
     _wrappedCompositeShape = new CompositeShape();
     wrappedRigidBody.Shape = _wrappedCompositeShape;
     UserData = descriptor.UserData;
     FixtureFactory = new CompositeFixtureFixtureFactory(this);
 }
예제 #4
0
    public CompositeMaterial2Sample(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(new Vector3F(0, 1, 0.25f).Normalized, 0))
      {
        Name = "GroundPlane",           // Names are not required but helpful for debugging.
        MotionType = MotionType.Static,
      };

      // Adjust the coefficients of friction of the ground plane.
      ((UniformMaterial)groundPlane.Material).DynamicFriction = 0.5f;
      ((UniformMaterial)groundPlane.Material).StaticFriction = 0.5f;
      Simulation.RigidBodies.Add(groundPlane);

      // Prepare two materials: a slippery material and a rough material.
      UniformMaterial slipperyMaterial = new UniformMaterial
      {
        DynamicFriction = 0.001f,
        StaticFriction = 0.001f,
      };
      UniformMaterial roughMaterial = new UniformMaterial
      {
        DynamicFriction = 1,
        StaticFriction = 1,
      };

      // Create a rigid body that consists of multiple shapes: Two boxes and a cylinder between them.
      CompositeShape compositeShape = new CompositeShape();
      compositeShape.Children.Add(new GeometricObject(new BoxShape(1f, 1f, 1f), new Pose(new Vector3F(1.5f, 0f, 0f))));
      compositeShape.Children.Add(new GeometricObject(new BoxShape(1f, 1, 1f), new Pose(new Vector3F(-1.5f, 0f, 0f))));
      compositeShape.Children.Add(new GeometricObject(new CylinderShape(0.1f, 2), new Pose(Matrix33F.CreateRotationZ(ConstantsF.PiOver2))));

      // A CompositeMaterial is used to assign a different material to each shape.
      CompositeMaterial compositeMaterial = new CompositeMaterial();
      compositeMaterial.Materials.Add(roughMaterial);     // Assign the rough material to the first box.
      compositeMaterial.Materials.Add(slipperyMaterial);  // Assign the slippery material to the second box.
      compositeMaterial.Materials.Add(null);              // Use whatever is default for the handle between the boxes.

      RigidBody body = new RigidBody(compositeShape, null, compositeMaterial)
      {
        Pose = new Pose(new Vector3F(0, 2.2f, -5)),
      };
      Simulation.RigidBodies.Add(body);
    }
예제 #5
0
    public ContinuousCollisionDetectionSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.ClearBackground = true;
      SetCamera(new Vector3F(0, 1, 10), 0, 0);

      // ----- Initialize collision detection and create objects.

      // Create a geometric object with a capsule shape.
      // Position it on the top with an arbitrary rotation.
      _startPoseA = new Pose(new Vector3F(0, 2, 0), Matrix33F.CreateRotationZ(0.1f));
      var geometricObjectA = new GeometricObject(new CapsuleShape(0.2f, 1), _startPoseA);
      _collisionObjectA = new CollisionObject(geometricObjectA);

      // Object A moves to the bottom of the screen.
      _targetPoseA = new Pose(new Vector3F(0, -2, 0), Matrix33F.CreateRotationZ(0.63f));

      // Create a geometric object with a composite shape.
      // Position it on the left with an arbitrary rotation.
      _startPoseB = new Pose(new Vector3F(-3, -1, 0), Matrix33F.CreateRotationZ(0.2f));
      var composite = new CompositeShape();
      composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(-0.75f, 0.5f, -0.5f))));
      composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(0.75f, 0.5f, -0.5f))));
      composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(-0.75f, 0.5f, 0.5f))));
      composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(0.75f, 0.5f, 0.5f))));
      composite.Children.Add(new GeometricObject(new BoxShape(1.8f, 0.1f, 1.1f), new Pose(new Vector3F(0, 1f, 0))));
      var geometricObjectB = new GeometricObject(composite, _startPoseB);

      // Object B moves to the left of the screen.
      _targetPoseB = new Pose(new Vector3F(3, -1, 0), Matrix33F.CreateRotationZ(0.3f));

      // Create collision objects for the geometric objects. 
      // (A collision object is just a wrapper around the geometric object that stores additional 
      // information that is required by the collision detection.)
      _collisionObjectA = new CollisionObject(geometricObjectA);
      _collisionObjectB = new CollisionObject(geometricObjectB);

      // Create a collision detection.
      // (The CollisionDetection stores general parameters and it can be used to perform
      // closest-point and contact queries.)
      _collisionDetection = new CollisionDetection();
    }
예제 #6
0
        public void CompositeShapeTest()
        {
            var c = new CompositeShape();

              Assert.AreEqual(0, c.GetVolume(0.1f, 10));

              c.Children.Add(
            new GeometricObject(
              new BoxShape(1, 2, 3),
              new Vector3F(10, 10, 10),
              new Pose(new Vector3F(1, 2, 3), RandomHelper.Random.NextQuaternionF())));
              c.Children.Add(
            new GeometricObject(
              new BoxShape(4, 5, 6),
              new Vector3F(2, 2, 2),
              new Pose(new Vector3F(10, -2, 0), RandomHelper.Random.NextQuaternionF())));

              var v0 = c.GetVolume(0.001f, 10);

              Assert.AreEqual(10 * 20 * 30 + 8 * 10 * 12, v0);
        }
예제 #7
0
     CompositeShape(CompositeShapeDescriptor descriptor)
 {
     WrappedCompositeShape = new DR.Geometry.Shapes.CompositeShape();
     UserData = descriptor.UserData;
     ShapePositionerFactory = new CompositeShapeShapePositionerFactory(this);
 }
예제 #8
0
    public static void Load(CollisionDomain collisionDomain)
    {
      // Create a box for the ground.
      AddObject("Ground", new Pose(new Vector3F(0, -5, 0)), new BoxShape(60, 10, 60), collisionDomain);

      // Create a small flying sphere to visualize the approx. head height. - This is just
      // for debugging so that we have a feeling for heights.
      AddObject("Sphere", new Pose(new Vector3F(0, 1.5f, 0)), new SphereShape(0.2f), collisionDomain);

      // Create small walls at the level boundary.
      AddObject("WallLeft", new Pose(new Vector3F(-30, 1, 0)), new BoxShape(0.3f, 2, 60), collisionDomain);
      AddObject("WallRight", new Pose(new Vector3F(30, 1, 0)), new BoxShape(0.3f, 2, 60), collisionDomain);
      AddObject("WallFront", new Pose(new Vector3F(0, 1, -30)), new BoxShape(60, 2, 0.3f), collisionDomain);
      AddObject("WallBack", new Pose(new Vector3F(0, 1, 30)), new BoxShape(60, 2, 0.3f), collisionDomain);

      // Create a few bigger objects.
      // We position the boxes so that we have a few corners we can run into. Character controllers
      // should be stable when the user runs into corners.
      AddObject("House0", new Pose(new Vector3F(10, 1, -10)), new BoxShape(8, 2, 8f), collisionDomain);
      AddObject("House1", new Pose(new Vector3F(13, 1, -4)), new BoxShape(2, 2, 4), collisionDomain);
      AddObject("House2", new Pose(new Vector3F(10, 2, -15), Matrix33F.CreateRotationY(-0.3f)), new BoxShape(8, 4, 2), collisionDomain);

      //
      // Create stairs with increasing step height.
      //
      // Each step is a box. With this object we can test if our character can climb up
      // stairs. The character controller has a step height limit. Increasing step heights
      // let us test if the step height limit works.
      float startHeight = 0;
      const float stepDepth = 1f;
      for (int i = 0; i < 10; i++)
      {
        float stepHeight = 0.1f + i * 0.05f;
        Pose pose = new Pose(new Vector3F(0, startHeight + stepHeight / 2, -2 - i * stepDepth));
        BoxShape shape = new BoxShape(2, stepHeight, stepDepth);
        AddObject("Step" + i, pose, shape, collisionDomain);
        startHeight += stepHeight;
      }

      //
      // Create a height field.
      //
      // Terrain that is uneven is best modeled with a height field. Height fields are faster
      // than general triangle meshes.
      // The height direction is the y direction. 
      // The height field lies in the x/z plane.
      var numberOfSamplesX = 20;
      var numberOfSamplesZ = 20;
      var samples = new float[numberOfSamplesX * numberOfSamplesZ];
      // Create arbitrary height values. 
      for (int z = 0; z < numberOfSamplesZ; z++)
      {
        for (int x = 0; x < numberOfSamplesX; x++)
        {
          if (x == 0 || z == 0 || x == 19 || z == 19)
          {
            // Set this boundary elements to a low height, so that the height field is connected
            // to the ground.
            samples[z * numberOfSamplesX + x] = -1;
          }
          else
          {
            // A sine/cosine function that creates some interesting waves.
            samples[z * numberOfSamplesX + x] = 1.0f + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1.0f);
          }
        }
      }
      var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ);
      AddObject("Heightfield", new Pose(new Vector3F(10, 0, 10)), heightField, collisionDomain);

      // Create rubble on the floor (small random objects on the floor).
      // Our character should be able to move over small bumps on the ground.
      for (int i = 0; i < 50; i++)
      {
        Pose pose = new Pose(
          new Vector3F(RandomHelper.Random.NextFloat(-5, 5), 0, RandomHelper.Random.NextFloat(10, 20)),
          RandomHelper.Random.NextQuaternionF());
        BoxShape shape = new BoxShape(RandomHelper.Random.NextVector3F(0.05f, 0.8f));
        AddObject("Stone" + i, pose, shape, collisionDomain);
      }

      // Create some slopes to see how our character performs on/under sloped surfaces.
      // Here we can test how the character controller behaves if the head touches an inclined
      // ceiling.
      AddObject("SlopeGround", new Pose(new Vector3F(-2, 1.8f, -12), QuaternionF.CreateRotationX(0.4f)), new BoxShape(2, 0.5f, 10), collisionDomain);
      AddObject("SlopeRoof", new Pose(new Vector3F(-2, 5.6f, -12), QuaternionF.CreateRotationX(-0.4f)), new BoxShape(2, 0.5f, 10), collisionDomain);

      // Slopes with different tilt angles.
      // The character controller has a slope limit. Only flat slopes should be climbable. 
      for (int i = 0; i < 10; i++)
      {
        float stepHeight = 0.1f + i * 0.1f;
        Pose pose = new Pose(
          new Vector3F(-10, i * 0.5f, -i * 2),
          Matrix33F.CreateRotationX(MathHelper.ToRadians(10) + i * MathHelper.ToRadians(10)));
        BoxShape shape = new BoxShape(8 * (1 - i * 0.1f), 0.5f, 30);
        AddObject("Slope" + i, pose, shape, collisionDomain);
        startHeight += stepHeight;
      }

      // Create a slope with a wall on one side.
      // This objects let's us test how the character controller behaves while falling and
      // sliding along a vertical wall. (Run up the slope and then jump down while moving into
      // the wall.)
      AddObject("LongSlope", new Pose(new Vector3F(-20, 3, -10), Matrix33F.CreateRotationX(0.4f)), new BoxShape(4, 5f, 30), collisionDomain);
      AddObject("LongSlopeWall", new Pose(new Vector3F(-22, 5, -10)), new BoxShape(0.5f, 10f, 25), collisionDomain);

      // Create a mesh object to test walking on triangle meshes.
      // Normally, the mesh would be loaded from a file. Here, we make a composite shape and 
      // let DigitalRune Geometry compute a mesh for it. Then we throw away the composite
      // shape and use only the mesh. - We do this to test triangle meshes. Using the composite
      // shape instead of the triangle mesh would be a lot faster.
      CompositeShape compositeShape = new CompositeShape();
      compositeShape.Children.Add(new GeometricObject(heightField, Pose.Identity));
      compositeShape.Children.Add(new GeometricObject(new CylinderShape(1, 2), new Pose(new Vector3F(10, 1, 10))));
      compositeShape.Children.Add(new GeometricObject(new SphereShape(3), new Pose(new Vector3F(15, 0, 15))));
      compositeShape.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Pose(new Vector3F(15, 0, 5))));
      ITriangleMesh mesh = compositeShape.GetMesh(0.01f, 3);
      TriangleMeshShape meshShape = new TriangleMeshShape(mesh);

      // Collision detection speed for triangle meshes can be improved by using a spatial 
      // partition. Here, we assign an AabbTree to the triangle mesh shape. The tree is
      // built automatically when needed and it stores triangle indices (therefore the generic 
      // parameter of the AabbTree is int).
      meshShape.Partition = new AabbTree<int>()
      {
        // The tree is automatically built using a mixed top-down/bottom-up approach. Bottom-up
        // building is slower but produces better trees. If the tree building takes too long,
        // we can lower the BottomUpBuildThreshold (default is 128).
        BottomUpBuildThreshold = 0,
      };

      AddObject("Mesh", new Pose(new Vector3F(-30, 0, 10)), meshShape, collisionDomain);
    }
예제 #9
0
    // 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 Vector3F(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize));
            hull.Points.Add(new Vector3F(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize));
            hull.Points.Add(new Vector3F(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize));
            hull.Points.Add(new Vector3F(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize));
            hull.Points.Add(new Vector3F(-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 Vector3F(0, 0, 0))));
            composite.Children.Add(
              new GeometricObject(
                new BoxShape(2 * ObjectSize, ObjectSize, ObjectSize),
                new Pose(new Vector3F(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 Vector3F(0, 0.5f, 0), Matrix33F.Identity)));
              compBvh.Children.Add(new GeometricObject(new BoxShape(0.8f, 0.5f, 0.5f), new Pose(new Vector3F(0.5f, 0.7f, 0), Matrix33F.CreateRotationZ(-MathHelper.ToRadians(15)))));
              compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3F(0, 1.15f, 0), Matrix33F.Identity)));
              compBvh.Children.Add(new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3F(0.6f, 1.15f, 0), Matrix33F.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 Vector3F(0, 0.5f * ObjectSize, 0), QuaternionF.Identity)));
            comp.Children.Add(new GeometricObject(new BoxShape(0.8f * ObjectSize, 0.5f * ObjectSize, 0.5f * ObjectSize), new Pose(new Vector3F(0.3f * ObjectSize, 0.7f * ObjectSize, 0), QuaternionF.CreateRotationZ(-MathHelper.ToRadians(45)))));
            comp.Children.Add(new GeometricObject(new SphereShape(0.3f * ObjectSize), new Pose(new Vector3F(0, 1.15f * ObjectSize, 0), QuaternionF.Identity)));
            shape = comp;
            break;
          case 10:
            shape = new ConvexHullOfPoints(new[]
            {
              new Vector3F(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize),
              new Vector3F(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize),
              new Vector3F(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3F(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3F(-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 Vector3F(0, 2 * ObjectSize, 0), Matrix33F.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 Vector3F(0.1f, 0.2f, 0.3f), new Vector3F(0.1f, 0.2f, -0.3f).Normalized);
          //break;            
          case 15:
            shape = new LineSegmentShape(
              new Vector3F(0.1f, 0.2f, 0.3f), new Vector3F(0.1f, 0.2f, 0.3f) + 3 * ObjectSize * new Vector3F(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 Vector3F(0.2f, 0, -0.12f), new Vector3F(1, 2, 3).Normalized, ObjectSize * 2);
            break;
          case 22:
            shape = new RayShape(new Vector3F(0.2f, 0, -0.12f), new Vector3F(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 Vector3F(0.1f, 1, -0.2f))));
            break;
          case 25:
            shape = new TriangleShape(
              new Vector3F(ObjectSize, 0, 0), new Vector3F(0, ObjectSize, 0), new Vector3F(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 Vector3F(0, 0.5f, 0), Matrix33F.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(
          //        new BoxShape(0.8f, 0.5f, 0.5f),
          //        new Pose(new Vector3F(0.5f, 0.7f, 0), Matrix33F.CreateRotationZ(-(float)MathHelper.ToRadians(15)))));
          //    compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3F(0, 1.15f, 0), Matrix33F.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3F(0.6f, 1.15f, 0), Matrix33F.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 Vector3F(0, 0.5f, 0), QuaternionF.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(
          //        new BoxShape(0.8f, 0.5f, 0.5f),
          //        new Pose(new Vector3F(0.5f, 0.7f, 0), QuaternionF.CreateRotationZ(-(float)MathHelper.ToRadians(15)))));
          //    compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3F(0, 1.15f, 0), QuaternionF.Identity)));
          //    compBvh.Children.Add(
          //      new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3F(0.6f, 1.15f, 0), QuaternionF.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 Vector3F(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize),
              new Vector3F(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize),
              new Vector3F(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3F(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize),
              new Vector3F(-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.NextVector3F(-BoxSize + ObjectSize * 2, BoxSize - ObjectSize * 2),
          random.NextQuaternionF());
        var newObject = new MovingGeometricObject
        {
          Pose = randomPose,
          Shape = shape,
          LinearVelocity = random.NextQuaternionF().Rotate(new Vector3F(MaxLinearVelocity, 0, 0)),
          AngularVelocity = random.NextQuaternionF().Rotate(Vector3F.Forward)
                            * RandomHelper.Random.NextFloat(0, MaxAngularVelocity),
        };

        if (RandomHelper.Random.NextBool())
          newObject.LinearVelocity = Vector3F.Zero;
        if (RandomHelper.Random.NextBool())
          newObject.AngularVelocity = Vector3F.Zero;

        if (shape is LineShape || shape is HeightField)
        {
          // Do not move lines or the height field.
          newObject.LinearVelocity = Vector3F.Zero;
          newObject.AngularVelocity = Vector3F.Zero;
        }

        // Create only 1 heightField!
        if (shape is HeightField)
        {
          if (isFirstHeightField)
          {
            isFirstHeightField = true;
            newObject.Pose = new Pose(new Vector3F(-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;
      }
    }
예제 #10
0
        public void CompositeShapeWithRotatedChildren()
        {
            var s = new CompositeShape();
              s.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(100, 10, 0), RandomHelper.Random.NextQuaternionF())));
              s.Children.Add(new GeometricObject(new ConeShape(1, 2), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(-10, -10, 0), RandomHelper.Random.NextQuaternionF())));
              float m0;
              Vector3F com0;
              Matrix33F i0;
              MassHelper.GetMass(s, new Vector3F(2), 1, true, 0.001f, 10, out m0, out com0, out i0);

              var m = s.GetMesh(0.001f, 6);
              m.Transform(Matrix44F.CreateScale(2));
              float m1;
              Vector3F com1;
              Matrix33F i1;
              MassHelper.GetMass(m, out m1, out com1, out i1);

              const float e = 0.01f;
              Assert.IsTrue(Numeric.AreEqual(m0, m1, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0, i1, e * (1 + i0.Trace)));
        }
예제 #11
0
    /// <summary>
    /// Initializes the physics simulation.
    /// </summary>
    private void InitializePhysics()
    {
      // Define the timing of the physics simulation:
      // The Windows Phone runs with 30 FPS, so one frame takes 1/30 seconds.
      // We can run the simulation using the same timing.
      // However, 1/30 seconds is a very large time step for a physics simulation. A large
      // time step improves performance, but reduces the quality of the simulation.
      // Instead we can run the simulation with a time step of 1/60 seconds and compute 
      // 2 time steps per frame.
      // Additionally, we can reduce the number of constraint solver iterations to gain additional
      // performance. But if you want to simulate complex scene with stable stacks or walls, you
      // might want to leave the default value.
      // Below are two variants - you can comment/uncomment the variants to compare them.

      // -----  Variant #1: "Fast, less stable"
      Simulation.Settings.Timing.FixedTimeStep = 1.0f / 30.0f;
      Simulation.Settings.Timing.MaxNumberOfSteps = 1;
      Simulation.Settings.Constraints.NumberOfConstraintIterations = 6;

      // ----- Variant #2: "Slower, more stable"
      //_simulation.Settings.Timing.FixedTimeStep = 1.0f / 60.0f;
      //_simulation.Settings.Timing.MaxNumberOfSteps = 2;
      //_simulation.Settings.Constraints.NumberOfConstraintIterations = 10;
      
      // Add the typical force effect for gravity and damping.
      Simulation.ForceEffects.Add(new Gravity { Acceleration = new Vector3F(0, -10, 0) });
      Simulation.ForceEffects.Add(new Damping());

      // Add a ground plane (static object).
      var groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0))
      {
        Name = "GroundPlane",
        MotionType = MotionType.Static,
      };
      Simulation.RigidBodies.Add(groundPlane);

      // Create a set of predefined shapes. 
      // The shapes are chosen randomly when a new rigid body is added.
      _shapes = new List<Shape>();
      _shapes.Add(new BoxShape(1.0f, 1.0f, 1.0f));
      _shapes.Add(new BoxShape(1.5f, 0.5f, 1.0f));
      _shapes.Add(new BoxShape(1.0f, 0.75f, 1.0f));
      _shapes.Add(new CapsuleShape(0.4f, 2.0f));
      _shapes.Add(new SphereShape(0.6f));

      // Add convex shape.
      var randomPoints = new List<Vector3F>();
      for (int i = 0; i < 20; i++)
        randomPoints.Add(RandomHelper.Random.NextVector3F(-1, 1));
      _shapes.Add(new ConvexPolyhedron(randomPoints));

      // Add a composite shape looking like table.
      var board = new BoxShape(2.0f, 0.3f, 1.2f);
      var leg = new BoxShape(0.2f, 1f, 0.2f);
      var table = new CompositeShape();
      table.Children.Add(new GeometricObject(board, new Pose(new Vector3F(0.0f, 1.0f, 0.0f))));
      table.Children.Add(new GeometricObject(leg, new Pose(new Vector3F(-0.7f, 0.5f, -0.4f))));
      table.Children.Add(new GeometricObject(leg, new Pose(new Vector3F(-0.7f, 0.5f, 0.4f))));
      table.Children.Add(new GeometricObject(leg, new Pose(new Vector3F(0.7f, 0.5f, 0.4f))));
      table.Children.Add(new GeometricObject(leg, new Pose(new Vector3F(0.7f, 0.5f, -0.4f))));
      _shapes.Add(table);
    }
예제 #12
0
        public void CompositeShapeWithRigidBodies()
        {
            // The first composite shape does not use rigid bodies.
              var s = new CompositeShape();
              s.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(100, 10, 0), RandomHelper.Random.NextQuaternionF())));
              s.Children.Add(new GeometricObject(new ConeShape(1, 2), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(-10, -10, 0), RandomHelper.Random.NextQuaternionF())));
              float m0;
              Vector3F com0;
              Matrix33F i0;
              MassHelper.GetMass(s, new Vector3F(1), 0.7f, true, 0.001f, 10, out m0, out com0, out i0);

              // The second composite shape uses rigid bodies as children.
              var r0 = new RigidBody(s.Children[0].Shape);
              r0.Pose = s.Children[0].Pose;
              r0.Scale = s.Children[0].Scale;
              r0.MassFrame = MassFrame.FromShapeAndDensity(r0.Shape, r0.Scale, 0.7f, 0.001f, 10);
              var r1 = new RigidBody(s.Children[1].Shape);
              r1.Pose = s.Children[1].Pose;
              r1.Scale = s.Children[1].Scale;
              r1.MassFrame = MassFrame.FromShapeAndDensity(r1.Shape, r1.Scale, 0.7f, 0.001f, 10);
              var s1 = new CompositeShape();
              s1.Children.Add(r0);
              s1.Children.Add(r1);

              float m1;
              Vector3F com1;
              Matrix33F i1;
              MassHelper.GetMass(s1, new Vector3F(1), 100, true, 0.001f, 10, out m1, out com1, out i1);

              const float e = 0.01f;
              Assert.IsTrue(Numeric.AreEqual(m0, m1, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0, i1, e * (1 + i0.Trace)));
        }
예제 #13
0
        public void CompositeShapeWithRigidBodiesDoesNotSupportScaling()
        {
            // The first composite shape does not use rigid bodies.
              var s = new CompositeShape();
              s.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(100, 10, 0), RandomHelper.Random.NextQuaternionF())));
              s.Children.Add(new GeometricObject(new ConeShape(1, 2), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(-10, -10, 0), RandomHelper.Random.NextQuaternionF())));

              // The second composite shape uses rigid bodies as children.
              var r0 = new RigidBody(s.Children[0].Shape);
              r0.Pose = s.Children[0].Pose;
              r0.Scale = s.Children[0].Scale;
              r0.MassFrame = MassFrame.FromShapeAndDensity(r0.Shape, r0.Scale, 0.7f, 0.001f, 10);
              var r1 = new RigidBody(s.Children[1].Shape);
              r1.Pose = s.Children[1].Pose;
              r1.Scale = s.Children[1].Scale;
              r1.MassFrame = MassFrame.FromShapeAndDensity(r1.Shape, r1.Scale, 0.7f, 0.001f, 10);
              var s1 = new CompositeShape();
              s1.Children.Add(r0);
              s1.Children.Add(r1);

              float m1;
              Vector3F com1;
              Matrix33F i1;
              MassHelper.GetMass(s1,
            new Vector3F(2),  // !!!
            100, true, 0.001f, 10, out m1, out com1, out i1);
        }
예제 #14
0
    //--------------------------------------------------------------
    #region Methods
    //--------------------------------------------------------------

    protected override void OnLoad()
    {
      // Add rigid bodies to simulation.
      var simulation = _services.GetInstance<Simulation>();

      // We use a random number generator with a custom seed.
      RandomHelper.Random = new Random(123);

      // ----- Add a ground plane.
      AddBody(simulation, "GroundPlane", Pose.Identity, new PlaneShape(Vector3F.UnitY, 0), MotionType.Static);

      // ----- Create a small flying sphere.
      AddBody(simulation, "Sphere", new Pose(new Vector3F(0, 1f, 0)), new SphereShape(0.2f), MotionType.Static);

      // ----- Create small walls at the level boundary.
      AddBody(simulation, "WallLeft", new Pose(new Vector3F(-30, 1, 0)), new BoxShape(0.3f, 2, 60), MotionType.Static);
      AddBody(simulation, "WallRight", new Pose(new Vector3F(30, 1, 0)), new BoxShape(0.3f, 2, 60), MotionType.Static);
      AddBody(simulation, "WallFront", new Pose(new Vector3F(0, 1, -30)), new BoxShape(60, 2, 0.3f), MotionType.Static);
      AddBody(simulation, "WallBack", new Pose(new Vector3F(0, 1, 30)), new BoxShape(60, 2, 0.3f), MotionType.Static);

      // ----- Create a few bigger objects.
      // We position the boxes so that we have a few corners we can run into. Character controllers
      // should be stable when the user runs into corners.
      AddBody(simulation, "House0", new Pose(new Vector3F(10, 1, -10)), new BoxShape(8, 2, 8f), MotionType.Static);
      AddBody(simulation, "House1", new Pose(new Vector3F(13, 1, -4)), new BoxShape(2, 2, 4), MotionType.Static);
      AddBody(simulation, "House2", new Pose(new Vector3F(10, 2, -15), Matrix33F.CreateRotationY(-0.3f)), new BoxShape(8, 4, 2), MotionType.Static);

      // ----- Create stairs with increasing step height.
      // Each step is a box. With this object we can test if our character can climb up
      // stairs. The character controller has a step height limit. Increasing step heights
      // let us test if the step height limit works.
      float startHeight = 0;
      const float stepDepth = 1f;
      for (int i = 0; i < 10; i++)
      {
        float stepHeight = 0.1f + i * 0.05f;
        Vector3F position = new Vector3F(0, startHeight + stepHeight / 2, -2 - i * stepDepth);
        AddBody(simulation, "Step" + i, new Pose(position), new BoxShape(2, stepHeight, stepDepth), MotionType.Static);

        startHeight += stepHeight;
      }

      // ----- V obstacle to test if we get stuck.
      AddBody(simulation, "V0", new Pose(new Vector3F(-5.5f, 0, 10), QuaternionF.CreateRotationZ(0.2f)), new BoxShape(1f, 2f, 2), MotionType.Static);
      AddBody(simulation, "V1", new Pose(new Vector3F(-4, 0, 10), QuaternionF.CreateRotationZ(-0.2f)), new BoxShape(1f, 2f, 2), MotionType.Static);

      // ----- Create a height field.
      // Terrain that is uneven is best modeled with a height field. Height fields are faster
      // than general triangle meshes.
      // The height direction is the y direction. 
      // The height field lies in the x/z plane.
      var numberOfSamplesX = 20;
      var numberOfSamplesZ = 20;
      var samples = new float[numberOfSamplesX * numberOfSamplesZ];
      // Create arbitrary height values. 
      for (int z = 0; z < numberOfSamplesZ; z++)
      {
        for (int x = 0; x < numberOfSamplesX; x++)
        {
          if (x == 0 || z == 0 || x == 19 || z == 19)
          {
            // Set this boundary elements to a low height, so that the height field is connected
            // to the ground.
            samples[z * numberOfSamplesX + x] = -1;
          }
          else
          {
            // A sine/cosine function that creates some interesting waves.
            samples[z * numberOfSamplesX + x] = 1.0f + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1.0f);
          }
        }
      }
      var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ);
      AddBody(simulation, "HeightField", new Pose(new Vector3F(10, 0, 10)), heightField, MotionType.Static);

      // ----- Create rubble on the floor (small random objects on the floor).
      // Our character should be able to move over small bumps on the ground.
      for (int i = 0; i < 50; i++)
      {
        Vector3F position = new Vector3F(RandomHelper.Random.NextFloat(-5, 5), 0, RandomHelper.Random.NextFloat(10, 20));
        QuaternionF orientation = RandomHelper.Random.NextQuaternionF();
        Vector3F size = RandomHelper.Random.NextVector3F(0.05f, 0.8f);
        AddBody(simulation, "Stone" + i, new Pose(position, orientation), new BoxShape(size), MotionType.Static);
      }

      // ----- Create some slopes to see how our character performs on/under sloped surfaces.
      // Here we can test how the character controller behaves if the head touches an inclined
      // ceiling.
      AddBody(simulation, "SlopeGround", new Pose(new Vector3F(-2, 1.8f, -12), QuaternionF.CreateRotationX(0.4f)), new BoxShape(2, 0.5f, 10), MotionType.Static);
      AddBody(simulation, "SlopeRoof", new Pose(new Vector3F(-2, 5.6f, -12), QuaternionF.CreateRotationX(-0.4f)), new BoxShape(2, 0.5f, 10), MotionType.Static);

      // Create slopes with increasing tilt angles.
      // The character controller has a slope limit. Only flat slopes should be climbable. 
      // Movement between slopes should be smooth.
      Vector3F slopePosition = new Vector3F(-17, -0.25f, 6);
      BoxShape slopeShape = new BoxShape(8, 0.5f, 5);
      for (int i = 1; i < 8; i++)
      {
        Matrix33F oldRotation = Matrix33F.CreateRotationX((i - 1) * MathHelper.ToRadians(10));
        Matrix33F rotation = Matrix33F.CreateRotationX(i * MathHelper.ToRadians(10));

        slopePosition += (oldRotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2
                         + (rotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2;

        AddBody(simulation, "Slope" + i, new Pose(slopePosition, rotation), slopeShape, MotionType.Static);
      }

      // Create slopes with decreasing tilt angles.
      slopePosition = new Vector3F(-8, -2, 5);
      slopeShape = new BoxShape(8f, 0.5f, 5);
      for (int i = 1; i < 8; i++)
      {
        Matrix33F oldRotation = Matrix33F.CreateRotationX(MathHelper.ToRadians(40) - (i - 1) * MathHelper.ToRadians(10));
        Matrix33F rotation = Matrix33F.CreateRotationX(MathHelper.ToRadians(40) - i * MathHelper.ToRadians(10));

        slopePosition += (oldRotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2
                         + (rotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2;
        Vector3F position = slopePosition - rotation * new Vector3F(0, slopeShape.WidthY / 2, 0);

        AddBody(simulation, "Slope2" + i, new Pose(position, rotation), slopeShape, MotionType.Static);
      }

      // ----- Create a slope with a wall on one side.
      // This objects let's us test how the character controller behaves while falling and
      // sliding along a vertical wall. (Run up the slope and then jump down while moving into
      // the wall.)
      AddBody(simulation, "LongSlope", new Pose(new Vector3F(-24, 3, -10), Matrix33F.CreateRotationX(0.4f)), new BoxShape(4, 5f, 30), MotionType.Static);
      AddBody(simulation, "LongSlopeWall", new Pose(new Vector3F(-26, 5, -10)), new BoxShape(0.5f, 10f, 25), MotionType.Static);

      // ----- Create a trigger object that represents a ladder.
      var ladder = AddBody(simulation, "Ladder", new Pose(new Vector3F(-25.7f, 5, 0)), new BoxShape(0.5f, 10f, 1), MotionType.Static);
      ladder.CollisionObject.Type = CollisionObjectType.Trigger;

      // ----- Create a mesh object to test walking on triangle meshes.
      // Normally, the mesh would be loaded from a file. Here, we make a composite shape and 
      // let DigitalRune Geometry compute a mesh for it. Then we throw away the composite
      // shape and use only the mesh. (We do this to test triangle meshes. Using the composite
      // shape instead of the triangle mesh would be a lot faster.)
      CompositeShape compositeShape = new CompositeShape();
      compositeShape.Children.Add(new GeometricObject(heightField, Pose.Identity));
      compositeShape.Children.Add(new GeometricObject(new CylinderShape(1, 2), new Pose(new Vector3F(10, 1, 10))));
      compositeShape.Children.Add(new GeometricObject(new SphereShape(3), new Pose(new Vector3F(15, 0, 15))));
      compositeShape.Children.Add(new GeometricObject(new BoxShape(4, 4, 3), new Pose(new Vector3F(15, 1.5f, 5))));
      compositeShape.Children.Add(new GeometricObject(new BoxShape(4, 4, 3), new Pose(new Vector3F(15, 1.5f, 0))));
      ITriangleMesh mesh = compositeShape.GetMesh(0.01f, 3);
      TriangleMeshShape meshShape = new TriangleMeshShape(mesh);

      // Collision detection speed for triangle meshes can be improved by using a spatial 
      // partition. Here, we assign an AabbTree to the triangle mesh shape. The tree is
      // built automatically when needed and it stores triangle indices (therefore the generic 
      // parameter of the AabbTree is int).
      meshShape.Partition = new AabbTree<int>()
      {
        // The tree is automatically built using a mixed top-down/bottom-up approach. Bottom-up
        // building is slower but produces better trees. If the tree building takes too long,
        // we can lower the BottomUpBuildThreshold (default is 128).
        BottomUpBuildThreshold = 0,
      };

      // Contact welding creates smoother contact normals - but it costs a bit of performance.
      meshShape.EnableContactWelding = true;

      AddBody(simulation, "Mesh", new Pose(new Vector3F(-30, 0, 10)), meshShape, MotionType.Static);

      // ----- Create a seesaw.
      var seesawBase = AddBody(simulation, "SeesawBase", new Pose(new Vector3F(5, 0.5f, 0)), new BoxShape(0.2f, 1, 1), MotionType.Static);
      var seesaw = AddBody(simulation, "Seesaw", new Pose(new Vector3F(5, 1.05f, 0)), new BoxShape(5, 0.1f, 1), MotionType.Dynamic);

      // Attach the seesaw to the base using a hinge joint.
      simulation.Constraints.Add(new HingeJoint
      {
        BodyA = seesaw,
        BodyB = seesawBase,
        AnchorPoseALocal = new Pose(new Vector3F(0, 0, 0),
                                    new Matrix33F(0, 0, -1,
                                                  0, 1, 0,
                                                  1, 0, 0)),
        AnchorPoseBLocal = new Pose(new Vector3F(0, 0.5f, 0),
                                    new Matrix33F(0, 0, -1,
                                                  0, 1, 0,
                                                  1, 0, 0)),
        CollisionEnabled = false,
      });

      // ----- A platform that is moving up/down.
      _elevator = AddBody(simulation, "Elevator", new Pose(new Vector3F(5, -1f, 5)), new BoxShape(3, 1f, 3), MotionType.Kinematic);
      _elevator.LinearVelocity = new Vector3F(2, 2, 0);

      // ----- A platform that is moving sideways.
      _pusher = AddBody(simulation, "Pusher", new Pose(new Vector3F(15, 0.5f, 0)), new BoxShape(3, 1f, 3), MotionType.Kinematic);
      _pusher.LinearVelocity = new Vector3F(0, 0, 2);

      // ----- Create conveyor belt with two static boxes on the sides.
      AddBody(simulation, "ConveyorSide0", new Pose(new Vector3F(19, 0.25f, 0)), new BoxShape(0.8f, 0.5f, 8f), MotionType.Static);
      AddBody(simulation, "ConveyorSide1", new Pose(new Vector3F(21, 0.25f, 0)), new BoxShape(0.8f, 0.5f, 8f), MotionType.Static);

      // The conveyor belt is a simple box with a special material.
      var conveyorBelt = AddBody(simulation, "ConveyorBelt", new Pose(new Vector3F(20, 0.25f, 0)), new BoxShape(1f, 0.51f, 8f), MotionType.Static);
      UniformMaterial materialWithSurfaceMotion = new UniformMaterial("ConveyorBelt", true)  // Important: The second parameter enables the surface
      {                                                                                      // motion. It has to be set to true in the constructor!
        SurfaceMotion = new Vector3F(0, 0, 1),   // The surface motion relative to the object.
      };
      conveyorBelt.Material = materialWithSurfaceMotion;

      // ----- Distribute a few dynamic spheres and boxes across the landscape.
      SphereShape sphereShape = new SphereShape(0.5f);
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = RandomHelper.Random.NextVector3F(-15, 15);
        position.Y = 20;

        AddBody(simulation, "Sphere" + i, new Pose(position), sphereShape, MotionType.Dynamic);
      }

      BoxShape boxShape = new BoxShape(1, 1, 1);
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = RandomHelper.Random.NextVector3F(-15, 15);
        position.Y = 20;

        AddBody(simulation, "Box" + i, new Pose(position), boxShape, MotionType.Dynamic);
      }

    }
예제 #15
0
        public void CompositeShapeWithNonUniformScaling()
        {
            var s = new CompositeShape();
              s.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(100, 10, 0))));
              s.Children.Add(new GeometricObject(new SphereShape(1), new Vector3F(1.1f, 0.3f, 0.8f), new Pose(new Vector3F(-10, -10, 0))));
              float m0;
              Vector3F com0;
              Matrix33F i0;
              MassHelper.GetMass(s, new Vector3F(2, 2.1f, 2.8f), 0.7f, true, 0.001f, 10, out m0, out com0, out i0);

              var m = s.GetMesh(0.001f, 6);
              m.Transform(Matrix44F.CreateScale(2, 2.1f, 2.8f));
              float m1;
              Vector3F com1;
              Matrix33F i1;
              MassHelper.GetMass(m, out m1, out com1, out i1);

              const float e = 0.01f;
              Assert.IsTrue(Numeric.AreEqual(m0, 0.7f * m1, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0, 0.7f * i1, e * (1 + i0.Trace)));

              // Try with target mass.
              float m3;
              Vector3F com3;
              Matrix33F i3;
              MassHelper.GetMass(s, new Vector3F(2, 2.1f, 2.8f), 23, false, 0.001f, 10, out m3, out com3, out i3);
              Assert.IsTrue(Numeric.AreEqual(23, m3, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com3, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0 * 23 / m0, i3, e * (1 + i0.Trace)));
        }
예제 #16
0
    public LightClipSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      _graphicsScreen = new DeferredGraphicsScreen(Services);
      _graphicsScreen.DrawReticle = true;
      GraphicsService.Screens.Insert(0, _graphicsScreen);
      GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

      Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer);
      Services.Register(typeof(IScene), null, _graphicsScreen.Scene);

      // Add gravity and damping to the physics simulation.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Add a custom game object which controls the camera.
      var cameraGameObject = new CameraObject(Services);
      GameObjectService.Objects.Add(cameraGameObject);
      _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode;

      GameObjectService.Objects.Add(new GrabObject(Services));
      GameObjectService.Objects.Add(new DynamicSkyObject(Services, true, false, true));
      GameObjectService.Objects.Add(new GroundObject(Services));

      GameObjectService.Objects.Add(new DudeObject(Services));
      GameObjectService.Objects.Add(new DynamicObject(Services, 1));
      GameObjectService.Objects.Add(new DynamicObject(Services, 2));
      GameObjectService.Objects.Add(new DynamicObject(Services, 3));
      GameObjectService.Objects.Add(new DynamicObject(Services, 4));
      GameObjectService.Objects.Add(new DynamicObject(Services, 6));
      GameObjectService.Objects.Add(new DynamicObject(Services, 7));
      GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
      GameObjectService.Objects.Add(new FogObject(Services));

      // The LavaBalls class controls all lava ball instances.
      var lavaBalls = new LavaBallsObject(Services);
      GameObjectService.Objects.Add(lavaBalls);

      // Create a lava ball instance.
      lavaBalls.Spawn();

      // Add a few palm trees.
      Random random = new Random(12345);
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        float scale = random.NextFloat(0.5f, 1.2f);
        GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation)));
      }

      var boxShape = new BoxShape(3, 3, 3);
      var compositeShape = new CompositeShape
      {
        Children =
        {
          new GeometricObject(boxShape, new Pose(new Vector3F(-2, 1.4f, 0))),
          new GeometricObject(boxShape, new Pose(new Vector3F(2, 1.4f, 0))),
        }
      };
      _clip = new GeometricObject(compositeShape, Pose.Identity);

      foreach (var lightNode in _graphicsScreen.Scene.GetDescendants().OfType<LightNode>())
      {
        lightNode.Clip = _clip;
        //lightNode.InvertClip = true;
      }
    }
예제 #17
0
 CompositeShape(CompositeShapeDescriptor descriptor)
 {
     WrappedCompositeShape = new DR.Geometry.Shapes.CompositeShape();
     UserData = descriptor.UserData;
     ShapePositionerFactory = new CompositeShapeShapePositionerFactory(this);
 }
예제 #18
0
    public override void Update(GameTime gameTime)
    {
      // If progress has changed significantly, get current decomposition.
      if (_newProgress - _oldProgress >= 10
          || _newProgress > 90 && _newProgress - _oldProgress > 1)
      {
        _decomposition = _convexDecomposition.Decomposition;
        _oldProgress = _newProgress;
      }

      var debugRenderer = GraphicsScreen.DebugRenderer;
      debugRenderer.Clear();

      // Draw a wireframe of the model.
      debugRenderer.DrawModel(_modelNode, Color.White, true, false);

      // Show current progress.
      debugRenderer.DrawText("\n\nProgress: " + _newProgress + " %");

      // Draw the current convex hulls.
      if (_decomposition != null)
      {
        foreach (var childGeometry in _decomposition.Children)
          debugRenderer.DrawObject(childGeometry, GraphicsHelper.GetUniqueColor(childGeometry), false, false);

        debugRenderer.DrawText("Number of convex parts: " + _decomposition.Children.Count);
      }
    }
예제 #19
0
    // Creates a lot of random objects.
    private void CreateRandomObjects()
    {
      var random = new Random(12345);

      for (int i = 0; i < NumberOfObjects; i++)
      {
        // Randomly choose a shape.
        Shape randomShape;
        switch (random.Next(0, 7))
        {
          case 0:
            // Box
            randomShape = new BoxShape(ObjectSize, ObjectSize * 2, ObjectSize * 3);
            break;
          case 1:
            // Capsule
            randomShape = new CapsuleShape(0.3f * ObjectSize, 2 * ObjectSize);
            break;
          case 2:
            // Cone
            randomShape = new ConeShape(1 * ObjectSize, 2 * ObjectSize);
            break;
          case 3:
            // Cylinder
            randomShape = new CylinderShape(0.4f * ObjectSize, 2 * ObjectSize);
            break;
          case 4:
            // Sphere
            randomShape = new SphereShape(ObjectSize);
            break;
          case 5:
            // Convex hull of several points.
            ConvexHullOfPoints hull = new ConvexHullOfPoints();
            hull.Points.Add(new Vector3F(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize));
            hull.Points.Add(new Vector3F(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize));
            hull.Points.Add(new Vector3F(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize));
            hull.Points.Add(new Vector3F(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize));
            hull.Points.Add(new Vector3F(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize));
            randomShape = 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 Vector3F(0, 0, 0))));
            composite.Children.Add(
              new GeometricObject(
                new BoxShape(2 * ObjectSize, ObjectSize, ObjectSize),
                new Pose(new Vector3F(0, 2 * ObjectSize, 0))));
            randomShape = composite;
            break;
          default:
#if WINDOWS
            Trace.Fail("Ups, we shouldn't land here :-(");
#endif
            randomShape = new SphereShape();
            break;
        }

        // Create an object with the random shape, pose, color and velocity.
        Pose randomPose = new Pose(
          random.NextVector3F(-BoxSize + ObjectSize * 2, BoxSize - ObjectSize * 2),
          random.NextQuaternionF());

        var newObject = new MovingGeometricObject
        {
          Pose = randomPose,
          Shape = randomShape,
          LinearVelocity = random.NextQuaternionF().Rotate(new Vector3F(MaxLinearVelocity, 0, 0)),
          AngularVelocity = random.NextQuaternionF().Rotate(Vector3F.Forward)
                            * RandomHelper.Random.NextFloat(0, MaxAngularVelocity),
        };

        // Add collision object to collision domain.
        _domain.CollisionObjects.Add(new CollisionObject(newObject));

        // We will collect a few statistics for debugging.
        Profiler.SetFormat("NumObjects", 1, "The total number of objects.");
        Profiler.SetFormat("NumObjectPairs", 1, "The number of objects pairs, which have to be checked.");
        Profiler.SetFormat("BroadPhasePairs", 1, "The number of overlaps reported by the broad phase.");
        Profiler.SetFormat("ContactSetCount", 1, "The number of actual collisions.");
      }
    }
예제 #20
0
        private void CreateCompositeShape()
        {
            // Convert islands into CompositeShape with convex children.
              _decomposition = new CompositeShape();

              if (_islands == null)
            return;

              foreach (var island in _islands)
              {
            if (island.Vertices.Length <= 0)
              continue;

            // ReSharper disable EmptyGeneralCatchClause
            try
            {
              // ----- Get convex hull mesh.
              DcelMesh convexHullMesh;
              if (island.ConvexHullBuilder == null)
              {
            // Create convex hull from scratch.

            // Get all vertices of all island triangles.
            var points = island.Triangles.SelectMany(t => t.Vertices);

            // Create convex hull.
            convexHullMesh = GeometryHelper.CreateConvexHull(points, VertexLimit, SkinWidth);
              }
              else
              {
            // Use existing convex hull.
            convexHullMesh = island.ConvexHullBuilder.Mesh;
            if (convexHullMesh.Vertices.Count > VertexLimit || SkinWidth != 0)
              convexHullMesh.ModifyConvex(VertexLimit, SkinWidth);
              }

              // ----- Add a ConvexPolyhedron to CompositeShape.
              if (convexHullMesh.Vertices.Count > 0)
              {
            var convexHullPoints = convexHullMesh.Vertices.Select(v => v.Position);
            var convexPolyhedron = new ConvexPolyhedron(convexHullPoints);
            var geometricObject = new GeometricObject(convexPolyhedron);
            _decomposition.Children.Add(geometricObject);
              }
            }
            catch
            {
              // Could not generate convex hull. Ignore object.
            }
            // ReSharper restore EmptyGeneralCatchClause
              }
        }
예제 #21
0
        private void DoWork()
        {
            // The locks are released regularly, so that the Decomposition property can be
              // accessed.

              Exception exception = null;
              try
              {
            if ((GlobalSettings.ValidationLevelInternal & GlobalSettings.ValidationLevelUserHighExpensive) != 0)
              ValidateInput();

            lock (_syncRoot)
            {
              _decomposition = null;

              // Create the Dual graph.
              CreateDualGraph();
            }

            // Partitioning process:
            MergeIslands(); // Each internal loop is locked.

            lock (_syncRoot)
            {
              if (!_cancel)
            CreateCompositeShape();
            }

            if (!_cancel)
              OnProgressChanged(100);
              }
              catch (Exception e)
              {
            exception = e;

            if (!IsBusy)  // Throw only when in synchronous decomposition.
              throw;
              }
              finally
              {
            _mesh = null;

            if (IsBusy) // IsBusy is only set for async operations.
            {
              IsBusy = false;

              // Raise completed event.
              var handler = Completed;
              if (handler != null)
            handler(this, new AsyncCompletedEventArgs(exception, _cancel, null));
            }
              }
        }
예제 #22
0
        private void MergeIslands()
        {
            List<CDIslandLink> newLinks = new List<CDIslandLink>();
              List<CDIslandLink> obsoleteLinks = (EnableMultithreading) ? new List<CDIslandLink>() : null;

              while (_links.Count > 0 && !_cancel)
              {
            lock (_syncRoot)
            {
              // Find link with lowest decimation cost.
              CDIslandLink bestLink = _links[0];
              int bestLinkIndex = 0;
              for (int i = 0; i < _links.Count; i++)
              {
            var link = _links[i];
            if (link.DecimationCost < bestLink.DecimationCost)
            {
              bestLink = link;
              bestLinkIndex = i;
            }
              }

              // Remove the found link.
              _links.RemoveAt(bestLinkIndex);

              // Ignore links that have exceeded the concavity limit.
              if (bestLink.Concavity > AllowedConcavity)
            continue;

              // The created composite shape is now invalid again.
              _decomposition = null;

              // Remove island B
              _islands.Remove(bestLink.IslandB);

              // Merge the islands of the best link into island A.
              foreach (var triangle in bestLink.IslandB.Triangles)
            triangle.Island = bestLink.IslandA;
              bestLink.IslandA.Triangles = bestLink.IslandA.Triangles.Union(bestLink.IslandB.Triangles).ToArray();
              bestLink.IslandA.Aabb = bestLink.Aabb;
              bestLink.IslandA.Vertices = bestLink.Vertices;
              bestLink.IslandA.ConvexHullBuilder = bestLink.ConvexHullBuilder;

              // Remove old links where A and B are involved and add new
              // links with A.
              if (!EnableMultithreading)
              {
            for (int i = _links.Count - 1; i >= 0; i--)
            {
              var link = _links[i];
              CDIsland otherIsland = null;
              if (link.IslandA == bestLink.IslandA || link.IslandA == bestLink.IslandB)
                otherIsland = link.IslandB;
              else if (link.IslandB == bestLink.IslandA || link.IslandB == bestLink.IslandB)
                otherIsland = link.IslandA;

              // This link does not link to the merged islands.
              if (otherIsland == null)
                continue;

              // Remove link.
              _links.RemoveAt(i);

              // If _newLinks already contains a link with otherIsland we are done.
              bool linkExists = false;
              foreach (var newLink in newLinks)
              {
                if (newLink.IslandA == otherIsland || newLink.IslandB == otherIsland)
                {
                  linkExists = true;
                  break;
                }
              }

              if (linkExists)
                continue;

              // Create link between otherIsland and bestLink.IslandA.
              link = new CDIslandLink(otherIsland, bestLink.IslandA, AllowedConcavity, SmallIslandBoost,
                                      IntermediateVertexLimit, SampleTriangleVertices, SampleTriangleCenters);
              newLinks.Add(link);
            }
              }
              else
              {
            // Experimental multithreading hack.
            // Note: When multithreading is enabled the result is non-deterministic
            // because the order of the links in the _links list change...
            Parallel.ForEach(_links, link =>
            {
              CDIsland otherIsland = null;
              if (link.IslandA == bestLink.IslandA || link.IslandA == bestLink.IslandB)
                otherIsland = link.IslandB;
              else if (link.IslandB == bestLink.IslandA || link.IslandB == bestLink.IslandB)
                otherIsland = link.IslandA;

              // This link does not link to the merged islands.
              if (otherIsland == null)
                return;

              // Remove link.
              lock (obsoleteLinks)
                obsoleteLinks.Add(link);

              // If _newLinks already contains a link with otherIsland we are done.
              lock (newLinks)
              {
                foreach (var newLink in newLinks)
                  if (newLink.IslandA == otherIsland || newLink.IslandB == otherIsland)
                    return;
              }

              // Create link between otherIsland and bestLink.IslandA.
              link = new CDIslandLink(otherIsland, bestLink.IslandA, AllowedConcavity, SmallIslandBoost,
                                      IntermediateVertexLimit, SampleTriangleVertices, SampleTriangleCenters);

              // Add link but only if another thread did not add a similar link.
              // TODO: Can this happen or can we remove this check.
              lock (newLinks)
              {
                foreach (var newLink in newLinks)
                  if (newLink.IslandA == otherIsland || newLink.IslandB == otherIsland)
                    return;

                newLinks.Add(link);
              }
            });

            foreach (var link in obsoleteLinks)
              _links.Remove(link);

            obsoleteLinks.Clear();
              }

              // Add new links.
              _links.AddRange(newLinks);
              newLinks.Clear();

              OnProgressChanged((_mesh.NumberOfTriangles - _islands.Count) * 100 / _mesh.NumberOfTriangles);
            }
              }
        }
예제 #23
0
    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>()
      {
        // The tree is automatically built using a mixed top-down/bottom-up approach. Bottom-up
        // building is slower but produces better trees. If the tree building takes too long,
        // we can lower the BottomUpBuildThreshold (default is 128).
        BottomUpBuildThreshold = 0,
      };

      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);
      }
    }
예제 #24
0
    protected override void OnLoad()
    {
      // Add rigid bodies to simulation.
      var simulation = _services.GetInstance<Simulation>();

      // ----- Add a ground plane.
      AddBody(simulation, "GroundPlane", Pose.Identity, new PlaneShape(Vector3F.UnitY, 0), MotionType.Static);

      // ----- Create a height field.
      var numberOfSamplesX = 20;
      var numberOfSamplesZ = 20;
      var samples = new float[numberOfSamplesX * numberOfSamplesZ];
      for (int z = 0; z < numberOfSamplesZ; z++)
      {
        for (int x = 0; x < numberOfSamplesX; x++)
        {
          if (x == 0 || z == 0 || x == 19 || z == 19)
          {
            samples[z * numberOfSamplesX + x] = -1;
          }
          else
          {
            samples[z * numberOfSamplesX + x] = 1.0f + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1.0f);
          }
        }
      }
      HeightField heightField = new HeightField(0, 0, 120, 120, samples, numberOfSamplesX, numberOfSamplesZ);
      //heightField.UseFastCollisionApproximation = true;
      AddBody(simulation, "HeightField", new Pose(new Vector3F(10, 0, 20)), heightField, MotionType.Static);

      // ----- Create rubble on the floor (small random objects on the floor).
      for (int i = 0; i < 60; i++)
      {
        Vector3F position = new Vector3F(RandomHelper.Random.NextFloat(-5, 5), 0, RandomHelper.Random.NextFloat(10, 20));
        QuaternionF orientation = RandomHelper.Random.NextQuaternionF();
        BoxShape shape = new BoxShape(RandomHelper.Random.NextVector3F(0.05f, 0.5f));
        AddBody(simulation, "Stone" + i, new Pose(position, orientation), shape, MotionType.Static);
      }

      // ----- Slopes with different tilt angles.
      // Create a loop.
      Vector3F slopePosition = new Vector3F(-20, -0.25f, -5);
      BoxShape slopeShape = new BoxShape(8, 0.5f, 2);
      for (int i = 1; i < 33; i++)
      {
        Matrix33F oldRotation = Matrix33F.CreateRotationX((i - 1) * MathHelper.ToRadians(10));
        Matrix33F rotation = Matrix33F.CreateRotationX(i * MathHelper.ToRadians(10));

        slopePosition += (oldRotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2
                         + (rotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2;

        AddBody(simulation, "Loop" + i, new Pose(slopePosition, rotation), slopeShape, MotionType.Static);
      }

      // Create an arched bridge.
      slopePosition = new Vector3F(-10, -2, -15);
      slopeShape = new BoxShape(8f, 0.5f, 5);
      for (int i = 1; i < 8; i++)
      {
        Matrix33F oldRotation = Matrix33F.CreateRotationX(MathHelper.ToRadians(40) - (i - 1) * MathHelper.ToRadians(10));
        Matrix33F rotation = Matrix33F.CreateRotationX(MathHelper.ToRadians(40) - i * MathHelper.ToRadians(10));

        slopePosition += (oldRotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2
                         + (rotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2;
        Vector3F position = slopePosition - rotation * new Vector3F(0, slopeShape.WidthY / 2, 0);

        AddBody(simulation, "Bridge" + i, new Pose(position, rotation), slopeShape, MotionType.Static);
      }

      // ----- Create a mesh object.
      // We first build a composite shape out of several primitives and then convert the 
      // composite shape to a triangle mesh. (Just for testing.)
      CompositeShape compositeShape = new CompositeShape();
      compositeShape.Children.Add(new GeometricObject(heightField, Pose.Identity));
      compositeShape.Children.Add(new GeometricObject(new CylinderShape(1, 2), new Pose(new Vector3F(10, 1, 10))));
      compositeShape.Children.Add(new GeometricObject(new SphereShape(3), new Pose(new Vector3F(15, 0, 15))));
      compositeShape.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Pose(new Vector3F(15, 0, 5))));
      ITriangleMesh mesh = compositeShape.GetMesh(0.01f, 3);
      TriangleMeshShape meshShape = new TriangleMeshShape(mesh, true);
      meshShape.Partition = new AabbTree<int>() { BottomUpBuildThreshold = 0 };
      AddBody(simulation, "Mesh", new Pose(new Vector3F(-120, 0, 20)), meshShape, MotionType.Static);

      // ----- Create a seesaw.
      var seesawBase = AddBody(simulation, "SeesawBase", new Pose(new Vector3F(15, 0.5f, 0)), new BoxShape(0.2f, 1, 6), MotionType.Static);
      var seesaw = AddBody(simulation, "Seesaw", new Pose(new Vector3F(16, 1.05f, 0)), new BoxShape(15, 0.1f, 6), MotionType.Dynamic);
      seesaw.MassFrame.Mass = 500;
      seesaw.CanSleep = false;

      // Connect seesaw using a hinge joint.
      simulation.Constraints.Add(new HingeJoint
      {
        BodyA = seesaw,
        BodyB = seesawBase,
        AnchorPoseALocal = new Pose(new Vector3F(1.0f, 0, 0),
                                    new Matrix33F(0, 0, -1,
                                                  0, 1, 0,
                                                  1, 0, 0)),
        AnchorPoseBLocal = new Pose(new Vector3F(0, 0.5f, 0),
                                    new Matrix33F(0, 0, -1,
                                                  0, 1, 0,
                                                  1, 0, 0)),
        CollisionEnabled = false,
      });


      // ----- Distribute a few dynamic spheres and boxes across the landscape.
      SphereShape sphereShape = new SphereShape(0.5f);
      for (int i = 0; i < 40; i++)
      {
        Vector3F position = RandomHelper.Random.NextVector3F(-60, 60);
        position.Y = 10;
        AddBody(simulation, "Sphere" + i, new Pose(position), sphereShape, MotionType.Dynamic);
      }

      BoxShape boxShape = new BoxShape(1.0f, 1.0f, 1.0f);
      for (int i = 0; i < 40; i++)
      {
        Vector3F position = RandomHelper.Random.NextVector3F(-60, 60);
        position.Y = 1;
        AddBody(simulation, "Box" + i, new Pose(position), boxShape, MotionType.Dynamic);
      }
    }