예제 #1
0
    public CustomGravitySample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      // Add basic force effects.
      Simulation.ForceEffects.Add(new CustomGravity());
      Simulation.ForceEffects.Add(new Damping());

      // Add a static sphere that represents the planet.
      RigidBody planet = new RigidBody(new SphereShape(5))
      {
        MotionType = MotionType.Static,
      };
      Simulation.RigidBodies.Add(planet);

      // ----- Add a few cylinder and sphere bodies at random positions above the planet.
      Shape cylinderShape = new CylinderShape(0.3f, 1);
      for (int i = 0; i < 10; i++)
      {
        // A random position 10 m above the planet center.
        Vector3F randomPosition = RandomHelper.Random.NextVector3F(-1, 1);
        randomPosition.Length = 10;

        RigidBody body = new RigidBody(cylinderShape)
        {
          Pose = new Pose(randomPosition),
        };
        Simulation.RigidBodies.Add(body);
      }

      Shape sphereShape = new SphereShape(0.5f);
      for (int i = 0; i < 10; i++)
      {
        Vector3F randomPosition = RandomHelper.Random.NextVector3F(-1, 1);
        randomPosition.Length = 10;

        RigidBody body = new RigidBody(sphereShape)
        {
          Pose = new Pose(randomPosition),
        };
        Simulation.RigidBodies.Add(body);
      }
    }
예제 #2
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);
      }
    }
예제 #3
0
        private static void GetMass(CylinderShape cylinder, Vector3F scale, float densityOrMass, bool isDensity, out float mass, out Matrix33F inertia)
        {
            scale = Vector3F.Absolute(scale);
              float radiusX = cylinder.Radius * scale.X;
              float heightY = cylinder.Height * scale.Y;
              float radiusZ = cylinder.Radius * scale.Z;
              mass = (isDensity) ? ConstantsF.Pi * radiusX * radiusZ * heightY * densityOrMass : densityOrMass;

              inertia = Matrix33F.Zero;
              inertia.M00 = 1.0f / 4.0f * mass * radiusZ * radiusZ + 1.0f / 12.0f * mass * heightY * heightY;
              inertia.M11 = 1.0f / 4.0f * mass * radiusX * radiusX + 1.0f / 4.0f * mass * radiusZ * radiusZ;
              inertia.M22 = 1.0f / 4.0f * mass * radiusX * radiusX + 1.0f / 12.0f * mass * heightY * heightY;
        }
예제 #4
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;
      }
    }
예제 #5
0
        public void GeneralShape()
        {
            var s = new CylinderShape(1, 3);
              float m0;
              Vector3F com0;
              Matrix33F i0;
              MassHelper.GetMass(s, new Vector3F(1, -2, -3), 0.7f, true, 0.001f, 4, out m0, out com0, out i0);

              var m = s.GetMesh(0.001f, 10);
              var s2 = new TriangleMeshShape(m);
              float m1;
              Vector3F com1;
              Matrix33F i1;
              MassHelper.GetMass(s2, new Vector3F(1, -2, -3), 0.7f, true, 0.001f, 4, 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)));

              // Try with target mass.
              float m2;
              Vector3F com2;
              Matrix33F i2;
              MassHelper.GetMass(s2, new Vector3F(1, -2, -3), 23, false, 0.001f, 4, out m2, out com2, out i2);
              Assert.IsTrue(Numeric.AreEqual(23, m2, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com2, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0 * 23 / m0, i2, e * (1 + i0.Trace)));
        }
예제 #6
0
    public BuoyancySample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      // Add basic force effects.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // ----- Buoyancy Force Effect
      // Buoyancy is a force effect that lets bodies swim in water. The water area is 
      // defined by two properties: 
      //  - Buoyancy.AreaOfEffect defines which objects are affected.
      //  - Buoyancy.Surface defines the water level within this area.

      // The area of effect can be defined in different ways. In this sample we will use 
      // a geometric object ("trigger volume").

      // First, define the shape of the water area. We will create simple pool.
      Shape poolShape = new BoxShape(16, 10, 16);
      Vector3F poolCenter = new Vector3F(0, -5, 0);

      // Then create a geometric object for the water area. (A GeometricObject is required
      // to position the shape in the world. A GeometricObject stores shape, scale, position,
      // orientation, ...)
      GeometricObject waterGeometry = new GeometricObject(poolShape, new Pose(poolCenter));

      // Then create a collision object for the geometric object. (A CollisionObject required
      // because the geometry should be used for collision detection with other objects.)
      _waterCollisionObject = new CollisionObject(waterGeometry)
      {
        // Assign the object to a different collision group:
        // The Grab component (see Grab.cs) uses a ray to perform hit tests. We don't want the ray
        // to collide with the water. Therefore, we need to assign the water collision object to a 
        // different collision group. The general geometry is in collision group 0. The rays are in 
        // collision group 2. Add the water to collision group 1. Collision between 0 and 2 are 
        // enabled. Collision between 1 and 2 need to be disabled - this collision filter was set 
        // in PhysicsGame.cs.
        CollisionGroup = 1,

        // Set the type to "Trigger". This improves the performance because the collision 
        // detection does not need to compute detailed contact information. The collision
        // detection only returns whether an objects has contact with the water.
        Type = CollisionObjectType.Trigger,
      };

      // The collision object needs to be added into the collision domain of the simulation.
      Simulation.CollisionDomain.CollisionObjects.Add(_waterCollisionObject);

      // Now we can add the buoyancy effect.
      Buoyancy buoyancy = new Buoyancy
      {
        AreaOfEffect = new GeometricAreaOfEffect(_waterCollisionObject),
        Surface = new Plane(Vector3F.Up, 0),

        Density = 1000f,    // The density of water (1000 kg/m³).
        AngularDrag = 0.4f,
        LinearDrag = 4f,

        // Optional: Let the objects drift in the water by setting a flow velocity. 
        //Velocity = new Vector3F(-0.5f, 0, 0.5f),
      };
      Simulation.ForceEffects.Add(buoyancy);


      // Add static area around the pool.
      RigidBody bottom = new RigidBody(new BoxShape(36, 2, 36))
      {
        MotionType = MotionType.Static,
        Pose = new Pose(new Vector3F(0, -11, 0)),
      };
      Simulation.RigidBodies.Add(bottom);
      RigidBody left = new RigidBody(new BoxShape(10, 10, 36))
      {
        MotionType = MotionType.Static,
        Pose = new Pose(new Vector3F(-13, -5, 0)),
      };
      Simulation.RigidBodies.Add(left);
      RigidBody right = new RigidBody(new BoxShape(10, 10, 36))
      {
        MotionType = MotionType.Static,
        Pose = new Pose(new Vector3F(13, -5, 0)),
      };
      Simulation.RigidBodies.Add(right);
      RigidBody front = new RigidBody(new BoxShape(16, 10, 10))
      {
        MotionType = MotionType.Static,
        Pose = new Pose(new Vector3F(0, -5, 13)),
      };
      Simulation.RigidBodies.Add(front);
      RigidBody back = new RigidBody(new BoxShape(16, 10, 10))
      {
        MotionType = MotionType.Static,
        Pose = new Pose(new Vector3F(0, -5, -13)),
      };
      Simulation.RigidBodies.Add(back);

      // ----- Add some random objects to test the effect.
      // Note: Objects swim if their density is less than the density of water. They sink
      // if the density is greater than the density of water.
      // We can define the density of objects by explicitly setting the mass.

      // Add a swimming board.
      BoxShape raftShape = new BoxShape(4, 0.3f, 4);
      MassFrame raftMass = MassFrame.FromShapeAndDensity(raftShape, Vector3F.One, 700, 0.01f, 3);
      RigidBody raft = new RigidBody(raftShape, raftMass, null)
      {
        Pose = new Pose(new Vector3F(0, 4, 0)),
      };
      Simulation.RigidBodies.Add(raft);

      // Add some boxes on top of the swimming board.
      BoxShape boxShape = new BoxShape(1, 1, 1);
      MassFrame boxMass = MassFrame.FromShapeAndDensity(boxShape, Vector3F.One, 700, 0.01f, 3);
      for (int i = 0; i < 5; i++)
      {
        RigidBody box = new RigidBody(boxShape, boxMass, null)
        {
          Pose = new Pose(new Vector3F(0, 5 + i * 1.1f, 0)),
        };
        Simulation.RigidBodies.Add(box);
      }

      // Add some "heavy stones" represented as spheres.
      SphereShape stoneShape = new SphereShape(0.5f);
      MassFrame stoneMass = MassFrame.FromShapeAndDensity(stoneShape, Vector3F.One, 2500, 0.01f, 3);
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = RandomHelper.Random.NextVector3F(-9, 9);
        position.Y = 5;

        RigidBody stone = new RigidBody(stoneShape, stoneMass, null)
        {
          Pose = new Pose(position),
        };
        Simulation.RigidBodies.Add(stone);
      }

      // Add some very light objects.
      CylinderShape cylinderShape = new CylinderShape(0.3f, 1);
      MassFrame cylinderMass = MassFrame.FromShapeAndDensity(cylinderShape, Vector3F.One, 500, 0.01f, 3);
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = RandomHelper.Random.NextVector3F(-9, 9);
        position.Y = 5;
        QuaternionF orientation = RandomHelper.Random.NextQuaternionF();

        RigidBody cylinder = new RigidBody(cylinderShape, cylinderMass, null)
        {
          Pose = new Pose(position, orientation),
        };
        Simulation.RigidBodies.Add(cylinder);
      }
    }
예제 #7
0
        public void CylinderMass()
        {
            var s = new CylinderShape(1, 3);
              float m0;
              Vector3F com0;
              Matrix33F i0;
              MassHelper.GetMass(s, new Vector3F(1, -2, -3), 1, true, 0.001f, 10, out m0, out com0, out i0);

              var m = s.GetMesh(0.001f, 10);
              m.Transform(Matrix44F.CreateScale(1, -2, -3));
              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)));

              // Try other density.
              float m2;
              Vector3F com2;
              Matrix33F i2;
              MassHelper.GetMass(s, new Vector3F(1, -2, -3), 0.7f, true, 0.001f, 10, out m2, out com2, out i2);
              Assert.IsTrue(Numeric.AreEqual(m0 * 0.7f, m2, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com2, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0 * 0.7f, i2, e * (1 + i0.Trace)));

              // Try with target mass.
              float m3;
              Vector3F com3;
              Matrix33F i3;
              MassHelper.GetMass(s, new Vector3F(1, -2, -3), 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)));
        }
예제 #8
0
        public void TriangleMeshShapeTest()
        {
            var s = new CylinderShape(1, 2);
              var v0 = s.GetVolume(0.001f, 10);

              var m = s.GetMesh(0.001f, 10);
              var s1 = new TriangleMeshShape(m);
              var v1 = m.GetVolume();

              Assert.IsTrue(Numeric.AreEqual(v0, v1, 0.01f * (1 + v0)));  // 1% error is allowed.
        }
예제 #9
0
        public void ScaledConvexShape()
        {
            var s = new CylinderShape(1, 2);
              var v0 = s.GetVolume(0.001f, 10);

              var s1 = new ScaledConvexShape(new CylinderShape(10, 10), new Vector3F(0.1f, 0.2f, 0.1f));
              var v1 = s1.GetVolume(0.0001f, 10);

              Assert.IsTrue(Numeric.AreEqual(v0, v1, 0.01f * (1 + v0)));  // 1% error is allowed.
        }
예제 #10
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.");
      }
    }
예제 #11
0
    public ConstraintCarSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      // Add basic force effects.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Create a material with high friction - this will be used for the ground and the wheels
      // to give the wheels some traction.
      UniformMaterial roughMaterial = new UniformMaterial
      {
        DynamicFriction = 1,
        StaticFriction = 1,
      };

      // Add a ground plane.
      RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0), null, roughMaterial)
      {
        MotionType = MotionType.Static,
      };
      Simulation.RigidBodies.Add(groundPlane);

      // Now, we build a car out of one box for the chassis and 4 cylindric wheels. 
      // Front wheels are fixed with Hinge2Joints and motorized with AngularVelocityMotors.
      // Back wheels are fixed with HingeJoints and not motorized. - This creates a sloppy
      // car configuration. Please note that cars for racing games are not normally built with 
      // simple constraints - nevertheless, it is funny to do and play with it.

      // Check out the "Vehicle Sample" (not included in this project)! The "Vehicle Sample" 
      // provides a robust ray-car implementation.)

      // ----- Chassis
      BoxShape chassisShape = new BoxShape(1.7f, 1, 4f);
      MassFrame chassisMass = MassFrame.FromShapeAndDensity(chassisShape, Vector3F.One, 200, 0.01f, 3);
      // Here is a trick: The car topples over very easily. By lowering the center of mass we 
      // make it more stable.
      chassisMass.Pose = new Pose(new Vector3F(0, -1, 0));
      RigidBody chassis = new RigidBody(chassisShape, chassisMass, null)
      {
        Pose = new Pose(new Vector3F(0, 1, 0)),
      };
      Simulation.RigidBodies.Add(chassis);

      // ------ Wheels
      CylinderShape cylinderShape = new CylinderShape(0.4f, 0.3f);
      MassFrame wheelMass = MassFrame.FromShapeAndDensity(cylinderShape, Vector3F.One, 500, 0.01f, 3);
      RigidBody wheelFrontLeft = new RigidBody(cylinderShape, wheelMass, roughMaterial)
      {
        Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
      };
      Simulation.RigidBodies.Add(wheelFrontLeft);
      RigidBody wheelFrontRight = new RigidBody(cylinderShape, wheelMass, roughMaterial)
      {
        Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
      };
      Simulation.RigidBodies.Add(wheelFrontRight);
      RigidBody wheelBackLeft = new RigidBody(cylinderShape, wheelMass, roughMaterial)
      {
        Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
      };
      Simulation.RigidBodies.Add(wheelBackLeft);
      RigidBody wheelBackRight = new RigidBody(cylinderShape, wheelMass, roughMaterial)
      {
        Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
      };
      Simulation.RigidBodies.Add(wheelBackRight);

      // ----- Hinge2Joints for the front wheels.
      // A Hinge2Joint allows a limited rotation on the first constraint axis - the steering
      // axis. The second constraint axis is locked and the third constraint axis is the 
      // rotation axis of the wheels.
      _frontLeftHinge = new Hinge2Joint
      {
        BodyA = chassis,
        // --> To define the constraint anchor orientation for the chassis:
        // The columns are the axes. We set the local y axis in the first column. This is
        // steering axis. In the last column we set the -x axis. This is the wheel rotation axis.
        // In the middle column is a vector that is normal to the first and last axis.
        // (All three columns are orthonormal and form a valid rotation matrix.)
        AnchorPoseALocal = new Pose(new Vector3F(-0.9f, -0.4f, -1.4f),
                                    new Matrix33F(0, 0, -1,
                                                  1, 0, 0,
                                                  0, -1, 0)),
        BodyB = wheelFrontLeft,
        // --> To define the constraint anchor orientation for the chassis:
        // The columns are the axes. We set the local x axis in the first column. This is
        // steering axis. In the last column we set the y axis. This is the wheel rotation axis.
        // (In local space of a cylinder the cylinder axis is the +y axis.)
        // In the middle column is a vector that is normal to the first and last axis.
        // (All three columns are orthonormal and form a valid rotation matrix.)
        AnchorPoseBLocal = new Pose(new Matrix33F(1, 0, 0,
                                                  0, 0, 1,
                                                  0, -1, 0)),
        CollisionEnabled = false,
        Minimum = new Vector2F(-0.7f, float.NegativeInfinity),
        Maximum = new Vector2F(0.7f, float.PositiveInfinity),
      };
      Simulation.Constraints.Add(_frontLeftHinge);

      _frontRightHinge = new Hinge2Joint
      {
        BodyA = chassis,
        BodyB = wheelFrontRight,
        AnchorPoseALocal = new Pose(new Vector3F(0.9f, -0.4f, -1.4f),
                                    new Matrix33F(0, 0, -1,
                                                  1, 0, 0,
                                                  0, -1, 0)),
        AnchorPoseBLocal = new Pose(new Matrix33F(1, 0, 0,
                                                  0, 0, 1,
                                                  0, -1, 0)),
        CollisionEnabled = false,
        Minimum = new Vector2F(-0.7f, float.NegativeInfinity),
        Maximum = new Vector2F(0.7f, float.PositiveInfinity),
      };
      Simulation.Constraints.Add(_frontRightHinge);

      // ----- HingeJoints for the back wheels.
      // Hinges allow free rotation on the first constraint axis.
      HingeJoint backLeftHinge = new HingeJoint
      {
        BodyA = chassis,
        AnchorPoseALocal = new Pose(new Vector3F(-0.9f, -0.4f, 1.4f)),
        BodyB = wheelBackLeft,
        // --> To define the constraint anchor orientation:
        // The columns are the axes. We set the local y axis in the first column. This is
        // cylinder axis and should be the hinge axis. In the other two columns we set two 
        // orthonormal vectors.
        // (All three columns are orthonormal and form a valid rotation matrix.)
        AnchorPoseBLocal = new Pose(new Matrix33F(0, 0, 1,
                                                  1, 0, 0,
                                                  0, 1, 0)),
        CollisionEnabled = false,
      };
      Simulation.Constraints.Add(backLeftHinge);
      HingeJoint backRightHinge = new HingeJoint
      {
        BodyA = chassis,
        AnchorPoseALocal = new Pose(new Vector3F(0.9f, -0.4f, 1.4f)),
        BodyB = wheelBackRight,
        AnchorPoseBLocal = new Pose(new Matrix33F(0, 0, 1,
                                                  1, 0, 0,
                                                  0, 1, 0)),
        CollisionEnabled = false,
      };
      Simulation.Constraints.Add(backRightHinge);

      // ----- Motors for the front wheels.
      // (Motor axes and target velocities are set in Update() below.)
      _frontLeftMotor = new AngularVelocityMotor
      {
        BodyA = chassis,
        BodyB = wheelFrontLeft,
        CollisionEnabled = false,

        // We use "single axis mode", which means the motor drives only on axis and does not
        // block motion orthogonal to this axis. - Rotation about the orthogonal axes is already
        // controlled by the Hinge2Joint.
        UseSingleAxisMode = true,

        // The motor has only limited power:
        MaxForce = 50000,
      };
      Simulation.Constraints.Add(_frontLeftMotor);

      _frontRightMotor = new AngularVelocityMotor
      {
        BodyA = chassis,
        BodyB = wheelFrontRight,
        CollisionEnabled = false,
        UseSingleAxisMode = true,
        MaxForce = 50000,
      };
      Simulation.Constraints.Add(_frontRightMotor);

      // ----- Drop a few boxes to create obstacles.
      BoxShape boxShape = new BoxShape(1, 1, 1);
      MassFrame boxMass = MassFrame.FromShapeAndDensity(boxShape, Vector3F.One, 100, 0.01f, 3);
      for (int i = 0; i < 20; i++)
      {
        Vector3F position = RandomHelper.Random.NextVector3F(-20, 20);
        position.Y = 5;
        QuaternionF orientation = RandomHelper.Random.NextQuaternionF();

        RigidBody body = new RigidBody(boxShape, boxMass, null)
        {
          Pose = new Pose(position, orientation),
        };
        Simulation.RigidBodies.Add(body);
      }
    }