コード例 #1
0
    protected override void OnLoad()
    {
      var contentManager = _services.GetInstance<ContentManager>();

      // ----- Graphics
      // Load a graphics model and add it to the scene for rendering.
      _modelNode = contentManager.Load<ModelNode>("Ship/Ship").Clone();
      _modelNode.PoseWorld = new Pose(Vector3F.Zero, Matrix33F.CreateRotationY(-ConstantsF.PiOver2));

      var scene = _services.GetInstance<IScene>();
      scene.Children.Add(_modelNode);

      // ----- Collision Detection
      // Create a collision object and add it to the collision domain.

      // Load collision shape from a separate model (created using the CollisionShapeProcessor).
      var shape = contentManager.Load<Shape>("Ship/Ship_CollisionModel");

      // Create a GeometricObject (= Shape + Pose + Scale).
      _geometricObject = new GeometricObject(shape, _modelNode.PoseWorld);

      // Create a collision object and add it to the collision domain.
      _collisionObject = new CollisionObject(_geometricObject);

      // Important: We do not need detailed contact information when a collision
      // is detected. The information of whether we have contact or not is sufficient.
      // Therefore, we can set the type to "Trigger". This increases the performance 
      // dramatically.
      _collisionObject.Type = CollisionObjectType.Trigger;

      // Add the collision object to the collision domain of the game.
      var collisionDomain = _services.GetInstance<CollisionDomain>();
      collisionDomain.CollisionObjects.Add(_collisionObject);
    }
コード例 #2
0
        /// <summary>
        /// Creates a new <see cref="GeometricObject"/> that is a clone (deep copy) of the current
        /// instance.
        /// </summary>
        /// <returns>
        /// A new <see cref="GeometricObject"/> that is a clone (deep copy) of the current instance.
        /// </returns>
        /// <remarks>
        /// <strong>Notes to Inheritors:</strong> The method <see cref="Clone"/> calls
        /// <see cref="CreateInstanceCore"/> which is responsible for creating a new instance of the
        /// <see cref="GeometricObject"/> derived class and <see cref="CloneCore"/> to create a copy of
        /// the current instance. Classes that derive from <see cref="GeometricObject"/> need to
        /// implement <see cref="CreateInstanceCore"/> and <see cref="CloneCore"/>.
        /// </remarks>
        public GeometricObject Clone()
        {
            GeometricObject clone = CreateInstance();

            clone.CloneCore(this);
            return(clone);
        }
コード例 #3
0
    protected override void OnLoad()
    {
      var contentManager = _services.GetInstance<ContentManager>();

      // ----- Graphics
      // Load graphics model (created using the ModelWithCollisionMeshProcessor).
      var sharedModelNode = contentManager.Load<ModelNode>("Saucer/saucer");

      // Let's create a clone because we do not want to change the shared Saucer 
      // instance stored in the content manager.
      _modelNode = sharedModelNode.Clone();

      _modelNode.PoseWorld = new Pose(Vector3F.Zero, Matrix33F.CreateRotationY(-ConstantsF.PiOver2));

      // The collision shape is stored in the UserData.
      var shape = (Shape)_modelNode.UserData;

      // Add model to the scene for rendering.
      var scene = _services.GetInstance<IScene>();
      scene.Children.Add(_modelNode);

      // ----- Collision Detection
      // Create a collision object and add it to the collision domain.
      _geometricObject = new GeometricObject(shape, _modelNode.PoseWorld);
      _collisionObject = new CollisionObject(_geometricObject);

      // Important: We do not need detailed contact information when a collision
      // is detected. The information of whether we have contact or not is sufficient.
      // Therefore, we can set the type to "Trigger". This increases the performance 
      // dramatically.
      _collisionObject.Type = CollisionObjectType.Trigger;

      var collisionDomain = _services.GetInstance<CollisionDomain>();
      collisionDomain.CollisionObjects.Add(_collisionObject);
    }
コード例 #4
0
ファイル: Wheel.cs プロジェクト: Zolniu/DigitalRune
        //--------------------------------------------------------------
        /// <summary>
        /// Initializes a new instance of the <see cref="Wheel"/> class.
        /// </summary>
        public Wheel()
        {
            Radius = 0.4f;
              SuspensionRestLength = 0.6f;
              MinSuspensionLength = float.NegativeInfinity;
              SuspensionLength = SuspensionRestLength;
              PreviousSuspensionLength = SuspensionRestLength;
              SuspensionStiffness = 20;
              SuspensionCompressionDamping = 4f;
              SuspensionRelaxationDamping = 3f;
              MaxSuspensionForce = 6000;
              RollingFrictionForce = 500;
              Friction = 0.9f;
              RollReduction = 0.3f;

              Vector3F rayOrigin = Vector3F.Zero;
              Vector3F rayDirection = -Vector3F.UnitY;
              float rayLength = Radius + SuspensionRestLength;
              Ray = new RayShape(rayOrigin, rayDirection, rayLength)
              {
            StopsAtFirstHit = true,
              };
              GeometricObject = new GeometricObject(Ray);
              CollisionObject = new CollisionObject(GeometricObject);
        }
コード例 #5
0
    public SpatialPartitionSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.Gray;
      GraphicsScreen.DrawReticle = true;
      SetCamera(new Vector3F(0, 1, 10), 0, 0);

      // Create a spatial partition. DigitalRune Geometry supports several types, see also
      // http://digitalrune.github.io/DigitalRune-Documentation/html/e32cab3b-cc7c-42ee-8ec9-23dd4467edd0.htm#WhichPartition
      // An AabbTree is useful for static objects. A DynamicAabbTree is good for moving objects.
      // The spatial partition can manage different types of items. In this case it manages
      // GeometricObjects. A delegate has to inform the spatial partition how to get the AABB
      // of an object.
      //_spatialPartition = new DynamicAabbTree<GeometricObject>
      _spatialPartition = new AabbTree<GeometricObject>
      {
        GetAabbForItem = geometricObject => geometricObject.Aabb,

        // Optional: 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,

        // Optional: A filter can be set to disable certain kind of overlaps.
        //Filter = ...
      };

      // Create a triangle mesh.
      var triangleMesh = new SphereShape(1).GetMesh(0.01f, 4);
      var triangleMeshShape = new TriangleMeshShape(triangleMesh)
      {
        // TriangleMeshShapes can also use a spatial partition to manage triangle.
        // The items in the spatial partition are the triangle indices. The GetAabbForItem
        // delegate is set automatically.
        Partition = new AabbTree<int>(),
      };

      // Spatial partitions are built automatically when needed. However, it is still recommended
      // to call Update to initialize the spatial partition explicitly.
      triangleMeshShape.Partition.Update(false);

      // Add a lot of triangle mesh objects to _spatialPartition.
      var random = new Random();
      for (int i = 0; i < 50; i++)
      {
        var randomPosition = new Vector3F(random.NextFloat(-6, 6), random.NextFloat(-3, 3), random.NextFloat(-10, 0));
        var geometricObject = new GeometricObject(triangleMeshShape, new Pose(randomPosition));
        _spatialPartition.Add(geometricObject);
      }

      _spatialPartition.Update(false);
    }
コード例 #6
0
    public CollisionDetectionSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
      SetCamera(new Vector3F(0, 1, 10), 0, 0);

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

      // Create a geometric object with a box shape.
      // Position it on the left with an arbitrary rotation.
      var geometricObjectA = new GeometricObject(
        new BoxShape(1, 2, 3),
        new Pose(new Vector3F(-2, -1, 0), Matrix33F.CreateRotationZ(0.1f)));

      // Create a geometric object with a capsule shape.
      // Position it on the right with an arbitrary rotation.
      var geometricObjectB = new GeometricObject(
        new CapsuleShape(1, 3),
        new Pose(new Vector3F(2, -1, 0), Matrix33F.CreateRotationZ(-0.2f)));

      // Create a geometric object with a complex shape that is the convex hull of
      // a circle and a rectangle. Position it on the top with an arbitrary rotation.
      // (A ConvexHullOfShapes is a collection of different shapes with different
      // positions and orientations. The ConvexHullOfShapes combines these shapes
      // into a single shape by building their convex hull.)
      var complexShape = new ConvexHullOfShapes();
      complexShape.Children.Add(new GeometricObject(new RectangleShape(1, 1), new Pose(new Vector3F(0, 0, 1))));
      complexShape.Children.Add(new GeometricObject(new CircleShape(1), new Pose(new Vector3F(0, 0, -1))));
      var geometricObjectC = new GeometricObject(
        complexShape,
        new Pose(new Vector3F(0, 2, 0), QuaternionF.CreateRotation(Vector3F.UnitZ, new Vector3F(1, 1, 1))));

      // 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);
      _collisionObjectC = new CollisionObject(geometricObjectC);

      // Create a collision detection.
      // (The CollisionDetection stores general parameters and it can be used to
      // perform closest-point and contact queries.)
      _collisionDetection = new CollisionDetection();

      // Create a new collision domain and add the collision objects.
      // (A CollisionDomain manages multiple collision objects. It improves the
      // performance of contact queries by reusing results of the last frame.)
      _domain = new CollisionDomain(_collisionDetection);
      _domain.CollisionObjects.Add(_collisionObjectA);
      _domain.CollisionObjects.Add(_collisionObjectB);
      _domain.CollisionObjects.Add(_collisionObjectC);
    }
コード例 #7
0
     SimpleFixture(DR.RigidBody wrappedRigidBody, FixtureDescriptor descriptor)
 {
     _wrappedRigidBody = wrappedRigidBody;
     _wrappedGeometricObject = new GeometricObject(new EmptyShape(), descriptor.Pose.ToDigitalRune());
     _wrappedRigidBody.Shape = new TransformedShape(_wrappedGeometricObject);
     _wrappedRigidBody.Material = new UniformMaterial();
     UserData = descriptor.UserData;
     _pose = descriptor.Pose;
     ShapeFactory = new SimpleFixtureShapeFactory(this);
     _root = true;
     MaterialFactory = new SimpleFixtureMaterialFactory(this);
 }
コード例 #8
0
        public void GetScreenSizeWithOrthographic()
        {
            // Camera
              var projection = new OrthographicProjection();
              projection.SetOffCenter(0, 4, 0, 2);
              var camera = new Camera(projection);
              var cameraNode = new CameraNode(camera);
              cameraNode.PoseWorld = new Pose(new Vector3F(123, 456, -789), Matrix33F.CreateRotation(new Vector3F(1, -2, 3), MathHelper.ToRadians(75)));

              // 2:1 viewport
              var viewport = new Viewport(10, 10, 200, 100);

              // Test object
              var shape = new SphereShape();
              var geometricObject = new GeometricObject(shape);

              // Empty sphere at camera position.
              shape.Radius = 0;
              geometricObject.Pose = cameraNode.PoseWorld;
              Vector2F screenSize = GraphicsHelper.GetScreenSize(cameraNode, viewport, geometricObject);
              Assert.AreEqual(0, screenSize.X);
              Assert.AreEqual(0, screenSize.Y);

              // Empty sphere centered at near plane.
              shape.Radius = 0;
              geometricObject.Pose = cameraNode.PoseWorld * new Pose(new Vector3F(0.123f, -0.543f, -1));
              screenSize = GraphicsHelper.GetScreenSize(cameraNode, viewport, geometricObject);
              Assert.AreEqual(0, screenSize.X);
              Assert.AreEqual(0, screenSize.Y);

              // Create sphere which as a bounding sphere of ~1 unit diameter:
              // Since the bounding sphere is based on the AABB, we need to make the
              // actual sphere a bit smaller.
              shape.Radius = 1 / (2 * (float)Math.Sqrt(3)) + Numeric.EpsilonF;

              // Sphere at camera position.
              geometricObject.Pose = cameraNode.PoseWorld;
              screenSize = GraphicsHelper.GetScreenSize(cameraNode, viewport, geometricObject);
              Assert.IsTrue(Numeric.AreEqual(screenSize.X, 50.0f, 10f));
              Assert.IsTrue(Numeric.AreEqual(screenSize.Y, 50.0f, 10f));

              // Sphere at near plane.
              geometricObject.Pose = cameraNode.PoseWorld * new Pose(new Vector3F(0.123f, -0.543f, -1));
              screenSize = GraphicsHelper.GetScreenSize(cameraNode, viewport, geometricObject);
              Assert.IsTrue(Numeric.AreEqual(screenSize.X, 50.0f, 10f));
              Assert.IsTrue(Numeric.AreEqual(screenSize.Y, 50.0f, 10f));

              // Double distance --> same size
              geometricObject.Pose = cameraNode.PoseWorld * new Pose(new Vector3F(0.123f, -0.543f, -2));
              screenSize = GraphicsHelper.GetScreenSize(cameraNode, viewport, geometricObject);
              Assert.IsTrue(Numeric.AreEqual(screenSize.X, 50.0f, 10f));
              Assert.IsTrue(Numeric.AreEqual(screenSize.Y, 50.0f, 10f));
        }
コード例 #9
0
 public SimpleFixture(GeometricObject geometricObject, List<UniformMaterial> materialCollection, UniformMaterial material, FixtureDescriptor descriptor, Matrix4x4 realParentPose)
 {
     _wrappedGeometricObject = geometricObject;
     _materialCollection = materialCollection;
     _material = material;
     UserData = descriptor.UserData;
     ShapeFactory = new SimpleFixtureShapeFactory(this);
     MaterialFactory = new SimpleFixtureMaterialFactory(this);
     _pose = descriptor.Pose;
     _root = false;
     _realParentPose = realParentPose;
 }
コード例 #10
0
        private GeometricObject CreateInstance()
        {
            GeometricObject newInstance = CreateInstanceCore();

            if (GetType() != newInstance.GetType())
            {
                string message = String.Format(
                    CultureInfo.InvariantCulture,
                    "Cannot clone geometric object. The derived class {0} does not implement CreateInstanceCore().",
                    GetType());

                throw new InvalidOperationException(message);
            }

            return(newInstance);
        }
コード例 #11
0
    public DebugRendererSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService)
      {
        RenderCallback = Render,
      };
      GraphicsService.Screens.Insert(0, delegateGraphicsScreen);

      // Add a custom game object which controls the camera.
      _cameraObject = new CameraObject(Services);
      GameObjectService.Objects.Add(_cameraObject);

      // Load a sprite font.
      var spriteFont = UIContentManager.Load<SpriteFont>("UI Themes/BlendBlue/Default");

      // Create a new debug renderer.
      _debugRenderer = new DebugRenderer(GraphicsService, spriteFont)
      {
        DefaultColor = Color.White,
      };

      // A normal XNA model.
      _xnaModel = ContentManager.Load<Model>("Saucer3/saucer");

      // A DigitalRune model.
      _modelNode = ContentManager.Load<ModelNode>("Dude/Dude").Clone();
      _modelNode.PoseLocal = new Pose(new Vector3F(6, 0, -7));

      // Create a geometric object with a height field shape.
      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++)
          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);
      _geometricObject = new GeometricObject(heightField, new Pose(new Vector3F(5, 0, -5)))
      {
        Scale = new Vector3F(0.01f, 0.05f, 0.02f),
      };
    }
コード例 #12
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();
    }
コード例 #13
0
 protected virtual void CloneCore(GeometricObject source)
 {
   Pose = source.Pose;
   Shape = source.Shape.Clone();
   Scale = source.Scale;
 }
コード例 #14
0
 public ShapePositioner(ShapePositionerDescriptor descriptor)
 {
     WrappedGeometricObject = new GeometricObject();
     Descriptor = descriptor;
     ShapeFactory = new ShapePositionerShapeFactory(this);
 }
コード例 #15
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);
      }
    }
コード例 #16
0
    public CollisionFilterSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.Gray;
      GraphicsScreen.DrawReticle = true;
      SetCamera(new Vector3F(0, 0, 10), 0, 0);

      // ----- Initialize collision detection system.
      // We use one collision domain that manages all objects.
      var domain = new CollisionDomain();

      // Let's set a filter which disables collision between object in the same collision group.
      // We can use a broad phase or a narrow phase filter:

      // Option A) Broad phase filter
      // The collision detection broad phase computes bounding box overlaps. 
      // A broad phase filter is best used if the filtering rules are simple and do not change 
      // during the runtime of your application.
      //domain.BroadPhase.Filter = new DelegatePairFilter<CollisionObject>(
      //  pair => pair.First.CollisionGroup != pair.Second.CollisionGroup);

      // Option B) Narrow phase filter
      // The collision detection narrow phase computes contacts between objects where the broad
      // phase has detected a bounding box overlap. Use a narrow phase filter if the filtering rules 
      // are complex or can change during the runtime of your application.
      var filter = new CollisionFilter();
      // Disable collision between objects in the same groups.
      filter.Set(0, 0, false);
      filter.Set(1, 1, false);
      filter.Set(2, 2, false);
      filter.Set(3, 3, false);
      domain.CollisionDetection.CollisionFilter = filter;

      // Create a random list of points.
      var points = new List<Vector3F>();
      for (int i = 0; i < 100; i++)
        points.Add(RandomHelper.Random.NextVector3F(-1.5f, 1.5f));

      // Add lots of spheres to the collision domain. Assign spheres to different collision groups.
      var random = new Random();
      var sphereShape = new SphereShape(0.7f);
      for (int i = 0; i < 20; i++)
      {
        var randomPosition = new Vector3F(random.NextFloat(-6, 6), random.NextFloat(-3, 3), 0);
        var geometricObject = new GeometricObject(sphereShape, new Pose(randomPosition));
        var collisionObject = new CollisionObject(geometricObject)
        {
          // A collision group is simply an integer. We can assign collision objects to collision
          // groups to control the collision filtering.
          CollisionGroup = random.NextInteger(0, 3),
        };
        domain.CollisionObjects.Add(collisionObject);
      }

      // Compute collisions. (The objects do not move in this sample. Therefore, we only have to 
      // call Update once.)
      domain.Update(0);

      // Draw objects. The color depends on the collision group.
      var debugRenderer = GraphicsScreen.DebugRenderer;
      debugRenderer.Clear();
      foreach (var collisionObject in domain.CollisionObjects)
      {
        Color color;
        switch (collisionObject.CollisionGroup)
        {
          case 0: color = Color.LightBlue; break;
          case 1: color = Color.Yellow; break;
          case 2: color = Color.Orange; break;
          default: color = Color.LightGreen; break;
        }

        debugRenderer.DrawObject(collisionObject.GeometricObject, color, false, false);
      }

      debugRenderer.DrawContacts(domain.ContactSets, 0.1f, Color.Red, true);
    }
コード例 #17
0
 public void GetScreenSizeException()
 {
     var viewport = new Viewport(10, 10, 200, 100);
       var geometricObject = new GeometricObject(new SphereShape());
       GraphicsHelper.GetScreenSize(null, viewport, geometricObject);
 }
コード例 #18
0
    private bool HasLedgeContact()
    {
      // Here is a primitive way to detect ledges and edges where the character can climb:
      // We use a box that is ~10 cm high and wider than the character capsule. We check for 
      // collisions in the top part of the character and a second time on a lower positions.
      // If the top part is free of collisions and the lower part collides with something, then
      // we have found a ledge and let the character hang onto it.

      // Note: This objects should not be allocated in each frame. Create them once, add them
      // to the collision domain and move them with the character controller - like the ray
      // of the DynamicCharacterController.
      BoxShape box = new BoxShape(CharacterController.Width + 0.2f, 0.1f, CharacterController.Width + 0.2f);
      GeometricObject geometricObject = new GeometricObject(box)
      {
        Pose = new Pose(CharacterController.Position + new Vector3F(0, 1.6f, 0))
      };
      var collisionObject = new CollisionObject(geometricObject)
      {
        CollisionGroup = 4,                 // Should not collide with character.
        Type = CollisionObjectType.Trigger, // Use a trigger because we do not need to compute detailed
      };                                    // collision information.

      // First test:
      if (_simulation.CollisionDomain.HasContact(collisionObject))
        return false;

      // Second test:
      geometricObject.Pose = new Pose(CharacterController.Position + new Vector3F(0, 1.5f, 0));
      if (_simulation.CollisionDomain.HasContact(collisionObject))
        return true;

      return false;
    }
コード例 #19
0
 protected virtual void CloneCore(GeometricObject source)
 {
     Pose  = source.Pose;
     Shape = source.Shape.Clone();
     Scale = source.Scale;
 }
コード例 #20
0
        private void SynchronizeShape()
        {
            Debug.Assert(ParticleSystem != null);

              // Note: Scene does not allow TransformedShapes with infinite shapes.
              // --> Handle infinite shapes explicitly. (The code below only checks for InfiniteShape.
              // LineShape or PlaneShape will raise an exception in Scene!)

              if (ParticleSystem.ReferenceFrame == ParticleReferenceFrame.Local || ParticleSystem.Shape is InfiniteShape)
              {
            Shape = ParticleSystem.Shape;
              }
              else
              {
            // Particles are simulated in world space. ParticleSystem.Shape must not be scale by
            // SceneNode.ScaleWorld. --> Add a TransformedShape that negates the scale.
            var transformedShape = Shape as TransformedShape;
            if (transformedShape == null)
            {
              transformedShape = new TransformedShape(new GeometricObject());
              Shape = transformedShape;
            }

            var geometricObject = transformedShape.Child as GeometricObject;
            if (geometricObject == null)
            {
              geometricObject = new GeometricObject();
              transformedShape.Child = geometricObject;
            }

            geometricObject.Shape = ParticleSystem.Shape;
            geometricObject.Scale = Vector3F.One / ScaleWorld;
              }
        }
コード例 #21
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;
      }
    }
コード例 #22
0
ファイル: LodGroupNode.cs プロジェクト: Zolniu/DigitalRune
        /// <summary>
        /// Gets a bounding shape that matches the specified AABB.
        /// </summary>
        /// <param name="aabb">The AABB.</param>
        /// <returns>A box or transformed box that matches the specified AABB.</returns>
        private Shape GetBoundingShape(Aabb aabb)
        {
            // The AABB of the LOD is real world size including scaling. We have to undo
              // the scale because this LodGroupNode also applies the same scale.
              var unscaledCenter = aabb.Center / ScaleWorld;
              var unscaledExtent = aabb.Extent / ScaleWorld;

              // Get existing shape objects to avoid unnecessary memory allocation.
              BoxShape boxShape;
              GeometricObject geometricObject = null;
              TransformedShape transformedShape = null;
              if (Shape is BoxShape)
              {
            boxShape = (BoxShape)Shape;
              }
              else if (Shape is TransformedShape)
              {
            transformedShape = (TransformedShape)Shape;
            geometricObject = (GeometricObject)transformedShape.Child;
            boxShape = (BoxShape)geometricObject.Shape;
              }
              else
              {
            boxShape = new BoxShape();
              }

              // Make bounding box the size of the unscaled AABB.
              boxShape.Extent = unscaledExtent;

              if (unscaledCenter.IsNumericallyZero)
              {
            // Bounding box is centered at origin.
            return boxShape;
              }

              // Apply offset to bounding box.
              if (transformedShape == null)
              {
            geometricObject = new GeometricObject(boxShape, new Pose(unscaledCenter));
            transformedShape = new TransformedShape(geometricObject);
              }
              else
              {
            geometricObject.Shape = boxShape;
            geometricObject.Pose = new Pose(unscaledCenter);
              }

              return transformedShape;
        }
コード例 #23
0
    public override void Update(GameTime gameTime)
    {
      var lastFileIndex = _fileIndex;
      if (InputService.IsPressed(Keys.NumPad7, true))
        _fileIndex++;
      if (InputService.IsPressed(Keys.NumPad4, true))
        _fileIndex--;
      if (_fileIndex < 0)
        _fileIndex = MaxFileIndex;
      if (_fileIndex > MaxFileIndex)
        _fileIndex = 0;
      if (lastFileIndex != _fileIndex)
      {
        LoadFile();
        _pointIndex = -1;
      }

      var lastPointIndex = _pointIndex;
      if (InputService.IsPressed(Keys.Right, true))
        _pointIndex++;
      if (InputService.IsPressed(Keys.Left, true))
        _pointIndex--;
      if (_pointIndex <= 0)
        _pointIndex = _points.Count;
      if (_pointIndex > _points.Count)
        _pointIndex = 1;

      var lastSkinWidth = _skinWidth;
      if (InputService.IsDown(Keys.Up))
        _skinWidth *= 1.1f;
      if (InputService.IsDown(Keys.Down))
        _skinWidth /= 1.1f;

      if (lastPointIndex != _pointIndex || _skinWidth != lastSkinWidth)
      {
        var watch = Stopwatch.StartNew();
        DcelMesh hull = GeometryHelper.CreateConvexHull(_points.Take(_pointIndex), int.MaxValue, _skinWidth);
        watch.Stop();
        _loadTime = (float)watch.Elapsed.TotalMilliseconds;
        _mesh = hull.ToTriangleMesh();
        _geometricObject = new GeometricObject(new TriangleMeshShape(_mesh));
      }

      var debugRenderer = GraphicsScreen.DebugRenderer;
      debugRenderer.Clear();
      debugRenderer.DrawAxes(Pose.Identity, 1, false);
      debugRenderer.DrawObject(_geometricObject, new Color(0.5f, 0.5f, 0.5f, 0.8f), false, false);
      debugRenderer.DrawObject(_geometricObject, Color.Black, true, true);
      foreach (var point in _points)
        debugRenderer.DrawPoint(point, Color.White, false);

      debugRenderer.DrawText(
        "\n\nFile: " + _fileIndex + "\n" +
        "Point Index: " + _pointIndex + "\n" +
        "Time: " + _loadTime + "\n");
    }
コード例 #24
0
    // Adds a game object and adds a collision object to the collision domain.
    private static void AddObject(string name, Pose pose, Shape shape, CollisionDomain collisionDomain)
    {
      // Create game object.
      var geometricObject = new GeometricObject(shape, pose);

      // Create collision object.
      var collisionObject = new CollisionObject(geometricObject)
      {
        CollisionGroup = 1,
      };

      // Add collision object to collision domain.
      collisionDomain.CollisionObjects.Add(collisionObject);
    }
コード例 #25
0
    private bool _cullingEnabled = true;   // True to use frustum culling. False to disable frustum culling.


    public FrustumCullingSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.CornflowerBlue;

      // The top-down camera.
      var orthographicProjection = new OrthographicProjection();
      orthographicProjection.Set(
        LevelSize * 1.1f * GraphicsService.GraphicsDevice.Viewport.AspectRatio,
        LevelSize * 1.1f,
        1,
        10000f);
      var topDownCamera = new Camera(orthographicProjection);
      _topDownCameraNode = new CameraNode(topDownCamera)
      {
        View = Matrix44F.CreateLookAt(new Vector3F(0, 1000, 0), new Vector3F(0, 0, 0), -Vector3F.UnitZ),
      };

      // The perspective camera moving through the scene.
      var perspectiveProjection = new PerspectiveProjection();
      perspectiveProjection.SetFieldOfView(
        MathHelper.ToRadians(45),
        GraphicsService.GraphicsDevice.Viewport.AspectRatio,
        1,
        500);
      var sceneCamera = new Camera(perspectiveProjection);
      _sceneCameraNode = new CameraNode(sceneCamera);

      // Initialize collision detection.
      // We use one collision domain that manages all objects.
      _domain = new CollisionDomain(new CollisionDetection())
      {
        // We exchange the default broad phase with a DualPartition. The DualPartition
        // has special support for frustum culling.
        BroadPhase = new DualPartition<CollisionObject>(),
      };

      // Create a lot of random objects and add them to the collision domain.
      RandomHelper.Random = new Random(12345);
      for (int i = 0; i < NumberOfObjects; i++)
      {
        // A real scene consists of a lot of complex objects such as characters, vehicles,
        // buildings, lights, etc. When doing frustum culling we need to test each objects against
        // the viewing frustum. If it intersects with the viewing frustum, the object is visible
        // from the camera's point of view. However, in practice we do not test the exact object
        // against the viewing frustum. Each objects is approximated by a simpler shape. In our
        // example, we assume that each object is approximated with an oriented bounding box.
        // (We could also use an other shape, such as a bounding sphere.)

        // Create a random box.
        Shape randomShape = new BoxShape(RandomHelper.Random.NextVector3F(1, 10));

        // Create a random position.
        Vector3F randomPosition;
        randomPosition.X = RandomHelper.Random.NextFloat(-LevelSize / 2, LevelSize / 2);
        randomPosition.Y = RandomHelper.Random.NextFloat(0, 2);
        randomPosition.Z = RandomHelper.Random.NextFloat(-LevelSize / 2, LevelSize / 2);

        // Create a random orientation.
        QuaternionF randomOrientation = RandomHelper.Random.NextQuaternionF();

        // Create object and add it to collision domain.
        var geometricObject = new GeometricObject(randomShape, new Pose(randomPosition, randomOrientation));
        var collisionObject = new CollisionObject(geometricObject)
        {
          CollisionGroup = 0,
        };
        _domain.CollisionObjects.Add(collisionObject);
      }

      // Per default, the collision domain computes collision between all objects. 
      // In this sample we do not need this information and disable it with a collision 
      // filter.
      // In a real application, we would use this collision information for rendering,
      // for example, to find out which lights overlap with which meshes, etc.
      var filter = new CollisionFilter();
      // Disable collision between objects in collision group 0.
      filter.Set(0, 0, false);
      _domain.CollisionDetection.CollisionFilter = filter;

      // Start with the scene camera.
      GraphicsScreen.CameraNode = _sceneCameraNode;

      // We will collect a few statistics for debugging.
      Profiler.SetFormat("NoCull", 1000, "Time in ms to submit DebugRenderer draw jobs without frustum culling.");
      Profiler.SetFormat("WithCull", 1000, "Time in ms to submit DebugRenderer draw jobs with frustum culling.");
    }
コード例 #26
0
        private float _slopeLimit = ConstantsF.PiOver4; // = 45°

        #endregion Fields

        #region Constructors

        //--------------------------------------------------------------
        /// <summary>
        /// Initializes a new instance of the <see cref="KinematicCharacterController"/> class.
        /// </summary>
        /// <param name="simulation">The simulation.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="simulation" /> is <see langword="null"/>.
        /// </exception>
        public DynamicCharacterController(Simulation simulation)
        {
            if (simulation == null)
            throw new ArgumentNullException("simulation");

              Simulation = simulation;

              CapsuleShape shape = new CapsuleShape(0.4f, 1.8f);
              MassFrame mass = new MassFrame { Mass = 80 };  // Push strength is proportional to the mass!
              UniformMaterial material = new UniformMaterial
              {
            // The body should be frictionless, so that it can be easily pushed by the simulation to
            // valid positions. And it does not slow down when sliding along walls.
            StaticFriction = 0.0f,
            DynamicFriction = 0.0f,

            // The body should not bounce when being hit or pushed.
            Restitution = 0
              };

              Body = new RigidBody(shape, mass, material)
              {
            // We set the mass explicitly and it should not automatically change when the
            // shape is changed; e.g. a ducked character has a smaller shape, but still the same mass.
            AutoUpdateMass = false,

            // This body is under our control and should never be deactivated by the simulation.
            CanSleep = false,
            CcdEnabled = true,

            // The capsule does not rotate in any direction.
            LockRotationX = true,
            LockRotationY = true,
            LockRotationZ = true,

            Name = "CharacterController",

            Pose = new Pose(new Vector3F(0, shape.Height / 2, 0)),
              };

              // Create a ray that senses the space below the capsule. The ray starts in the capsule
              // center (to detect penetrations) and extends 0.4 units below the capsule bottom.
              RayShape rayShape = new RayShape(Vector3F.Zero, -Vector3F.UnitY, shape.Height / 2 + 0.4f)
              {
            StopsAtFirstHit = true,
              };
              GeometricObject rayGeometry = new GeometricObject(rayShape, Body.Pose);
              _ray = new CollisionObject(rayGeometry);

              // Whenever the Body moves, the ray moves with it.
              Body.PoseChanged += (s, e) => rayGeometry.Pose = Body.Pose;

              // Enable the character controller. (Adds body to simulation.)
              Enabled = true;
        }
コード例 #27
0
    private void StandUp()
    {
      // Similar to crouch - only we make the character capsule taller again. 
      // Before we change the height of the capsule we need to check if there is enough 
      // room to stand up. To check this we position a smaller capsule in this area and
      // test for collisions.
      CapsuleShape testCapsule = new CapsuleShape(0.38f, 1.6f);
      GeometricObject testObject = new GeometricObject(testCapsule, new Pose(CharacterController.Position + 1.0f * Vector3F.UnitY));
      CollisionObject testCollisionObject = new CollisionObject(testObject)
      {
        CollisionGroup = 4,                 // Should not collide with the character.
        Type = CollisionObjectType.Trigger, // Use a trigger because we do not need to compute detailed
      };                                    // collision information.

      // Check whether the test capsule touches anything.
      if (!_simulation.CollisionDomain.HasContact(testCollisionObject))
      {
        // No contact, enough room to stand up.
        CharacterController.Height = 1.8f;

        // The drawing data in the UserData (see RigidBodyRenderer) must be invalidated.
        CharacterController.Body.UserData = null;
      }
    }
コード例 #28
0
    /// <summary>
    /// Gets a bounding shape that matches the specified AABB.
    /// </summary>
    /// <param name="aabb">The AABB.</param>
    /// <returns>A box or transformed box that matches the specified AABB.</returns>
    private Shape GetBoundingShape(Aabb aabb)
    {
      // Get existing shape objects to avoid unnecessary memory allocation.
      BoxShape boxShape;
      GeometricObject geometricObject = null;
      TransformedShape transformedShape = null;
      if (Shape is BoxShape)
      {
        boxShape = (BoxShape)Shape;
      }
      else if (Shape is TransformedShape)
      {
        transformedShape = (TransformedShape)Shape;
        geometricObject = (GeometricObject)transformedShape.Child;
        boxShape = (BoxShape)geometricObject.Shape;
      }
      else
      {
        boxShape = new BoxShape();
      }

      // Make box the size of the AABB.
      boxShape.Extent = aabb.Extent;

      if (aabb.Center.IsNumericallyZero)
      {
        // Bounding box is centered at origin.
        return boxShape;
      }
      
      // Apply offset to bounding box.
      if (transformedShape == null)
      {
        geometricObject = new GeometricObject(boxShape, new Pose(aabb.Center));
        transformedShape = new TransformedShape(geometricObject);
      }
      else
      {
        geometricObject.Shape = boxShape;
        geometricObject.Pose = new Pose(aabb.Center);
      }

      return transformedShape;
    }
コード例 #29
0
    //--------------------------------------------------------------
    #region Creation & Cleanup
    //--------------------------------------------------------------

    public CharacterController(CollisionDomain domain)
    {
      _collisionDomain = domain;

      // Create a game object for the character controller.
      GeometricObject = new GeometricObject(
        new CapsuleShape(Width / 2, Height),
        new Pose(new Vector3F(0, Height / 2, 0)));

      // Create a collision object for the game object and add it to the collision domain.
      CollisionObject = new CollisionObject(GeometricObject);
      _collisionDomain.CollisionObjects.Add(CollisionObject);
    }