예제 #1
0
        public SmokeSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            // Create a single particle system and add it multiple times to the scene
            // graph ("instancing"). By default, all instances look identical. The
            // properties ParticleSystemNode.Color/Alpha/AngleOffset can be used to
            // render the particles with some variations.
            _particleSystem = Smoke.Create(ContentManager);
            ParticleSystemService.ParticleSystems.Add(_particleSystem);

            _particleSystemNode0 = new ParticleSystemNode(_particleSystem);
            GraphicsScreen.Scene.Children.Add(_particleSystemNode0);

            _particleSystemNode1             = new ParticleSystemNode(_particleSystem);
            _particleSystemNode1.PoseWorld   = new Pose(new Vector3F(5, 0, -5));
            _particleSystemNode1.Color       = new Vector3F(0.9f, 0.8f, 0.7f);
            _particleSystemNode1.Alpha       = 0.8f;
            _particleSystemNode1.AngleOffset = 0.3f;
            GraphicsScreen.Scene.Children.Add(_particleSystemNode1);

            _particleSystemNode2             = new ParticleSystemNode(_particleSystem);
            _particleSystemNode2.PoseWorld   = new Pose(new Vector3F(-10, 5, -5), Matrix33F.CreateRotationZ(-ConstantsF.PiOver2));
            _particleSystemNode2.Color       = new Vector3F(0.5f, 0.5f, 0.5f);
            _particleSystemNode2.AngleOffset = 0.6f;
            GraphicsScreen.Scene.Children.Add(_particleSystemNode2);
        }
예제 #2
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);
        }
예제 #3
0
        public void CreateRotationZ()
        {
            float     angle = (float)MathHelper.ToRadians(30);
            Matrix33F m     = Matrix33F.CreateRotationZ(angle);

            Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F((float)Math.Cos(angle), (float)Math.Sin(angle), 0), m * Vector3F.UnitX));

            QuaternionF q = QuaternionF.CreateRotation(Vector3F.UnitZ, angle);

            Assert.IsTrue(Vector3F.AreNumericallyEqual(q.Rotate(Vector3F.One), m * Vector3F.One));

            Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.CreateRotation(Vector3F.UnitZ, angle), m));
        }
        /// <summary>
        /// Adds test objects (walls, palm trees, ...) to the scene.
        /// </summary>
        private void AddTestObjects()
        {
            // Add a few palm trees.
            Random random = new Random(12345);

            for (int i = 0; i < 10; i++)
            {
                Vector3F  position    = new Vector3F(3.5f, 0, 2.5f - i / 2.0f);
                Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
                float     scale       = random.NextFloat(0.5f, 1.2f);
                Pose      pose        = _globalRotation * new Pose(position, orientation);
                GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, pose));
            }

            // Add a vertical concrete wall.
            GameObjectService.Objects.Add(
                new StaticObject(
                    Services,
                    "Building/concrete_small_window_1",
#if XNA
                    new Vector3F(1.0f, 1.6f, 1.8f),
                    _globalRotation * new Pose(new Vector3F(3.5f, 1.8f, -4f), Matrix33F.CreateRotationY(0)),
#else
                    new Vector3F(1.8f, 1.6f, 1.0f),
                    _globalRotation * new Pose(new Vector3F(3.5f, 1.8f, -4f), Matrix33F.CreateRotationY(ConstantsF.PiOver2)),
#endif
                    true,
                    false));

            // Add a vertical brick wall.
            GameObjectService.Objects.Add(
                new StaticObject(
                    Services,
                    "Building/wall_brick_1",
                    new Vector3F(1.8f, 1.6f, 1),
                    _globalRotation * new Pose(new Vector3F(-3f, 1.8f, -4f), Matrix33F.CreateRotationY(ConstantsF.PiOver2)),
                    true,
                    false));

            // Create a ceiling using a rotated wall.
            GameObjectService.Objects.Add(
                new StaticObject(
                    Services,
                    "Building/wall_brick_1",
                    new Vector3F(1.8f, 2.8f, 1),
                    _globalRotation * new Pose(new Vector3F(0.3f, 4, -4), Matrix33F.CreateRotationZ(ConstantsF.PiOver2) * Matrix33F.CreateRotationY(ConstantsF.PiOver2)),
                    true,
                    false));
        }
예제 #5
0
        private void UpdateEphemeris()
        {
#if XBOX
            _ephemeris.Time = new DateTimeOffset(_time.Ticks, TimeSpan.Zero);
#else
            _ephemeris.Time = _time;
#endif
            _ephemeris.Update();

            var sunDirection  = (Vector3F)_ephemeris.SunDirectionRefracted;
            var sunUp         = sunDirection.Orthonormal1;
            var moonDirection = (Vector3F)_ephemeris.MoonPosition.Normalized;
            var moonUp        = (Vector3F)_ephemeris.EquatorialToWorld.TransformDirection(Vector3D.Up);

#if true
            _starfield.PoseWorld = new Pose((Matrix33F)_ephemeris.EquatorialToWorld.Minor);
            _sun.LookAt((Vector3F)_ephemeris.SunDirectionRefracted, sunUp);
            _moon.SunDirection = (Vector3F)_ephemeris.SunPosition.Normalized;
#else
            Vector3F  sunRotationAxis = new Vector3F(0, -0.1f, 1).Normalized;
            float     hour            = (float)_time.TimeOfDay.TotalHours / 24;
            Matrix33F sunRotation     = Matrix33F.CreateRotation(sunRotationAxis, hour * ConstantsF.TwoPi - ConstantsF.PiOver2);

            _starfield.Orientation = sunRotation;
            _sun.Direction         = sunRotation * new Vector3F(1, 0, 0);
            _moon.SunDirection     = _sun.Direction;
#endif

            _milkyWaySkybox.PoseWorld = new Pose(
                (Matrix33F)_ephemeris.EquatorialToWorld.Minor
                * Matrix33F.CreateRotationZ(ConstantsF.PiOver2)
                * Matrix33F.CreateRotationX(ConstantsF.PiOver2));

            _moon.LookAt(moonDirection, moonUp);
            _cieSkyFilter.SunDirection       = sunDirection;
            _gradientSky.SunDirection        = sunDirection;
            _gradientTextureSky.SunDirection = sunDirection;
            _gradientTextureSky.TimeOfDay    = _time.TimeOfDay;
            _scatteringSky.SunDirection      = sunDirection;

            _cloudLayerNode.SunDirection = _scatteringSky.SunDirection;
            _cloudLayerNode.SunLight     = ChangeSaturation(_scatteringSky.GetSunlight() / 5f, 1);
            //_cloudPlaneRenderer.Color = new Vector4F(ChangeSaturation(_scatteringSky.GetFogColor(128), 0.9f) * 1.0f, 1);
            //Vector3F c = (_scatteringSky.GetFogColor(128) + _scatteringSky.GetSunlight() / 10) / 2;
            //_cloudPlaneRenderer.Color = new Vector4F(c, 1);
            _cloudLayerNode.AmbientLight = _scatteringSky.GetAmbientLight(1024) / 6f;
            //_cloudLayerNode.AmbientLight = _scatteringSky.GetFogColor(128) * _scatteringSky.GetAmbientLight(256).Length / 6f;
        }
예제 #6
0
        private static Pose GetRandomPose()
        {
            // Get a random position.
            const float decalAreaSize  = 20;
            var         randomPosition = new Vector3F(
                RandomHelper.Random.NextFloat(-decalAreaSize, decalAreaSize),
                0,
                RandomHelper.Random.NextFloat(-decalAreaSize, 0));

            // Decals are project along the forward (-z) direction.
            // To project onto the terrain we have to point the decal down.
            var downOrientation = Matrix33F.CreateRotationX(-ConstantsF.PiOver2);

            // Get a random rotation around z.
            var randomOrientation = Matrix33F.CreateRotationZ(RandomHelper.Random.NextFloat(0, ConstantsF.TwoPi));

            return(new Pose(randomPosition, downOrientation * randomOrientation));
        }
예제 #7
0
        /// <summary>
        /// Converts this render transformation to a 3x3 matrix.
        /// </summary>
        /// <returns>
        /// A 3x3-matrix that represents the same transformation.
        /// </returns>
        public Matrix33F ToMatrix33F()
        {
            Matrix33F t = new Matrix33F(1, 0, Translation.X,
                                        0, 1, Translation.Y,
                                        0, 0, 1);
            Matrix33F o = new Matrix33F(1, 0, Origin.X,
                                        0, 1, Origin.Y,
                                        0, 0, 1);
            Matrix33F s = new Matrix33F(Scale.X, 0, 0,
                                        0, Scale.Y, 0,
                                        0, 0, 1);
            Matrix33F r      = Matrix33F.CreateRotationZ(Rotation);
            Matrix33F minusO = new Matrix33F(1, 0, -Origin.X,
                                             0, 1, -Origin.Y,
                                             0, 0, 1);

            return(t * o * r * s * minusO);
        }
예제 #8
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();
        }
예제 #9
0
        public CustomSceneNodeSample(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);

            // Create a new empty scene.
            _scene = new Scene();

            // Add the camera node to the scene.
            _scene.Children.Add(_cameraObject.CameraNode);

            // Add a few TextNodes. Position them along a circle.
            for (int i = 0; i < 36; i++)
            {
                Vector3F position = Matrix33F.CreateRotationZ(MathHelper.ToRadians((float)i * 10)) * new Vector3F(1, 0, 0);
                var      textNode = new TextNode
                {
                    PoseLocal = new Pose(position),
                    Color     = Color.Yellow,
                    Text      = i.ToString()
                };
                _scene.Children.Add(textNode);
            }

            // Initialize the TextRenderer.
            var spriteFont = UIContentManager.Load <SpriteFont>("UI Themes/BlendBlue/Default");

            _textRenderer = new TextRenderer(GraphicsService, spriteFont);

            // For debugging:
            _debugRenderer = new DebugRenderer(GraphicsService, spriteFont);
        }
예제 #10
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);
            }
        }
예제 #11
0
        private void UpdateSky()
        {
            // Update ephemeris model.
#if XBOX
            _ephemeris.Time = new DateTimeOffset(_time.Ticks, TimeSpan.Zero);
#else
            _ephemeris.Time = _time;
#endif
            _ephemeris.Update();

            // Update rotation of milky way. We also need to add an offset because the
            // cube map texture is rotated.
            _milkyWayNode.PoseWorld = new Pose(
                (Matrix33F)_ephemeris.EquatorialToWorld.Minor
                * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + -0.004f)
                * Matrix33F.CreateRotationX(ConstantsF.PiOver2 + -0.002f));

            // Update rotation of stars.
            _starfieldNode.PoseWorld = new Pose((Matrix33F)_ephemeris.EquatorialToWorld.Minor);

            // Update direction of sun.
            SunDirection = (Vector3F)_ephemeris.SunDirectionRefracted;
            var sunUp = SunDirection.Orthonormal1;
            _sunNode.LookAt(SunDirection, sunUp);

            // Update direction of moon.
            var moonDirection = (Vector3F)_ephemeris.MoonPosition.Normalized;
            var moonUp        = (Vector3F)_ephemeris.EquatorialToWorld.TransformDirection(Vector3D.Up);
            _moonNode.LookAt(moonDirection, moonUp);

            // The moon needs to know the sun position and brightness to compute the moon phase.
            _moonNode.SunDirection = (Vector3F)_ephemeris.SunPosition.Normalized;
            _moonNode.SunLight     = Ephemeris.ExtraterrestrialSunlight * SunlightScale;

            // The ScatteringSky needs the sun direction and brightness to compute the sky colors.
            _scatteringSkyNode.SunDirection = SunDirection;
            _scatteringSkyNode.SunColor     = Ephemeris.ExtraterrestrialSunlight * ScatteringSkyLightScale;

            // Update the light directions.
            _sunlightNode.LookAt(-SunDirection, sunUp);
            _moonlightNode.LookAt(-moonDirection, moonUp);

            // The ScatteringSkyNode can compute the actual sunlight.
            SunLight = _scatteringSkyNode.GetSunlight();

            // Undo the ScatteringSkyLightScale and apply a custom scale for the sunlight.
            SunLight = SunLight / ScatteringSkyLightScale * SunlightScale;

            // The ScatteringSkyNode can also compute the ambient light by sampling the
            // sky hemisphere.
            AmbientLight = _scatteringSkyNode.GetAmbientLight(256);
            AmbientLight = AmbientLight / ScatteringSkyLightScale * SunlightScale;

            // Desaturate the ambient light to avoid very blue shadows.
            AmbientLight = InterpolationHelper.Lerp(
                new Vector3F(Vector3F.Dot(AmbientLight, GraphicsHelper.LuminanceWeights)),
                AmbientLight,
                0.5f);

            // The Ephemeris model can compute the actual moonlight.
            Vector3F moonlight, moonAmbient;
            Ephemeris.GetMoonlight(
                _scatteringSkyNode.ObserverAltitude,
                2.2f,
                _ephemeris.MoonPosition,
                (float)_ephemeris.MoonPhaseAngle,
                out moonlight,
                out moonAmbient);
            moonlight   *= MoonlightScale;
            moonAmbient *= MoonlightScale;

            // Scale sun light to 0 at horizon.
            var directionalLightColor = SunLight;
            directionalLightColor *= MathHelper.Clamp(SunDirection.Y / 0.1f, 0, 1);

            var directionalLight = ((DirectionalLight)_sunlightNode.Light);
            directionalLight.Color = directionalLightColor;
            ((DirectionalLight)_moonlightNode.Light).Color = moonlight;
            ((AmbientLight)_ambientLightNode.Light).Color  = AmbientLight + moonAmbient + LightPollution;

            // Use the sunlight color to create a bright sun disk.
            var sunDiskColor = SunLight;
            sunDiskColor.TryNormalize();
            _sunNode.GlowColor0 = sunDiskColor * Ephemeris.ExtraterrestrialSunlight.Length * SunlightScale * 10;

            if (_enableClouds)
            {
                // Update lighting info of cloud layer nodes.
                _cloudLayerNode0.SunDirection = SunDirection;
                _cloudLayerNode0.SunLight     = SunLight;
                _cloudLayerNode0.AmbientLight = AmbientLight;

                // The second cloud layer uses simple unlit clouds (only ambient lighting).
                _cloudLayerNode1.SunDirection = SunDirection;
                _cloudLayerNode1.SunLight     = Vector3F.Zero;
                _cloudLayerNode1.AmbientLight = AmbientLight + SunLight;

                // Use the cloud map as the texture for the directional light to create cloud shadows.
                if (EnableCloudShadows)
                {
                    directionalLight.Texture = _cloudLayerNode0.CloudMap.Texture;
                }
                else
                {
                    directionalLight.Texture = null;
                }

                // Compute a texture offset so that the current sun position and the projected cloud
                // shadows match.
                // Since sky dome is always centered on the camera, position the sunlight node in
                // line with the camera.
                var cameraPosition = _cameraObject.CameraNode.PoseWorld.Position;
                var upVector       = Vector3F.AreNumericallyEqual(SunDirection, Vector3F.UnitZ) ? Vector3F.UnitY : Vector3F.UnitZ;
                _sunlightNode.LookAt(cameraPosition + SunDirection, cameraPosition, upVector);

                // Choose a scale for the cloud shadows.
                directionalLight.TextureScale = new Vector2F(-1000);

                // Get the scaled texture offset for the sun direction.
                directionalLight.TextureOffset = _cloudLayerNode0.GetTextureCoordinates(SunDirection) *
                                                 directionalLight.TextureScale;
            }

            // The ScatteringSkyNode can also estimate a fog color by sampling the horizon colors.
            Vector3F fogColor = _scatteringSkyNode.GetFogColor(256, FogSampleAngle);

            // Desaturate the fog color.
            fogColor = InterpolationHelper.Lerp(
                new Vector3F(Vector3F.Dot(fogColor, GraphicsHelper.LuminanceWeights)),
                fogColor,
                FogSaturation);

            // Find any FogNode in the scene and update its fog color.
            foreach (var fogNode in ((Scene)_scene).GetSubtree().OfType <FogNode>())
            {
                var fog = fogNode.Fog;
                fog.Color0             = fog.Color1 = new Vector4F(fogColor, 1);
                fog.ScatteringSymmetry = FogScatteringSymmetry;
            }

            // TODO: If the fog is dense, reduce the direct light and increase the ambient light.
        }
예제 #12
0
        /// <summary>
        /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.)
        /// </summary>
        /// <param name="skeleton">The skeleton of the Xbox LIVE Avatar.</param>
        /// <param name="simulation">The simulation.</param>
        /// <returns>The avatar ragdoll.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="skeleton"/> or <paramref name="simulation"/> is
        /// <see langword="null"/>.
        /// </exception>
        /// <remarks>
        /// This method is available only in the Xbox 360 build of the
        /// DigitalRune.Physics.Specialized.dll.
        /// </remarks>
        public static Ragdoll CreateAvatarRagdoll(Skeleton skeleton, Simulation simulation)
        {
            if (skeleton == null)
            {
                throw new ArgumentNullException("skeleton");
            }
            if (simulation == null)
            {
                throw new ArgumentNullException("simulation");
            }

            var ragdoll = new Ragdoll();

            // The lists ragdoll.Bodies, ragdoll.BodyOffsets and _motors contain one entry per bone - even if there
            // is no RigidBody for this bone. - This wastes memory but simplifies the code.
            for (int i = 0; i < AvatarRenderer.BoneCount; i++)
            {
                ragdoll.Bodies.Add(null);
                ragdoll.BodyOffsets.Add(Pose.Identity);
                ragdoll.Joints.Add(null);
                ragdoll.Limits.Add(null);
                ragdoll.Motors.Add(null);
            }

            // ----- Create bodies.
            // We use the same mass for all bodies. This is not physically correct but it makes the
            // simulation more stable, for several reasons:
            // - It is better to avoid large mass differences. Therefore, all limbs have the same mass.
            // - Capsule shapes have a low inertia value about their height axis. This causes instability
            //   and it is better to use larger inertia values.
            var massFrame = MassFrame.FromShapeAndMass(new SphereShape(0.2f), Vector3F.One, 4, 0.1f, 1);

            // Use standard material.
            var material = new UniformMaterial();

            // Create rigid bodies for the important bones. The shapes have been manually adapted to
            // produce useful results for thin and overweight avatars.
            // Without offset, the bodies are centered at the joint. ragdoll.BodyOffsets stores an offset pose
            // for each body. Instead, we could use TransformedShape but we can easily handle that
            // ourselves.
            // The collar bones are special, they use dummy shapes and are only used to connect the
            // shoulder bones.
            ragdoll.Bodies[(int)AvatarBone.Root]               = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.Root]          = new Pose(new Vector3F(0, -0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f));
            ragdoll.Bodies[(int)AvatarBone.BackLower]          = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.BackLower]     = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f));
            ragdoll.Bodies[(int)AvatarBone.BackUpper]          = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.BackUpper]     = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.1f));
            ragdoll.Bodies[(int)AvatarBone.Neck]               = new RigidBody(new CapsuleShape(0.04f, 0.09f), massFrame, material);
            ragdoll.Bodies[(int)AvatarBone.Head]               = new RigidBody(new SphereShape(0.15f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.Head]          = new Pose(new Vector3F(0, 0.1f, 0));
            ragdoll.Bodies[(int)AvatarBone.CollarLeft]         = new RigidBody(Shape.Empty, massFrame, material);
            ragdoll.Bodies[(int)AvatarBone.CollarRight]        = new RigidBody(Shape.Empty, massFrame, material);
            ragdoll.Bodies[(int)AvatarBone.ShoulderLeft]       = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ShoulderLeft]  = new Pose(new Vector3F(0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.ShoulderRight]      = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ShoulderRight] = new Pose(new Vector3F(-0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.ElbowLeft]          = new RigidBody(new CapsuleShape(0.04f, 0.21f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ElbowLeft]     = new Pose(new Vector3F(0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.ElbowRight]         = new RigidBody(new CapsuleShape(0.04f, 0.21f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ElbowRight]    = new Pose(new Vector3F(-0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.WristLeft]          = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.WristLeft]     = new Pose(new Vector3F(0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f));
            ragdoll.Bodies[(int)AvatarBone.WristRight]         = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.WristRight]    = new Pose(new Vector3F(-0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f));
            ragdoll.Bodies[(int)AvatarBone.HipLeft]            = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.HipLeft]       = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.HipRight]           = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.HipRight]      = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.KneeLeft]           = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.KneeLeft]      = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.KneeRight]          = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.KneeRight]     = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.AnkleLeft]          = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.AnkleLeft]     = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0));
            ragdoll.Bodies[(int)AvatarBone.AnkleRight]         = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.AnkleRight]    = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0));

            // ----- Add joint constraints.
            const float jointErrorReduction = 0.2f;
            const float jointSoftness       = 0.0001f;

            AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, 0.6f, 0.000001f);
            AddJoint(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, 0.6f, 0.000001f);
            AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, jointErrorReduction, jointSoftness);

            // ----- Add constraint limits.
            // We use TwistSwingLimits to define an allowed twist and swing cone for the joints.
            // Exceptions are the back and knees, where we use AngularLimits to create hinges.
            // (We could also create a hinge with a TwistSwingLimit where the twist axis is the hinge
            // axis and no swing is allowed - but AngularLimits create more stable hinges.)
            // Another exception are the collar bones joint. We use AngularLimits to disallow any
            // rotations.
            AddAngularLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(-0.3f, 0, 0), new Vector3F(0.3f, 0, 0));

            AddAngularLimit(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(-0.3f, 0, 0), new Vector3F(0.4f, 0, 0));

            var rotationZ90Degrees = Matrix33F.CreateRotationZ(ConstantsF.PiOver2);

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.3f, -0.3f), new Vector3F(+0.1f, +0.3f, +0.3f));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.6f, -0.6f), new Vector3F(+0.1f, +0.6f, +0.6f));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft,
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(),
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(),
                               new Vector3F(0), new Vector3F(0));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight,
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(),
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(),
                               new Vector3F(0), new Vector3F(0));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 - 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f));

            AddAngularLimit(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0));

            AddAngularLimit(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f));

            // ----- Add motors
            // We use QuaternionMotors to create forces that rotate the bones into desired poses.
            // This can be used for damping, spring or animating the ragdoll.
            AddMotor(ragdoll, (AvatarBone)(-1), AvatarBone.Root);
            AddMotor(ragdoll, AvatarBone.Root, AvatarBone.BackLower);
            AddMotor(ragdoll, AvatarBone.BackLower, AvatarBone.BackUpper);
            AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.Neck);
            AddMotor(ragdoll, AvatarBone.Neck, AvatarBone.Head);
            AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarLeft);
            AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarRight);
            AddMotor(ragdoll, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft);
            AddMotor(ragdoll, AvatarBone.CollarRight, AvatarBone.ShoulderRight);
            AddMotor(ragdoll, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft);
            AddMotor(ragdoll, AvatarBone.ShoulderRight, AvatarBone.ElbowRight);
            AddMotor(ragdoll, AvatarBone.ElbowLeft, AvatarBone.WristLeft);
            AddMotor(ragdoll, AvatarBone.ElbowRight, AvatarBone.WristRight);
            AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipLeft);
            AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipRight);
            AddMotor(ragdoll, AvatarBone.HipLeft, AvatarBone.KneeLeft);
            AddMotor(ragdoll, AvatarBone.HipRight, AvatarBone.KneeRight);
            AddMotor(ragdoll, AvatarBone.KneeLeft, AvatarBone.AnkleLeft);
            AddMotor(ragdoll, AvatarBone.KneeRight, AvatarBone.AnkleRight);

            // ----- Set collision filters.
            // Collisions between connected bones have been disabled with Constraint.CollisionEnabled
            // = false in the joints. We need to disable a few other collisions.
            // Following bodies do not collide with anything. They are only used to connect other
            // bones.
            ragdoll.Bodies[(int)AvatarBone.Neck].CollisionObject.Enabled        = false;
            ragdoll.Bodies[(int)AvatarBone.CollarLeft].CollisionObject.Enabled  = false;
            ragdoll.Bodies[(int)AvatarBone.CollarRight].CollisionObject.Enabled = false;

            // We disable filters for following body pairs because they are usually penetrating each
            // other, which needs to be ignored.
            var filter = simulation.CollisionDomain.CollisionDetection.CollisionFilter as CollisionFilter;

            if (filter != null)
            {
                filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderLeft].CollisionObject, false);
                filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderRight].CollisionObject, false);
            }

            return(ragdoll);
        }
예제 #13
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>();

            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);
            }
        }
예제 #14
0
        public void Orthogonalize()
        {
            var m = Matrix33F.CreateRotationX(0.1f) * Matrix33F.CreateRotationY(20) * Matrix33F.CreateRotationZ(1000);

            // Introduce error.
            m.M01 += 0.1f;
            m.M22 += 0.1f;

            Assert.IsFalse(m.IsOrthogonal);
            Assert.IsFalse(m.IsRotation);

            m.Orthogonalize();

            Assert.IsTrue(m.IsOrthogonal);
            Assert.IsTrue(m.IsRotation);

            // Orthogonalizing and orthogonal matrix does not change the matrix.
            var n = m;

            n.Orthogonalize();
            Assert.IsTrue(Matrix33F.AreNumericallyEqual(m, n));
        }
예제 #15
0
        // Add a flower shape.
        private void CreateFlower()
        {
            // Define single flower petal.
            var petalPath = new Path2F
            {
                new PathKey2F
                {
                    Parameter     = 0,
                    Interpolation = SplineInterpolation.Bezier,
                    Point         = new Vector2F(0, 0),
                    TangentIn     = new Vector2F(0, 0),
                    TangentOut    = new Vector2F(-0.2f, 0.2f)
                },
                new PathKey2F
                {
                    Parameter     = 1,
                    Interpolation = SplineInterpolation.Bezier,
                    Point         = new Vector2F(0, 1),
                    TangentIn     = new Vector2F(-0.3f, 1.1f),
                    TangentOut    = new Vector2F(0.3f, 1.1f)
                },
                new PathKey2F
                {
                    Parameter     = 2,
                    Interpolation = SplineInterpolation.Bezier,
                    Point         = new Vector2F(0, 0),
                    TangentIn     = new Vector2F(0.2f, 0.2f),
                    TangentOut    = new Vector2F(0, 0)
                }
            };

            var petal = new PathFigure2F();

            petal.Segments.Add(petalPath);

            // Duplicate and rotate flower petal several times.
            const int numberOfPetals = 9;
            var       flower         = new CompositeFigure();

            flower.Children.Add(petal);
            for (int i = 1; i < numberOfPetals; i++)
            {
                var transformedPetal = new TransformedFigure(petal)
                {
                    Pose = new Pose(Matrix33F.CreateRotationZ(i * ConstantsF.TwoPi / numberOfPetals))
                };
                flower.Children.Add(transformedPetal);
            }

            var flowerNode = new FigureNode(flower)
            {
                Name            = "Flower",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(1, 0.2f, 0.2f),
                FillColor       = new Vector3F(1, 0.5f, 0.5f),
                FillAlpha       = 1,
                PoseLocal       = new Pose(new Vector3F(3, 1, 0)),
                ScaleLocal      = new Vector3F(0.5f)
            };

            _scene.Children.Add(flowerNode);
        }
예제 #16
0
        //--------------------------------------------------------------
        #region Creation & Cleanup
        //--------------------------------------------------------------

        /// <summary>
        /// Initializes a new instance of the <see cref="SsaoFilter"/> class.
        /// </summary>
        /// <param name="graphicsService">The graphics service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicsService"/> is <see langword="null"/>.
        /// </exception>
        public SsaoFilter(IGraphicsService graphicsService)
            : base(graphicsService)
        {
            _effect                    = GraphicsService.Content.Load <Effect>("DigitalRune/PostProcessing/SsaoFilter");
            _farParameter              = _effect.Parameters["Far"];
            _radiusParameter           = _effect.Parameters["Radius"];
            _strengthParameter         = _effect.Parameters["Strength"];
            _maxDistancesParameter     = _effect.Parameters["MaxDistances"];
            _viewportSizeParameter     = _effect.Parameters["ViewportSize"];
            _sourceTextureParameter    = _effect.Parameters["SourceTexture"];
            _gBuffer0Parameter         = _effect.Parameters["GBuffer0"];
            _occlusionTextureParameter = _effect.Parameters["OcclusionTexture"];
            _createLinesAPass          = _effect.CurrentTechnique.Passes["CreateLinesA"];
            _createLinesBPass          = _effect.CurrentTechnique.Passes["CreateLinesB"];
            _blurHorizontalPass        = _effect.CurrentTechnique.Passes["BlurHorizontal"];
            _blurVerticalPass          = _effect.CurrentTechnique.Passes["BlurVertical"];
            _combinePass               = _effect.CurrentTechnique.Passes["Combine"];
            _copyPass                  = _effect.CurrentTechnique.Passes["Copy"];

            Radii              = new Vector2F(0.01f, 0.02f);
            MaxDistances       = new Vector2F(0.5f, 1.0f);
            Strength           = 1f;
            NumberOfBlurPasses = 1;
            DownsampleFactor   = 2;
            Quality            = 2;
            Scale              = new Vector2F(0.5f, 2f);
            CombineWithSource  = true;

            _blur = new Blur(graphicsService);
            _blur.InitializeGaussianBlur(7, 7 / 3, true);

            _copyFilter       = PostProcessHelper.GetCopyFilter(graphicsService);
            _downsampleFilter = PostProcessHelper.GetDownsampleFilter(graphicsService);

            Random random = new Random(123456);

            Vector3[] vectors = new Vector3[9];

            // 16 random vectors for Crytek-style point samples.
            //for (int i = 0; i < vectors.Length; i++)
            //  vectors[i] = (Vector3)random.NextQuaternionF().Rotate(Vector3F.One).Normalized;
            //    //* random.NextFloat(0.5f, 1) // Note: StarCraft 2 uses varying length to vary the sample offset length.

            // We create rotated random vectors with uniform distribution in 360°. Each random vector
            // is further rotated with small random angle.
            float jitterAngle = ConstantsF.TwoPi / vectors.Length / 4;

            for (int i = 0; i < vectors.Length; i++)
            {
                vectors[i] = (Vector3)(Matrix33F.CreateRotationZ(ConstantsF.TwoPi * i / vectors.Length + random.NextFloat(-jitterAngle, jitterAngle)) * new Vector3F(1, 0, 0)).Normalized;
            }

            // Permute randomVectors.
            for (int i = 0; i < vectors.Length; i++)
            {
                MathHelper.Swap(ref vectors[i], ref vectors[random.Next(i, vectors.Length - 1)]);
            }

            // Scale random vectors.
            for (int i = 0; i < vectors.Length; i++)
            {
                vectors[i].Z = random.NextFloat(Scale.X, Scale.Y);
            }

            _effect.Parameters["RandomVectors"].SetValue(vectors);
        }
예제 #17
0
        // Add a 3D coordinate cross.
        private void CreateGizmo(SpriteFont spriteFont)
        {
            var gizmoNode = new SceneNode
            {
                Name       = "Gizmo",
                Children   = new SceneNodeCollection(),
                PoseLocal  = new Pose(new Vector3F(3, 2, 0)),
                ScaleLocal = new Vector3F(0.5f)
            };

            // Red arrow
            var arrow = new PathFigure2F();

            arrow.Segments.Add(new LineSegment2F {
                Point1 = new Vector2F(0, 0), Point2 = new Vector2F(1, 0)
            });
            arrow.Segments.Add(new LineSegment2F {
                Point1 = new Vector2F(1, 0), Point2 = new Vector2F(0.9f, 0.02f)
            });
            arrow.Segments.Add(new LineSegment2F {
                Point1 = new Vector2F(1, 0), Point2 = new Vector2F(0.9f, -0.02f)
            });
            var figureNode = new FigureNode(arrow)
            {
                Name            = "Gizmo X",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(1, 0, 0),
                PoseLocal       = new Pose(new Vector3F(0, 0, 0))
            };

            gizmoNode.Children.Add(figureNode);

            // Green arrow
            var transformedArrow = new TransformedFigure(arrow)
            {
                Pose = new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(90)))
            };

            figureNode = new FigureNode(transformedArrow)
            {
                Name            = "Gizmo Y",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(0, 1, 0),
                PoseLocal       = new Pose(new Vector3F(0, 0, 0))
            };
            gizmoNode.Children.Add(figureNode);

            // Blue arrow
            transformedArrow = new TransformedFigure(arrow)
            {
                Pose = new Pose(Matrix33F.CreateRotationY(MathHelper.ToRadians(-90)))
            };
            figureNode = new FigureNode(transformedArrow)
            {
                Name            = "Gizmo Z",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(0, 0, 1),
                PoseLocal       = new Pose(new Vector3F(0, 0, 0))
            };
            gizmoNode.Children.Add(figureNode);

            // Red arc
            var arc = new PathFigure2F();

            arc.Segments.Add(
                new StrokedSegment2F(
                    new LineSegment2F {
                Point1 = new Vector2F(0, 0), Point2 = new Vector2F(1, 0),
            },
                    false));
            arc.Segments.Add(
                new ArcSegment2F
            {
                Point1 = new Vector2F(1, 0),
                Point2 = new Vector2F(0, 1),
                Radius = new Vector2F(1, 1)
            });
            arc.Segments.Add(
                new StrokedSegment2F(
                    new LineSegment2F {
                Point1 = new Vector2F(0, 1), Point2 = new Vector2F(0, 0),
            },
                    false));
            var transformedArc = new TransformedFigure(arc)
            {
                Scale = new Vector3F(0.333f),
                Pose  = new Pose(Matrix33F.CreateRotationY(MathHelper.ToRadians(-90)))
            };

            figureNode = new FigureNode(transformedArc)
            {
                Name            = "Gizmo YZ",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(1, 0, 0),
                FillColor       = new Vector3F(1, 0, 0),
                FillAlpha       = 0.5f,
                PoseLocal       = new Pose(new Vector3F(0, 0, 0))
            };
            gizmoNode.Children.Add(figureNode);

            // Green arc
            transformedArc = new TransformedFigure(arc)
            {
                Scale = new Vector3F(0.333f),
                Pose  = new Pose(Matrix33F.CreateRotationX(MathHelper.ToRadians(90)))
            };
            figureNode = new FigureNode(transformedArc)
            {
                Name            = "Gizmo XZ",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(0, 1, 0),
                FillColor       = new Vector3F(0, 1, 0),
                FillAlpha       = 0.5f,
                PoseLocal       = new Pose(new Vector3F(0, 0, 0))
            };
            gizmoNode.Children.Add(figureNode);

            // Blue arc
            transformedArc = new TransformedFigure(arc)
            {
                Scale = new Vector3F(0.333f),
            };
            figureNode = new FigureNode(transformedArc)
            {
                Name            = "Gizmo XY",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(0, 0, 1),
                FillColor       = new Vector3F(0, 0, 1),
                FillAlpha       = 0.5f,
                PoseLocal       = new Pose(new Vector3F(0, 0, 0))
            };
            gizmoNode.Children.Add(figureNode);

            // Labels "X", "Y", "Z"
            var spriteNode = new SpriteNode(new TextSprite("X", spriteFont))
            {
                Color     = new Vector3F(1, 0, 0),
                Origin    = new Vector2F(0, 1),
                PoseLocal = new Pose(new Vector3F(1, 0, 0))
            };

            gizmoNode.Children.Add(spriteNode);
            spriteNode = new SpriteNode(new TextSprite("Y", spriteFont))
            {
                Color     = new Vector3F(0, 1, 0),
                Origin    = new Vector2F(0, 1),
                PoseLocal = new Pose(new Vector3F(0, 1, 0))
            };
            gizmoNode.Children.Add(spriteNode);
            spriteNode = new SpriteNode(new TextSprite("Z", spriteFont))
            {
                Color     = new Vector3F(0, 0, 1),
                Origin    = new Vector2F(0, 1),
                PoseLocal = new Pose(new Vector3F(0, 0, 1))
            };
            gizmoNode.Children.Add(spriteNode);

            _scene.Children.Add(gizmoNode);
        }
예제 #18
0
        public BillboardSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            _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);

            // In this example we need three renderers:
            // The MeshRenderer handles MeshNodes.
            _meshRenderer = new MeshRenderer();

            // The BillboardRenderer handles BillboardNodes and ParticleSystemNodes.
            _billboardRenderer = new BillboardRenderer(GraphicsService, 2048);

            // The DebugRenderer is used to draw text.
            var spriteFont = UIContentManager.Load <SpriteFont>("Default");

            _debugRenderer = new DebugRenderer(GraphicsService, spriteFont);

            // Create a new empty scene.
            _scene = new Scene();

            // Add the camera node to the scene.
            _scene.Children.Add(_cameraObject.CameraNode);

            // Add a few models to the scene.
            var sandbox = ContentManager.Load <ModelNode>("Sandbox/Sandbox").Clone();

            _scene.Children.Add(sandbox);

            // Add some lights to the scene which have the same properties as the lights
            // of BasicEffect.EnableDefaultLighting().
            SceneSample.InitializeDefaultXnaLights(_scene);

            var texture = new PackedTexture(ContentManager.Load <Texture2D>("Billboard/BillboardReference"));

            // ----- View plane-aligned billboards with variations.
            // View plane-aligned billboards are rendered parallel to the screen.
            // The up-axis of the BillboardNode determines the up direction of the
            // billboard.
            var pose0         = new Pose(new Vector3F(-9, 1.0f, 1.5f));
            var pose1         = pose0;
            var billboard     = new ImageBillboard(texture);
            var billboardNode = new BillboardNode(billboard);

            billboardNode.Name      = "View plane-aligned\nVarying color\nVarying alpha";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            billboardNode.Color     = new Vector3F(1, 0, 0);
            billboardNode.Alpha     = 0.9f;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            billboardNode.Color     = new Vector3F(0, 1, 0);
            billboardNode.Alpha     = 0.7f;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            billboardNode.Color     = new Vector3F(0, 0, 1);
            billboardNode.Alpha     = 0.3f;
            _scene.Children.Add(billboardNode);

            // ----- View plane-aligned billboards with different blend modes
            // blend mode = 0 ... additive blend
            // blend mode = 1 ... alpha blend
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 0.0f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "View plane-aligned\nVarying blend mode";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 0.333f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 0.667f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.BlendMode     = 1.0f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- View plane-aligned billboards with alpha test
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.9f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "View plane-aligned\nVarying reference alpha";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.667f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.333f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboard               = new ImageBillboard(texture);
            billboard.AlphaTest     = 0.0f;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- View plane-aligned billboards with different scale and rotation
            pose0.Position.X        += 2;
            pose1                    = pose0;
            billboard                = new ImageBillboard(texture);
            billboard.Orientation    = BillboardOrientation.ViewPlaneAligned;
            billboardNode            = new BillboardNode(billboard);
            billboardNode.Name       = "View plane-aligned\nVarying scale\nVarying rotation";
            billboardNode.PoseWorld  = pose1;
            billboardNode.ScaleLocal = new Vector3F(0.4f);
            _scene.Children.Add(billboardNode);

            pose1.Position.Z        -= 1;
            billboardNode            = billboardNode.Clone();
            billboardNode.Name       = null;
            billboardNode.PoseWorld  = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-15)));
            billboardNode.ScaleLocal = new Vector3F(0.6f);
            _scene.Children.Add(billboardNode);

            pose1.Position.Z        -= 1;
            billboardNode            = billboardNode.Clone();
            billboardNode.Name       = null;
            billboardNode.PoseWorld  = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-30)));
            billboardNode.ScaleLocal = new Vector3F(0.8f);
            _scene.Children.Add(billboardNode);

            pose1.Position.Z        -= 1;
            billboardNode            = billboardNode.Clone();
            billboardNode.Name       = null;
            billboardNode.PoseWorld  = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-45)));
            billboardNode.ScaleLocal = new Vector3F(1.0f);
            _scene.Children.Add(billboardNode);

            // ----- Viewpoint-oriented billboards
            // Viewpoint-orientated billboards always face the player. (The face normal
            // points directly to the camera.)
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.ViewpointOriented;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Viewpoint-oriented";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- Screen-aligned billboards
            // View plane-aligned billboards and screen-aligned billboards are similar. The
            // billboards are rendered parallel to the screen. The orientation can be changed
            // by rotating the BillboardNode. The difference is that the orientation of view
            // plane-aligned billboards is relative to world space and the orientation of
            // screen-aligned billboards is relative to view space.
            // Screen-aligned billboards are, for example, used for text label.
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.ScreenAligned;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Screen-aligned";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- Axial, view plane-aligned billboards
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.AxialViewPlaneAligned;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Axial, view plane-aligned";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = billboardNode.Clone();
            billboardNode.Name      = null;
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- Axial, viewpoint-oriented billboards
            pose0.Position.X       += 2;
            pose1                   = pose0;
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.AxialViewpointOriented;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "Axial, viewpoint-oriented";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // ----- World-oriented billboards
            // World-oriented billboards have a fixed orientation in world space. The
            // orientation is determine by the BillboardNode.
            pose0.Position.X       += 2;
            pose1                   = pose0;
            pose1.Orientation      *= Matrix33F.CreateRotationY(0.2f);
            billboard               = new ImageBillboard(texture);
            billboard.Orientation   = BillboardOrientation.WorldOriented;
            billboardNode           = new BillboardNode(billboard);
            billboardNode.Name      = "World-oriented";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            pose1.Orientation      *= Matrix33F.CreateRotationY(0.2f);
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(15)));
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            pose1.Orientation      *= Matrix33F.CreateRotationY(0.2f);
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(30)));
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            pose1.Orientation      *= Matrix33F.CreateRotationY(0.2f);
            billboardNode           = new BillboardNode(billboard);
            billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(45)));
            _scene.Children.Add(billboardNode);

            // ----- Animated billboards
            // DigitalRune Graphics supports "texture atlases". I.e. textures can be packed
            // together into a single, larger texture file. A PackedTexture can describe a
            // single texture packed into a texture atlas or a tile set packed into a
            // texture atlas. In this example the "beeWingFlap" is a set of three tiles.
            // Tile sets can be used for sprite animations. (The animation is set below in
            // Update().)
            pose0.Position.X       += 2;
            pose1                   = pose0;
            texture                 = new PackedTexture("Bee", ContentManager.Load <Texture2D>("Particles/beeWingFlap"), Vector2F.Zero, Vector2F.One, 3, 1);
            _animatedBillboard      = new ImageBillboard(texture);
            billboardNode           = new BillboardNode(_animatedBillboard);
            billboardNode.Name      = "Animated billboards";
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(_animatedBillboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            pose1.Position.Z       -= 1;
            billboardNode           = new BillboardNode(_animatedBillboard);
            billboardNode.PoseWorld = pose1;
            _scene.Children.Add(billboardNode);

            // Use DebugRenderer to draw node names above billboard nodes.
            foreach (var node in _scene.GetDescendants().OfType <BillboardNode>())
            {
                _debugRenderer.DrawText(node.Name, node.PoseWorld.Position + new Vector3F(0, 1, 0), new Vector2F(0.5f), Color.Yellow, false);
            }
        }
예제 #19
0
        public void AddRagdoll(float scale, Vector3F ragdollPosition)
        {
            // Ragdolls are usually used in games to create realistic death animations of
            // characters. The character is usually rendered using a skinned triangle mesh.
            // But in the physics simulation the body parts of the character are represented
            // using simple shapes, such as spheres, capsules, boxes, or convex polyhedra,
            // which are connected with joints.
            // The physics simulations computes how these parts collide and fall. The positions
            // and orientations are then read back each frame to update the animation of the
            // triangle mesh.

            // In this example the ragdoll is built from spheres, capsules and boxes. The
            // rigid bodies are created in code. In practice, ragdolls should be built using
            // external tools, such as a 3D modeller or a game editor.

            #region ----- Create rigid bodies for the most relevant body parts -----

            BoxShape  pelvisShape = new BoxShape(0.3f * scale, 0.22f * scale, 0.20f * scale);
            MassFrame pelvisMass  = MassFrame.FromShapeAndDensity(pelvisShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody pelvis      = new RigidBody(pelvisShape, pelvisMass, null)
            {
                Pose = new Pose(new Vector3F(0f, 0.01f * scale, -0.03f * scale) + ragdollPosition),
            };
            Simulation.RigidBodies.Add(pelvis);

            BoxShape  torsoShape = new BoxShape(0.35f * scale, 0.22f * scale, 0.44f * scale);
            MassFrame torsoMass  = MassFrame.FromShapeAndDensity(torsoShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody torso      = new RigidBody(torsoShape, torsoMass, null)
            {
                Pose = new Pose(new Vector3F(0f, 0.01f * scale, -0.4f * scale) + ragdollPosition),
            };
            Simulation.RigidBodies.Add(torso);

            SphereShape headShape = new SphereShape(0.13f * scale);
            MassFrame   headMass  = MassFrame.FromShapeAndDensity(headShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody   head      = new RigidBody(headShape, headMass, null)
            {
                Pose = new Pose(new Vector3F(0f * scale, 0f, -0.776f * scale) + ragdollPosition),
            };
            Simulation.RigidBodies.Add(head);

            CapsuleShape upperArmShape = new CapsuleShape(0.08f * scale, 0.3f * scale);
            MassFrame    upperArmMass  = MassFrame.FromShapeAndDensity(upperArmShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody    leftUpperArm  = new RigidBody(upperArmShape, upperArmMass, null)
            {
                Pose = new Pose(new Vector3F(-0.32f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(leftUpperArm);
            RigidBody rightUpperArm = new RigidBody(upperArmShape, upperArmMass, null)
            {
                Pose = new Pose(new Vector3F(0.32f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(rightUpperArm);

            CapsuleShape lowerArmShape = new CapsuleShape(0.08f * scale, 0.4f * scale);
            MassFrame    lowerArmMass  = MassFrame.FromShapeAndDensity(lowerArmShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody    leftLowerArm  = new RigidBody(lowerArmShape, lowerArmMass, null)
            {
                Pose = new Pose(new Vector3F(-0.62f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(leftLowerArm);
            RigidBody rightLowerArm = new RigidBody(lowerArmShape, lowerArmMass, null)
            {
                Pose = new Pose(new Vector3F(0.62f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(rightLowerArm);

            CapsuleShape upperLegShape = new CapsuleShape(0.09f * scale, 0.5f * scale);
            MassFrame    upperLegMass  = MassFrame.FromShapeAndDensity(upperLegShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody    leftUpperLeg  = new RigidBody(upperLegShape, upperLegMass, null)
            {
                Pose = new Pose(new Vector3F(-0.10f * scale, 0.01f * scale, 0.233f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(leftUpperLeg);

            RigidBody rightUpperLeg = new RigidBody(upperLegShape, upperLegMass, null)
            {
                Pose = new Pose(new Vector3F(0.10f * scale, 0.01f * scale, 0.233f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(rightUpperLeg);

            CapsuleShape lowerLegShape = new CapsuleShape(0.08f * scale, 0.4f * scale);
            MassFrame    lowerLegMass  = MassFrame.FromShapeAndDensity(pelvisShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody    leftLowerLeg  = new RigidBody(lowerLegShape, lowerLegMass, null)
            {
                Pose = new Pose(new Vector3F(-0.11f * scale, 0.01f * scale, 0.7f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(leftLowerLeg);
            RigidBody rightLowerLeg = new RigidBody(lowerLegShape, lowerLegMass, null)
            {
                Pose = new Pose(new Vector3F(0.11f * scale, 0.01f * scale, 0.7f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)),
            };
            Simulation.RigidBodies.Add(rightLowerLeg);

            BoxShape  footShape = new BoxShape(0.12f * scale, 0.28f * scale, 0.07f * scale);
            MassFrame footMass  = MassFrame.FromShapeAndDensity(footShape, Vector3F.One, Density, 0.01f, 3);
            RigidBody leftFoot  = new RigidBody(footShape, footMass, null)
            {
                Pose = new Pose(new Vector3F(-0.11f * scale, -0.06f * scale, 0.94f * scale) + ragdollPosition),
            };
            Simulation.RigidBodies.Add(leftFoot);
            RigidBody rightFoot = new RigidBody(footShape, footMass, null)
            {
                Pose = new Pose(new Vector3F(0.11f * scale, -0.06f * scale, 0.94f * scale) + ragdollPosition),
            };
            Simulation.RigidBodies.Add(rightFoot);
            #endregion

            #region ----- Add joints between body parts -----

            Vector3F   pelvisJointPosition = new Vector3F(0f, 0.026f * scale, -0.115f * scale) + ragdollPosition;
            HingeJoint pelvisJoint         = new HingeJoint
            {
                BodyA            = torso,
                BodyB            = pelvis,
                AnchorPoseALocal = new Pose(torso.Pose.ToLocalPosition(pelvisJointPosition)),
                AnchorPoseBLocal = new Pose(pelvis.Pose.ToLocalPosition(pelvisJointPosition)),
                Minimum          = -0.5f,
                Maximum          = 1.1f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(pelvisJoint);

            Vector3F   neckJointPosition = new Vector3F(0f, 0.026f * scale, -0.690f * scale) + ragdollPosition;
            HingeJoint neckJoint         = new HingeJoint
            {
                BodyA            = head,
                BodyB            = torso,
                AnchorPoseALocal = new Pose(head.Pose.ToLocalPosition(neckJointPosition)),
                AnchorPoseBLocal = new Pose(torso.Pose.ToLocalPosition(neckJointPosition)),
                Minimum          = -1f,
                Maximum          = 1f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(neckJoint);

            Vector3F  leftShoulderJointPosition    = new Vector3F(-0.193f * scale, 0.056f * scale, -0.528f * scale) + ragdollPosition;
            Vector3F  leftShoulderJointAxis        = new Vector3F(0, -1, -1).Normalized;
            Matrix33F leftShoulderJointOrientation = new Matrix33F();
            leftShoulderJointOrientation.SetColumn(0, leftShoulderJointAxis);
            leftShoulderJointOrientation.SetColumn(1, leftShoulderJointAxis.Orthonormal1);
            leftShoulderJointOrientation.SetColumn(2, leftShoulderJointAxis.Orthonormal2);
            BallJoint leftShoulderJoint = new BallJoint
            {
                BodyA = leftUpperArm,
                BodyB = torso,
                AnchorPositionALocal = leftUpperArm.Pose.ToLocalPosition(leftShoulderJointPosition),
                AnchorPositionBLocal = torso.Pose.ToLocalPosition(leftShoulderJointPosition),
                CollisionEnabled     = false,
                ErrorReduction       = JointErrorReduction,
                Softness             = JointSoftness,
                MaxForce             = JointMaxForce,
            };
            Simulation.Constraints.Add(leftShoulderJoint);

            Vector3F  rightShoulderJointPosition    = new Vector3F(0.193f * scale, 0.056f * scale, -0.528f * scale) + ragdollPosition;
            Vector3F  rightShoulderJointAxis        = new Vector3F(0, 1, 1).Normalized;
            Matrix33F rightShoulderJointOrientation = new Matrix33F();
            rightShoulderJointOrientation.SetColumn(0, rightShoulderJointAxis);
            rightShoulderJointOrientation.SetColumn(1, rightShoulderJointAxis.Orthonormal1);
            rightShoulderJointOrientation.SetColumn(2, rightShoulderJointAxis.Orthonormal2);
            BallJoint rightShoulderJoint = new BallJoint
            {
                BodyA = rightUpperArm,
                BodyB = torso,
                AnchorPositionALocal = rightUpperArm.Pose.ToLocalPosition(rightShoulderJointPosition),
                AnchorPositionBLocal = torso.Pose.ToLocalPosition(rightShoulderJointPosition),
                CollisionEnabled     = false,
                ErrorReduction       = JointErrorReduction,
                Softness             = JointSoftness,
                MaxForce             = JointMaxForce,
            };
            Simulation.Constraints.Add(rightShoulderJoint);

            Vector3F  leftElbowJointPosition = new Vector3F(-0.451f * scale, 0.071f * scale, -0.538f * scale) + ragdollPosition;
            Matrix33F elbowAxisOrientation   = new Matrix33F(0, 0, -1,
                                                             0, 1, 0,
                                                             1, 0, 0);
            HingeJoint leftElbowJoint = new HingeJoint
            {
                BodyA            = leftLowerArm,
                BodyB            = leftUpperArm,
                AnchorPoseALocal = new Pose(leftLowerArm.Pose.ToLocalPosition(leftElbowJointPosition), leftLowerArm.Pose.Orientation.Inverse * elbowAxisOrientation),
                AnchorPoseBLocal = new Pose(leftUpperArm.Pose.ToLocalPosition(leftElbowJointPosition), leftUpperArm.Pose.Orientation.Inverse * elbowAxisOrientation),
                Minimum          = -2,
                Maximum          = 0,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(leftElbowJoint);

            Vector3F   rightElbowJointPosition = new Vector3F(0.451f * scale, 0.071f * scale, -0.538f * scale) + ragdollPosition;
            HingeJoint rightElbowJoint         = new HingeJoint
            {
                BodyA            = rightLowerArm,
                BodyB            = rightUpperArm,
                AnchorPoseALocal = new Pose(rightLowerArm.Pose.ToLocalPosition(rightElbowJointPosition), rightLowerArm.Pose.Orientation.Inverse * elbowAxisOrientation),
                AnchorPoseBLocal = new Pose(rightUpperArm.Pose.ToLocalPosition(rightElbowJointPosition), rightUpperArm.Pose.Orientation.Inverse * elbowAxisOrientation),
                Minimum          = 0,
                Maximum          = 2,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(rightElbowJoint);

            Vector3F   leftHipJointPosition = new Vector3F(-0.107f * scale, 0.049f * scale, 0.026f * scale) + ragdollPosition;
            HingeJoint leftHipJoint         = new HingeJoint
            {
                BodyA            = pelvis,
                BodyB            = leftUpperLeg,
                AnchorPoseALocal = new Pose(pelvis.Pose.ToLocalPosition(leftHipJointPosition)),
                AnchorPoseBLocal = new Pose(leftUpperLeg.Pose.ToLocalPosition(leftHipJointPosition), leftUpperLeg.Pose.Orientation.Inverse),
                Minimum          = -0.1f,
                Maximum          = 1.2f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(leftHipJoint);

            Vector3F   rightHipJointPosition = new Vector3F(0.107f * scale, 0.049f * scale, 0.026f * scale) + ragdollPosition;
            HingeJoint rightHipJoint         = new HingeJoint
            {
                BodyA            = pelvis,
                BodyB            = rightUpperLeg,
                AnchorPoseALocal = new Pose(pelvis.Pose.ToLocalPosition(rightHipJointPosition)),
                AnchorPoseBLocal = new Pose(rightUpperLeg.Pose.ToLocalPosition(rightHipJointPosition), rightUpperLeg.Pose.Orientation.Inverse),
                Minimum          = -0.1f,
                Maximum          = 1.2f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(rightHipJoint);

            Vector3F   leftKneeJointPosition = new Vector3F(-0.118f * scale, -0.012f * scale, 0.439f * scale) + ragdollPosition;
            HingeJoint leftKneeJoint         = new HingeJoint
            {
                BodyA            = leftLowerLeg,
                BodyB            = leftUpperLeg,
                AnchorPoseALocal = new Pose(leftLowerLeg.Pose.ToLocalPosition(leftKneeJointPosition)),
                AnchorPoseBLocal = new Pose(leftUpperLeg.Pose.ToLocalPosition(leftKneeJointPosition)),
                Minimum          = 0,
                Maximum          = 1.7f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(leftKneeJoint);

            Vector3F   rightKneeJointPosition = new Vector3F(0.118f * scale, -0.012f * scale, 0.439f * scale) + ragdollPosition;
            HingeJoint rightKneeJoint         = new HingeJoint
            {
                BodyA            = rightLowerLeg,
                BodyB            = rightUpperLeg,
                AnchorPoseALocal = new Pose(rightLowerLeg.Pose.ToLocalPosition(rightKneeJointPosition)),
                AnchorPoseBLocal = new Pose(rightUpperLeg.Pose.ToLocalPosition(rightKneeJointPosition)),
                Minimum          = 0,
                Maximum          = 1.7f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(rightKneeJoint);

            Vector3F   leftAnkleJointPosition = new Vector3F(-0.118f * scale, -0.016f * scale, 0.861f * scale) + ragdollPosition;
            HingeJoint leftAnkleJoint         = new HingeJoint
            {
                BodyA            = leftFoot,
                BodyB            = leftLowerLeg,
                AnchorPoseALocal = new Pose(leftFoot.Pose.ToLocalPosition(leftAnkleJointPosition)),
                AnchorPoseBLocal = new Pose(leftLowerLeg.Pose.ToLocalPosition(leftAnkleJointPosition), leftLowerLeg.Pose.Orientation.Inverse),
                Minimum          = -0.4f,
                Maximum          = 0.9f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(leftAnkleJoint);

            Vector3F   rightAnkleJointPosition = new Vector3F(0.118f * scale, -0.016f * scale, 0.861f * scale) + ragdollPosition;
            HingeJoint rightAnkleJoint         = new HingeJoint
            {
                BodyA            = rightFoot,
                BodyB            = rightLowerLeg,
                AnchorPoseALocal = new Pose(rightFoot.Pose.ToLocalPosition(rightAnkleJointPosition)),
                AnchorPoseBLocal = new Pose(rightLowerLeg.Pose.ToLocalPosition(rightAnkleJointPosition), rightLowerLeg.Pose.Orientation.Inverse),
                Minimum          = -0.4f,
                Maximum          = 0.9f,
                CollisionEnabled = false,
                ErrorReduction   = JointErrorReduction,
                Softness         = JointSoftness,
                MaxForce         = JointMaxForce,
            };
            Simulation.Constraints.Add(rightAnkleJoint);
            #endregion

            #region ----- Add damping to improve stability -----

            if (DampingEnabled)
            {
                // Damping removes jiggling and improves stability.
                AddDamping(pelvis, torso);
                AddDamping(torso, head);
                AddDamping(torso, leftUpperArm);
                AddDamping(leftUpperArm, leftLowerArm);
                AddDamping(torso, rightUpperArm);
                AddDamping(rightUpperArm, rightLowerArm);
                AddDamping(pelvis, leftUpperLeg);
                AddDamping(pelvis, rightUpperLeg);
                AddDamping(leftUpperLeg, leftLowerLeg);
                AddDamping(rightUpperLeg, rightLowerLeg);
                AddDamping(leftLowerLeg, leftFoot);
                AddDamping(rightLowerLeg, rightFoot);
            }
            #endregion
        }
예제 #20
0
        public BridgeSample(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);

            // We add another damping effect that acts only on the suspension bridge parts.
            // This damping uses higher damping factors than the standard damping. It makes the
            // bridge movement smoother and more stable.
            // We use a ListAreaOfEffect. So the additional damping acts only on bodies in this list.
            ListAreaOfEffect boardList = new ListAreaOfEffect(new List <RigidBody>());
            Damping          damping   = new Damping
            {
                AreaOfEffect   = boardList,
                AngularDamping = 1f,
                LinearDamping  = 0.5f
            };

            Simulation.ForceEffects.Add(damping);

            const int numberOfBoards = 20;
            BoxShape  boardShape     = new BoxShape(0.8f, 0.1f, 1.5f);
            RigidBody lastBoard      = null;

            for (int i = 0; i < numberOfBoards; i++)
            {
                // A single plank of the bridge.
                RigidBody body = new RigidBody(boardShape)
                {
                    Pose = new Pose(new Vector3F(-10 + boardShape.WidthX * i, 4, 0))
                };
                Simulation.RigidBodies.Add(body);

                // Add the body to the list of the additional damping force effect.
                boardList.RigidBodies.Add(body);

                if (lastBoard != null)
                {
                    // Connect the last body with current body using a hinge.
                    HingeJoint hinge = new HingeJoint
                    {
                        BodyA = lastBoard,
                        // The attachment point is at the right side of the board.
                        // --> To define the constraint anchor orientation:
                        // The columns are the axes. We set the local z axis in the first column. This is
                        // the hinge axis. In the other two columns we set two orthonormal vectors.
                        // (All three columns are orthonormal and form a valid rotation matrix.)
                        AnchorPoseALocal = new Pose(new Vector3F(boardShape.WidthX / 2, 0, 0),
                                                    new Matrix33F(0, 0, -1,
                                                                  0, 1, 0,
                                                                  1, 0, 0)),
                        BodyB = body,
                        // The attachment point is at the left side of the board.
                        // The anchor orientation is defined as above.
                        AnchorPoseBLocal = new Pose(new Vector3F(-boardShape.WidthX / 2, 0, 0),
                                                    new Matrix33F(0, 0, -1,
                                                                  0, 1, 0,
                                                                  1, 0, 0)),
                        CollisionEnabled = false,
                        // ErrorReduction and Softness are tweaked to get a stable and smooth bridge
                        // movement.
                        ErrorReduction = 0.3f,
                        Softness       = 0.00005f,
                    };
                    Simulation.Constraints.Add(hinge);
                }
                else if (i == 0)
                {
                    // To attach the bridge somewhere, connect the the first board to a fixed position in the
                    // world.
                    HingeJoint hinge = new HingeJoint
                    {
                        BodyA            = Simulation.World,
                        AnchorPoseALocal = new Pose(new Vector3F(-9, 3, 0),
                                                    new Matrix33F(0, 0, -1,
                                                                  0, 1, 0,
                                                                  1, 0, 0)),
                        BodyB            = body,
                        AnchorPoseBLocal = new Pose(new Vector3F(-boardShape.WidthX / 2, 0, 0),
                                                    new Matrix33F(0, 0, -1,
                                                                  0, 1, 0,
                                                                  1, 0, 0)),
                    };
                    Simulation.Constraints.Add(hinge);
                }

                if (i == numberOfBoards - 1)
                {
                    // To attach the bridge somewhere, connect the the last board to a fixed position in the
                    // world.
                    HingeJoint hinge = new HingeJoint
                    {
                        BodyA            = Simulation.World,
                        AnchorPoseALocal = new Pose(new Vector3F(9, 3, 0),
                                                    new Matrix33F(0, 0, -1,
                                                                  0, 1, 0,
                                                                  1, 0, 0)),
                        BodyB            = body,
                        AnchorPoseBLocal = new Pose(new Vector3F(boardShape.WidthX / 2, 0, 0),
                                                    new Matrix33F(0, 0, -1,
                                                                  0, 1, 0,
                                                                  1, 0, 0)),
                    };
                    Simulation.Constraints.Add(hinge);
                }

                lastBoard = body;
            }

            // The bridge is ready.
            // Now, add some ramps so that the character controller can walk up to the bridge.
            BoxShape  rampShape = new BoxShape(10, 10, 2);
            RigidBody ramp0     = new RigidBody(rampShape)
            {
                Pose       = new Pose(new Vector3F(-12.5f, -3f, 0), Matrix33F.CreateRotationZ(0.3f)),
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(ramp0);
            RigidBody ramp1 = new RigidBody(rampShape)
            {
                Pose       = new Pose(new Vector3F(12.5f, -3f, 0), Matrix33F.CreateRotationZ(-0.3f)),
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(ramp1);

            // Drop a few light boxes onto the bridge.
            BoxShape  boxShape = new BoxShape(1, 1, 1);
            MassFrame boxMass  = MassFrame.FromShapeAndDensity(boxShape, Vector3F.One, 100, 0.01f, 3);

            for (int i = 0; i < 10; i++)
            {
                Vector3F    randomPosition    = new Vector3F(RandomHelper.Random.NextFloat(-10, 10), 5, 0);
                QuaternionF randomOrientation = RandomHelper.Random.NextQuaternionF();
                RigidBody   body = new RigidBody(boxShape, boxMass, null)
                {
                    Pose = new Pose(randomPosition, randomOrientation),
                };
                Simulation.RigidBodies.Add(body);
            }
        }
예제 #21
0
        public ConstraintSample2(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);

            // ----- PointOnLineConstraint
            RigidBody box0 = new RigidBody(new BoxShape(0.1f, 0.5f, 6))
            {
                Pose       = new Pose(new Vector3F(-4, 3, 0)),
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(box0);
            RigidBody sphere0 = new RigidBody(new SphereShape(0.5f))
            {
                Pose = new Pose(new Vector3F(-4, 2, 0))
            };

            Simulation.RigidBodies.Add(sphere0);
            PointOnLineConstraint pointOnLineConstraint = new PointOnLineConstraint
            {
                BodyA = box0,
                // The line goes through this point:
                AnchorPositionALocal = new Vector3F(0, -0.25f, 0),
                BodyB = sphere0,
                AnchorPositionBLocal = new Vector3F(0, 0.5f, 0),
                // The line axis:
                AxisALocal = Vector3F.UnitZ,
                // The movement on the line axis:
                Minimum          = -3,
                Maximum          = +3,
                CollisionEnabled = false,
            };

            Simulation.Constraints.Add(pointOnLineConstraint);

            // ----- PointOnPlaneConstraint
            RigidBody box1 = new RigidBody(new BoxShape(2f, 0.5f, 6))
            {
                Pose       = new Pose(new Vector3F(-1, 3, 0)),
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(box1);
            RigidBody sphere1 = new RigidBody(new SphereShape(0.5f))
            {
                Pose = new Pose(new Vector3F(-1, 2, 0))
            };

            Simulation.RigidBodies.Add(sphere1);
            PointOnPlaneConstraint pointOnPlaneConstraint = new PointOnPlaneConstraint
            {
                BodyA = box1,
                // The plane goes through this point:
                AnchorPositionALocal = new Vector3F(0, -0.25f, 0),
                BodyB = sphere1,
                AnchorPositionBLocal = new Vector3F(0, 0.5f, 0),
                // Two orthonormal vectors that define the plane:
                XAxisALocal = Vector3F.UnitX,
                YAxisALocal = Vector3F.UnitZ,
                // Limits for the x axis and y axis movement:
                Minimum          = new Vector2F(-1, -3),
                Maximum          = new Vector2F(1, 3),
                CollisionEnabled = false,
            };

            Simulation.Constraints.Add(pointOnPlaneConstraint);

            // ----- NoRotationConstraint
            // This constraint keeps two rotations synchronized.
            RigidBody box2 = new RigidBody(new BoxShape(1, 1, 1))
            {
                Pose = new Pose(new Vector3F(2, 3, 0)),
            };

            Simulation.RigidBodies.Add(box2);
            RigidBody box3 = new RigidBody(new BoxShape(1, 1, 1))
            {
                Pose = new Pose(new Vector3F(2.5f, 2, 0))
            };

            Simulation.RigidBodies.Add(box3);
            NoRotationConstraint noRotationConstraint = new NoRotationConstraint
            {
                BodyA            = box2,
                BodyB            = box3,
                CollisionEnabled = true,
            };

            Simulation.Constraints.Add(noRotationConstraint);

            // ----- Distance limit.
            // Here, the distance of two cone tips is kept at a constant distance.
            RigidBody cone0 = new RigidBody(new ConeShape(0.5f, 1f))
            {
                Pose       = new Pose(new Vector3F(4, 3, 0), Matrix33F.CreateRotationZ(ConstantsF.Pi)),
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(cone0);
            RigidBody cone1 = new RigidBody(new ConeShape(0.5f, 1f))
            {
                Pose = new Pose(new Vector3F(4, 0, 0))
            };

            Simulation.RigidBodies.Add(cone1);
            DistanceLimit distanceLimit = new DistanceLimit
            {
                BodyA = cone0,
                BodyB = cone1,
                // The attachment points are the tips of the cones.
                AnchorPositionALocal = new Vector3F(0, 1, 0),
                AnchorPositionBLocal = new Vector3F(0, 1, 0),
                // The tips should always have a distance of 0.5 units.
                MinDistance = 0.5f,
                MaxDistance = 0.5f,
            };

            Simulation.Constraints.Add(distanceLimit);
        }
예제 #22
0
        /// <summary>
        /// Initializes the ragdoll for the given skeleton pose.
        /// </summary>
        /// <param name="skeletonPose">The skeleton pose.</param>
        /// <param name="ragdoll">The ragdoll.</param>
        /// <param name="simulation">The simulation in which the ragdoll will be used.</param>
        /// <param name="scale">A scaling factor to scale the size of the ragdoll.</param>
        public static void Create(SkeletonPose skeletonPose, Ragdoll ragdoll, Simulation simulation, float scale)
        {
            var skeleton = skeletonPose.Skeleton;

            const float totalMass      = 80; // The total mass of the ragdoll.
            const int   numberOfBodies = 17;

            // Get distance from foot to head as a measure for the size of the ragdoll.
            int head               = skeleton.GetIndex("Head");
            int footLeft           = skeleton.GetIndex("L_Ankle1");
            var headPosition       = skeletonPose.GetBonePoseAbsolute(head).Translation;
            var footPosition       = skeletonPose.GetBonePoseAbsolute(footLeft).Translation;
            var headToFootDistance = (headPosition - footPosition).Length;

            // We use the same mass properties for all bodies. This is not realistic but more stable
            // because large mass differences or thin bodies (arms!) are less stable.
            // We use the mass properties of sphere proportional to the size of the model.
            var massFrame = MassFrame.FromShapeAndMass(new SphereShape(headToFootDistance / 8), Vector3F.One, totalMass / numberOfBodies, 0.1f, 1);

            var material = new UniformMaterial();

            #region ----- Add Bodies and Body Offsets -----

            var numberOfBones = skeleton.NumberOfBones;
            ragdoll.Bodies.AddRange(Enumerable.Repeat <RigidBody>(null, numberOfBones));
            ragdoll.BodyOffsets.AddRange(Enumerable.Repeat(Pose.Identity, numberOfBones));

            var pelvis = skeleton.GetIndex("Pelvis");
            ragdoll.Bodies[pelvis]      = new RigidBody(new BoxShape(0.3f * scale, 0.4f * scale, 0.55f * scale), massFrame, material);
            ragdoll.BodyOffsets[pelvis] = new Pose(new Vector3F(0, 0, 0));

            var backLower = skeleton.GetIndex("Spine");
            ragdoll.Bodies[backLower]      = new RigidBody(new BoxShape(0.36f * scale, 0.4f * scale, 0.55f * scale), massFrame, material);
            ragdoll.BodyOffsets[backLower] = new Pose(new Vector3F(0.18f * scale, 0, 0));

            var backUpper = skeleton.GetIndex("Spine2");
            ragdoll.Bodies[backUpper]      = new RigidBody(new BoxShape(0.5f * scale, 0.4f * scale, 0.65f * scale), massFrame, material);
            ragdoll.BodyOffsets[backUpper] = new Pose(new Vector3F(0.25f * scale, 0, 0));

            var neck = skeleton.GetIndex("Neck");
            ragdoll.Bodies[neck]      = new RigidBody(new CapsuleShape(0.12f * scale, 0.3f * scale), massFrame, material);
            ragdoll.BodyOffsets[neck] = new Pose(new Vector3F(0.15f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[neck].CollisionObject.Enabled = false;

            ragdoll.Bodies[head]      = new RigidBody(new SphereShape(0.2f * scale), massFrame, material);
            ragdoll.BodyOffsets[head] = new Pose(new Vector3F(0.15f * scale, 0.02f * scale, 0));

            var armUpperLeft = skeleton.GetIndex("L_UpperArm");
            ragdoll.Bodies[armUpperLeft]      = new RigidBody(new CapsuleShape(0.12f * scale, 0.6f * scale), massFrame, material);
            ragdoll.BodyOffsets[armUpperLeft] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            var armLowerLeft = skeleton.GetIndex("L_Forearm");
            ragdoll.Bodies[armLowerLeft]      = new RigidBody(new CapsuleShape(0.08f * scale, 0.5f * scale), massFrame, material);
            ragdoll.BodyOffsets[armLowerLeft] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            var handLeft = skeleton.GetIndex("L_Hand");
            ragdoll.Bodies[handLeft]      = new RigidBody(new BoxShape(0.2f * scale, 0.06f * scale, 0.15f * scale), massFrame, material);
            ragdoll.BodyOffsets[handLeft] = new Pose(new Vector3F(0.1f * scale, 0, 0));

            var armUpperRight = skeleton.GetIndex("R_UpperArm");
            ragdoll.Bodies[armUpperRight]      = new RigidBody(new CapsuleShape(0.12f * scale, 0.6f * scale), massFrame, material);
            ragdoll.BodyOffsets[armUpperRight] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            var armLowerRight = skeleton.GetIndex("R_Forearm");
            ragdoll.Bodies[armLowerRight]      = new RigidBody(new CapsuleShape(0.08f * scale, 0.5f * scale), massFrame, material);
            ragdoll.BodyOffsets[armLowerRight] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            var handRight = skeleton.GetIndex("R_Hand");
            ragdoll.Bodies[handRight]      = new RigidBody(new BoxShape(0.2f * scale, 0.06f * scale, 0.15f * scale), massFrame, material);
            ragdoll.BodyOffsets[handRight] = new Pose(new Vector3F(0.1f * scale, 0, 0));

            var legUpperLeft = skeleton.GetIndex("L_Thigh1");
            ragdoll.Bodies[legUpperLeft]      = new RigidBody(new CapsuleShape(0.16f * scale, 0.8f * scale), massFrame, material);
            ragdoll.BodyOffsets[legUpperLeft] = new Pose(new Vector3F(0.4f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            var legLowerLeft = skeleton.GetIndex("L_Knee2");
            ragdoll.Bodies[legLowerLeft]      = new RigidBody(new CapsuleShape(0.12f * scale, 0.65f * scale), massFrame, material);
            ragdoll.BodyOffsets[legLowerLeft] = new Pose(new Vector3F(0.32f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            //var footLeft = skeleton.GetIndex("L_Ankle1");
            ragdoll.Bodies[footLeft]      = new RigidBody(new BoxShape(0.20f * scale, 0.5f * scale, 0.3f * scale), massFrame, material);
            ragdoll.BodyOffsets[footLeft] = new Pose(new Vector3F(0.16f * scale, 0.15f * scale, 0));

            var legUpperRight = skeleton.GetIndex("R_Thigh");
            ragdoll.Bodies[legUpperRight]      = new RigidBody(new CapsuleShape(0.16f * scale, 0.8f * scale), massFrame, material);
            ragdoll.BodyOffsets[legUpperRight] = new Pose(new Vector3F(0.4f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            var legLowerRight = skeleton.GetIndex("R_Knee");
            ragdoll.Bodies[legLowerRight]      = new RigidBody(new CapsuleShape(0.12f * scale, 0.65f * scale), massFrame, material);
            ragdoll.BodyOffsets[legLowerRight] = new Pose(new Vector3F(0.32f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

            var footRight = skeleton.GetIndex("R_Ankle");
            ragdoll.Bodies[footRight]      = new RigidBody(new BoxShape(0.20f * scale, 0.5f * scale, 0.3f * scale), massFrame, material);
            ragdoll.BodyOffsets[footRight] = new Pose(new Vector3F(0.16f * scale, 0.15f * scale, 0));
            #endregion

            #region ----- Set Collision Filters -----

            // Collisions between connected bodies will be disabled in AddJoint(). (A BallJoint
            // has a property CollisionEnabled which decides whether connected bodies can
            // collide.)
            // But we need to disable some more collision between bodies that are not directly
            // connected but still too close to each other.
            var filter = (ICollisionFilter)simulation.CollisionDomain.CollisionDetection.CollisionFilter;
            filter.Set(ragdoll.Bodies[backUpper].CollisionObject, ragdoll.Bodies[head].CollisionObject, false);
            filter.Set(ragdoll.Bodies[armUpperRight].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false);
            filter.Set(ragdoll.Bodies[armUpperLeft].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false);
            filter.Set(ragdoll.Bodies[legUpperLeft].CollisionObject, ragdoll.Bodies[legUpperRight].CollisionObject, false);
            #endregion

            #region ----- Add Joints -----

            AddJoint(skeletonPose, ragdoll, pelvis, backLower);
            AddJoint(skeletonPose, ragdoll, backLower, backUpper);
            AddJoint(skeletonPose, ragdoll, backUpper, neck);
            AddJoint(skeletonPose, ragdoll, neck, head);
            AddJoint(skeletonPose, ragdoll, backUpper, armUpperLeft);
            AddJoint(skeletonPose, ragdoll, armUpperLeft, armLowerLeft);
            AddJoint(skeletonPose, ragdoll, armLowerLeft, handLeft);
            AddJoint(skeletonPose, ragdoll, backUpper, armUpperRight);
            AddJoint(skeletonPose, ragdoll, armUpperRight, armLowerRight);
            AddJoint(skeletonPose, ragdoll, armLowerRight, handRight);
            AddJoint(skeletonPose, ragdoll, pelvis, legUpperLeft);
            AddJoint(skeletonPose, ragdoll, legUpperLeft, legLowerLeft);
            AddJoint(skeletonPose, ragdoll, legLowerLeft, footLeft);
            AddJoint(skeletonPose, ragdoll, pelvis, legUpperRight);
            AddJoint(skeletonPose, ragdoll, legUpperRight, legLowerRight);
            AddJoint(skeletonPose, ragdoll, legLowerRight, footRight);
            #endregion

            #region ----- Add Limits -----

            // Choosing limits is difficult.
            // We create hinge limits with AngularLimits in the back and in the knee.
            // For all other joints we use TwistSwingLimits with symmetric cones.

            AddAngularLimit(skeletonPose, ragdoll, pelvis, backLower, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f));
            AddAngularLimit(skeletonPose, ragdoll, backLower, backUpper, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.4f));
            AddAngularLimit(skeletonPose, ragdoll, backUpper, neck, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f));
            AddTwistSwingLimit(ragdoll, neck, head, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.5f, -0.7f), new Vector3F(0.1f, 0.5f, 0.7f));

            var parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse;
            var childBindPoseAbsolute  = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperLeft).Inverse;
            var bindPoseRelative       = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
            AddTwistSwingLimit(ragdoll, backUpper, armUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(-0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f));

            AddTwistSwingLimit(ragdoll, armUpperLeft, armLowerLeft, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f));
            AddTwistSwingLimit(ragdoll, armLowerLeft, handLeft, Matrix33F.Identity, Matrix33F.CreateRotationX(+ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f));

            parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse;
            childBindPoseAbsolute  = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperRight).Inverse;
            bindPoseRelative       = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
            AddTwistSwingLimit(ragdoll, backUpper, armUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f));

            AddTwistSwingLimit(ragdoll, armUpperRight, armLowerRight, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f));
            AddTwistSwingLimit(ragdoll, armLowerRight, handRight, Matrix33F.Identity, Matrix33F.CreateRotationX(-ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f));

            parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse;
            childBindPoseAbsolute  = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperLeft).Inverse;
            bindPoseRelative       = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
            AddTwistSwingLimit(ragdoll, pelvis, legUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f));

            AddAngularLimit(skeletonPose, ragdoll, legUpperLeft, legLowerLeft, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f));
            AddTwistSwingLimit(ragdoll, legLowerLeft, footLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f));

            parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse;
            childBindPoseAbsolute  = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperRight).Inverse;
            bindPoseRelative       = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
            AddTwistSwingLimit(ragdoll, pelvis, legUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f));

            AddAngularLimit(skeletonPose, ragdoll, legUpperRight, legLowerRight, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f));
            AddTwistSwingLimit(ragdoll, legLowerRight, footRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f));
            #endregion

            #region ----- Add Motors -----

            ragdoll.Motors.AddRange(Enumerable.Repeat <RagdollMotor>(null, numberOfBones));
            ragdoll.Motors[pelvis]        = new RagdollMotor(pelvis, -1);
            ragdoll.Motors[backLower]     = new RagdollMotor(backLower, pelvis);
            ragdoll.Motors[backUpper]     = new RagdollMotor(backUpper, backLower);
            ragdoll.Motors[neck]          = new RagdollMotor(neck, backUpper);
            ragdoll.Motors[head]          = new RagdollMotor(head, neck);
            ragdoll.Motors[armUpperLeft]  = new RagdollMotor(armUpperLeft, backUpper);
            ragdoll.Motors[armLowerLeft]  = new RagdollMotor(armLowerLeft, armUpperLeft);
            ragdoll.Motors[handLeft]      = new RagdollMotor(handLeft, armLowerLeft);
            ragdoll.Motors[armUpperRight] = new RagdollMotor(armUpperRight, backUpper);
            ragdoll.Motors[armLowerRight] = new RagdollMotor(armLowerRight, armUpperRight);
            ragdoll.Motors[handRight]     = new RagdollMotor(handRight, armLowerRight);
            ragdoll.Motors[legUpperLeft]  = new RagdollMotor(legUpperLeft, pelvis);
            ragdoll.Motors[legLowerLeft]  = new RagdollMotor(legLowerLeft, legUpperLeft);
            ragdoll.Motors[footLeft]      = new RagdollMotor(footLeft, legLowerLeft);
            ragdoll.Motors[legUpperRight] = new RagdollMotor(legUpperRight, pelvis);
            ragdoll.Motors[legLowerRight] = new RagdollMotor(legLowerRight, legUpperRight);
            ragdoll.Motors[footRight]     = new RagdollMotor(footRight, legLowerRight);
            #endregion
        }
예제 #23
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;
            }
        }
예제 #24
0
        /// <summary>
        /// Initializes the physics simulation.
        /// </summary>
        private void InitializePhysics()
        {
            // Add a gravity force.
            _gravity = new Gravity {
                Acceleration = new Vector3F(0, -GravityAcceleration, 0)
            };
            Simulation.ForceEffects.Add(_gravity);

            // Add a damping force.
            Simulation.ForceEffects.Add(new Damping());

            // Add a few spheres.
            Simulation.RigidBodies.Add(new RigidBody(new SphereShape(0.3f))
            {
                Pose = new Pose(new Vector3F(0, 1, 0)),
            });
            Simulation.RigidBodies.Add(new RigidBody(new SphereShape(0.2f))
            {
                Pose = new Pose(new Vector3F(1, 1, 0)),
            });
            Simulation.RigidBodies.Add(new RigidBody(new SphereShape(0.4f))
            {
                Pose = new Pose(new Vector3F(0, 1, 2)),
            });

            // Add ragdoll.
            AddRagdoll(1, new Vector3F(0, 2, 0));

            // The Simulation performs 2 sub-time-steps per frame because we have set
            // the FixedTimeStep of the simulation to 1/60 s and the TargetElapsedTime of the game
            // is 1/30 s (30 Hz). In the event SubTimeStepFinished, we call our method
            // HandleBreakableJoints() to check the forces in the joints and disable constraints where
            // the force is too large.
            // Instead, we could also call HandleBreakableJoints() in the Update() method of the game
            // but then it is only called with the 30 Hz of the game. It is more accurate to call the
            // method at the end of each simulation sub-time-step (60 Hz).
            Simulation.SubTimeStepFinished += (s, e) => HandleBreakableJoints();

            // Add 6 planes that keep the bodies inside the visible area. The exact positions and angles
            // have been determined by experimentation.
            var groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0))
            {
                Name       = "GroundPlane",
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(groundPlane);
            var nearPlane = new RigidBody(new PlaneShape(-Vector3F.UnitY, -8))
            {
                Name       = "NearPlane",
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(nearPlane);
            var leftPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-22f)) * Vector3F.UnitX, -4.8f))
            {
                Name       = "LeftPlane",
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(leftPlane);

            var rightPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationZ(MathHelper.ToRadians(22f)) * -Vector3F.UnitX, -4.8f))
            {
                Name       = "RightPlane",
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(rightPlane);

            var topPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationX(MathHelper.ToRadians(14f)) * Vector3F.UnitZ, -3f))
            {
                Name       = "TopPlane",
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(topPlane);

            var bottomPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationX(MathHelper.ToRadians(-14f)) * -Vector3F.UnitZ, -3f))
            {
                Name       = "BottomPlane",
                MotionType = MotionType.Static,
            };

            Simulation.RigidBodies.Add(bottomPlane);
        }
        public CompositeMaterial2Sample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            // Add basic force effects.
            Simulation.ForceEffects.Add(new Gravity());
            Simulation.ForceEffects.Add(new Damping());

            // Add a ground plane.
            RigidBody groundPlane = new RigidBody(new PlaneShape(new Vector3F(0, 1, 0.25f).Normalized, 0))
            {
                Name       = "GroundPlane", // Names are not required but helpful for debugging.
                MotionType = MotionType.Static,
            };

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

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

            // Create a rigid body that consists of multiple shapes: Two boxes and a cylinder between them.
            CompositeShape compositeShape = new CompositeShape();

            compositeShape.Children.Add(new GeometricObject(new BoxShape(1f, 1f, 1f), new Pose(new Vector3F(1.5f, 0f, 0f))));
            compositeShape.Children.Add(new GeometricObject(new BoxShape(1f, 1, 1f), new Pose(new Vector3F(-1.5f, 0f, 0f))));
            compositeShape.Children.Add(new GeometricObject(new CylinderShape(0.1f, 2), new Pose(Matrix33F.CreateRotationZ(ConstantsF.PiOver2))));

            // A CompositeMaterial is used to assign a different material to each shape.
            CompositeMaterial compositeMaterial = new CompositeMaterial();

            compositeMaterial.Materials.Add(roughMaterial);    // Assign the rough material to the first box.
            compositeMaterial.Materials.Add(slipperyMaterial); // Assign the slippery material to the second box.
            compositeMaterial.Materials.Add(null);             // Use whatever is default for the handle between the boxes.

            RigidBody body = new RigidBody(compositeShape, null, compositeMaterial)
            {
                Pose = new Pose(new Vector3F(0, 2.2f, -5)),
            };

            Simulation.RigidBodies.Add(body);
        }