コード例 #1
0
        // Add a chain-like figure using TransformedFigure and CompositeFigure.
        private void CreateChain()
        {
            var ellipse = new EllipseFigure
            {
                IsFilled = false,
                RadiusX  = 1f,
                RadiusY  = 1f,
            };

            var compositeFigure = new CompositeFigure();

            for (int i = 0; i < 9; i++)
            {
                var transformedEllipse = new TransformedFigure(ellipse)
                {
                    Scale = new Vector3F(0.4f, 0.2f, 1),
                    Pose  = new Pose(new Vector3F(-2 + i * 0.5f, 0, 0), Matrix33F.CreateRotationX(ConstantsF.PiOver2 * (i % 2)))
                };
                compositeFigure.Children.Add(transformedEllipse);
            }

            _scene.Children.Add(new FigureNode(compositeFigure)
            {
                Name            = "Chain",
                StrokeThickness = 2,
                StrokeColor     = new Vector3F(0.1f),
                StrokeAlpha     = 1,
                PoseLocal       = new Pose(new Vector3F(0, 3, 0)),
            });
        }
コード例 #2
0
        //--------------------------------------------------------------
        #region Creation & Cleanup
        //--------------------------------------------------------------

        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class.
        /// </summary>
        /// </overloads>
        ///
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainDecalLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            {
                throw new ArgumentNullException("graphicService");
            }

            // Use a down orientation per default.
            Pose = new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2));

            var effect = graphicService.Content.Load <Effect>("DigitalRune/Terrain/TerrainDecalLayer");

            Material = new Material
            {
                { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
            };

            FadeOutStart       = int.MaxValue;
            FadeOutEnd         = int.MaxValue;
            Width              = 1;
            Height             = 1;
            DiffuseColor       = new Vector3F(1, 1, 1);
            SpecularColor      = new Vector3F(1, 1, 1);
            SpecularPower      = 10;
            Alpha              = 1;
            DiffuseTexture     = graphicService.GetDefaultTexture2DWhite();
            SpecularTexture    = graphicService.GetDefaultTexture2DBlack();
            NormalTexture      = graphicService.GetDefaultNormalTexture();
            HeightTextureScale = 1;
            HeightTexture      = graphicService.GetDefaultTexture2DBlack();

            UpdateAabb();
        }
コード例 #3
0
        private void SetCameraPose()
        {
            var vehiclePose = _vehicle.Pose;

            if (_useSpectatorView)
            {
                // Spectator Mode:
                // Camera is looking at the car from a fixed location in the level.
                Vector3F position = new Vector3F(10, 8, 10);
                Vector3F target   = vehiclePose.Position;
                Vector3F up       = Vector3F.UnitY;

                // Set the new camera view matrix. (Setting the View matrix changes the Pose.
                // The pose is simply the inverse of the view matrix).
                CameraNode.View = Matrix44F.CreateLookAt(position, target, up);
            }
            else
            {
                // Player Camera:
                // Camera moves with the car. The look direction can be changed by moving the mouse.
                Matrix33F yaw         = Matrix33F.CreateRotationY(_yaw);
                Matrix33F pitch       = Matrix33F.CreateRotationX(_pitch);
                Matrix33F orientation = vehiclePose.Orientation * yaw * pitch;
                Vector3F  forward     = orientation * -Vector3F.UnitZ;
                Vector3F  up          = Vector3F.UnitY;
                Vector3F  position    = vehiclePose.Position - 10 * forward + 5 * up;
                Vector3F  target      = vehiclePose.Position + 1 * up;

                CameraNode.View = Matrix44F.CreateLookAt(position, target, up);
            }
        }
コード例 #4
0
        public void CreateRotationX()
        {
            float     angle = (float)MathHelper.ToRadians(30.0f);
            Matrix33F m     = Matrix33F.CreateRotationX(angle);

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

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

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

            Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.CreateRotation(Vector3F.UnitX, angle), m));
        }
コード例 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class with a custom
        /// material.
        /// </summary>
        /// <param name="material">The material.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="material"/> is <see langword="null"/>.
        /// </exception>
        public TerrainDecalLayer(Material material)
        {
            if (material == null)
            {
                throw new ArgumentNullException("material");
            }

            // Use a down orientation per default.
            Pose = new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2));

            Material = material;
            UpdateAabb();
        }
コード例 #6
0
        public override void Update(GameTime gameTime)
        {
            // Update the poses of the animated scene nodes.
            var frontWheelSteeringRotation = Matrix33F.CreateRotationY(_frontWheelSteeringAngle.Value);

            _frontWheelLeft.PoseLocal  = _frontWheelLeftRestPose * new Pose(frontWheelSteeringRotation);
            _frontWheelRight.PoseLocal = _frontWheelRightRestPose * new Pose(frontWheelSteeringRotation);
            _hatch.PoseLocal           = _hatchRestPose * new Pose(Matrix33F.CreateRotationX(_hatchAngle.Value));
            _turret.PoseLocal          = _turretRestPose * new Pose(Matrix33F.CreateRotationY(_turretAngle.Value));
            _cannon.PoseLocal          = _cannonRestPose * new Pose(Matrix33F.CreateRotationX(_cannonAngle.Value));

            base.Update(gameTime);
        }
コード例 #7
0
ファイル: LdrSkySample.cs プロジェクト: terrynoya/DigitalRune
        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;
        }
コード例 #8
0
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            // ----- Animate the 2 cubes.
            _animationTime += (float)gameTime.ElapsedGameTime.TotalSeconds * 10;

            // Before updating the positions and orientations, store the previous poses of
            // the scene nodes. (The property SceneNode.LastPoseWorld is read by certain
            // post-processing effects, such as motion blur.)
            _movingCube.SetLastPose(true);
            _rotatingCube.SetLastPose(true);

            _movingCube.PoseWorld   = new Pose(new Vector3F(-6, 1, -3 + (float)Math.Sin(_animationTime) * 2f));
            _rotatingCube.PoseWorld = new Pose(new Vector3F(-4, 1, -1), Matrix33F.CreateRotationX(_animationTime));

            // <1> / <Shift> + <1> --> Change number of samples.
            if (InputService.IsPressed(Keys.D1, true))
            {
                bool  isShiftDown = (InputService.ModifierKeys & ModifierKeys.Shift) != 0;
                float delta       = isShiftDown ? +1 : -1;
                _objectMotionBlur.NumberOfSamples = MathHelper.Max(_objectMotionBlur.NumberOfSamples + delta, 1);
            }

            // <2> / <Shift> + <2> --> Change max blur radius.
            if (InputService.IsDown(Keys.D2))
            {
                // Increase or decrease value by a factor of 1.01 every frame (1/60 s).
                bool  isShiftDown = (InputService.ModifierKeys & ModifierKeys.Shift) != 0;
                float factor      = isShiftDown ? 1.01f : 1.0f / 1.01f;
                float time        = (float)gameTime.ElapsedGameTime.TotalSeconds;
                _objectMotionBlur.MaxBlurRadius =
                    MathHelper.Max(_objectMotionBlur.MaxBlurRadius * (float)Math.Pow(factor, time * 60), 1);
            }

            // <3> / <Shift> + <3> --> Toggle soft edges.
            if (InputService.IsPressed(Keys.D3, false))
            {
                _objectMotionBlur.SoftenEdges = !_objectMotionBlur.SoftenEdges;
            }

            GraphicsScreen.DebugRenderer.DrawText(
                "\n\nHold <1> or <Shift>+<1> to decrease or increase the number of samples: " + _objectMotionBlur.NumberOfSamples
                + "\nHold <2> or <Shift>+<2> to decrease or increase the max blur radius: " + _objectMotionBlur.MaxBlurRadius
                + "\nPress <3> to toggle soft edges: " + _objectMotionBlur.SoftenEdges);
        }
コード例 #9
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));
        }
コード例 #10
0
        public CampfireSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            var particleSystem = Campfire.CreateCampfire(ContentManager);

            // Add a smoke effect as a child to the campfire.
            particleSystem.Children = new ParticleSystemCollection();
            particleSystem.Children.Add(CampfireSmoke.CreateCampfireSmoke(ContentManager));

            // Position the campfire (including its child) in the level.
            // (The fire effect lies in the xy plane and shoots into the forward direction (= -z axis).
            // Therefore, we rotate the particle system to shoot upwards.)
            particleSystem.Pose = new Pose(new Vector3F(0, 0.2f, 0), Matrix33F.CreateRotationX(ConstantsF.PiOver2));

            ParticleSystemService.ParticleSystems.Add(particleSystem);

            _particleSystemNode = new ParticleSystemNode(particleSystem);
            GraphicsScreen.Scene.Children.Add(_particleSystemNode);
        }
コード例 #11
0
ファイル: PoseTest.cs プロジェクト: terrynoya/DigitalRune
        public void Test1()
        {
            Pose p = Pose.Identity;

            Assert.AreEqual(Matrix44F.Identity, p.ToMatrix44F());
            Assert.AreEqual(Matrix33F.Identity, p.Orientation);
            Assert.AreEqual(Vector3F.Zero, p.Position);

            p.Position = new Vector3F(1, 2, 3);

            p.Orientation = Matrix33F.CreateRotation(new Vector3F(3, -4, 9), 0.49f);
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToWorldDirection(Vector3F.UnitX), 0), p * new Vector4F(1, 0, 0, 0)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToWorldDirection(Vector3F.UnitY), 0), p * new Vector4F(0, 1, 0, 0)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToWorldDirection(Vector3F.UnitZ), 0), p * new Vector4F(0, 0, 1, 0)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToWorldPosition(Vector3F.UnitX), 1), p * new Vector4F(1, 0, 0, 1)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToWorldPosition(Vector3F.UnitY), 1), p * new Vector4F(0, 1, 0, 1)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToWorldPosition(Vector3F.UnitZ), 1), p * new Vector4F(0, 0, 1, 1)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToLocalDirection(Vector3F.UnitX), 0), p.Inverse * new Vector4F(1, 0, 0, 0)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToLocalDirection(Vector3F.UnitY), 0), p.Inverse * new Vector4F(0, 1, 0, 0)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToLocalDirection(Vector3F.UnitZ), 0), p.Inverse * new Vector4F(0, 0, 1, 0)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToLocalPosition(Vector3F.UnitX), 1), p.Inverse * new Vector4F(1, 0, 0, 1)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToLocalPosition(Vector3F.UnitY), 1), p.Inverse * new Vector4F(0, 1, 0, 1)));
            Assert.IsTrue(Vector4F.AreNumericallyEqual(new Vector4F(p.ToLocalPosition(Vector3F.UnitZ), 1), p.Inverse * new Vector4F(0, 0, 1, 1)));

            Pose p2 = Pose.FromMatrix(new Matrix44F(p.Orientation, Vector3F.Zero));

            Assert.IsTrue(Matrix33F.AreNumericallyEqual(p.Orientation, p2.Orientation));
            Assert.IsTrue(Vector3F.AreNumericallyEqual(p2.Position, Vector3F.Zero));

            Matrix44F m = p2;

            m.SetColumn(3, new Vector4F(p.Position, 1));
            p2 = Pose.FromMatrix(m);
            Assert.IsTrue(Matrix33F.AreNumericallyEqual(p.Orientation, p2.Orientation));
            Assert.AreEqual(p.Position, p2.Position);
            //Assert.IsTrue(Vector3F.AreNumericallyEqual(p.Position, p2.Position));

            // Test other constructors.
            Assert.AreEqual(Vector3F.Zero, new Pose(QuaternionF.CreateRotationX(0.3f)).Position);
            Assert.AreEqual(Matrix33F.CreateRotationX(0.3f), new Pose(Matrix33F.CreateRotationX(0.3f)).Orientation);
            Assert.AreEqual(new Vector3F(1, 2, 3), new Pose(new Vector3F(1, 2, 3)).Position);
            Assert.AreEqual(Matrix33F.Identity, new Pose(new Vector3F(1, 2, 3)).Orientation);
        }
コード例 #12
0
        private void UpdateOrientation(Vector delta)
        {
            Pose pose = _cameraNode.PoseWorld;

            // Get previous yaw and pitch angles.
            float yaw, pitch;

            GetYawPitch(pose.Orientation, out yaw, out pitch);

            // Apply delta.
            float speed = (float)Speed;

            yaw   -= (float)delta.X * speed;
            pitch -= (float)delta.Y * speed;

            // Set new camera orientation.
            pose.Orientation      = Matrix33F.CreateRotationY(yaw) * Matrix33F.CreateRotationX(pitch);
            _cameraNode.PoseWorld = pose;
        }
コード例 #13
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));
        }
コード例 #14
0
        public BrownOut(ContentManager contentManager)
        {
            Pose = new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2));

            // Smoke on a ring.
            var outerRingSmoke = CreateSmoke(contentManager);

            outerRingSmoke.Effectors.Add(new StreamEmitter {
                DefaultEmissionRate = 30
            });
            outerRingSmoke.Effectors.Add(new StartPositionEffector
            {
                Distribution = new CircleDistribution {
                    OuterRadius = 5, InnerRadius = 4
                }
            });

            // Smoke in the area inside the ring.
            var innerCircleSmoke = CreateSmoke(contentManager);

            innerCircleSmoke.Effectors.Add(new StreamEmitter {
                DefaultEmissionRate = 10
            });
            innerCircleSmoke.Effectors.Add(new StartPositionEffector
            {
                Distribution = new CircleDistribution {
                    OuterRadius = 4, InnerRadius = 0
                }
            });

            // Uniform particle parameter that are the same for all child particle systems.
            Parameters.AddUniform <float>(ParticleParameterNames.Lifetime).DefaultValue = 5;
            _isDepthSortedParameter = Parameters.AddUniform <bool>(ParticleParameterNames.IsDepthSorted);
            _isDepthSortedParameter.DefaultValue = true;

            Children = new ParticleSystemCollection {
                outerRingSmoke, innerCircleSmoke
            };
        }
コード例 #15
0
        private void OnMouseMove(object sender, MouseEventArgs eventArgs)
        {
            var mousePosition = eventArgs.GetPosition(AssociatedObject);

            if (eventArgs.LeftButton == MouseButtonState.Pressed)
            {
                var    target = CameraTarget;
                float  speed  = (float)Speed;
                Vector delta  = mousePosition - _lastMousePosition;

                // Rotation around y-axis in world space
                float angle0    = (float)delta.X * speed * _upDirection;
                Pose  rotation0 = new Pose(Matrix33F.CreateRotationY(angle0));

                // Rotation around x-axis in view space.
                float angle1    = (float)delta.Y * speed;
                Pose  rotation1 = new Pose(Matrix33F.CreateRotationX(angle1));
                float distance  = (CameraTarget - _cameraNode.PoseWorld.Position).Length;

                // Variant #1: Set camera pose.
                var pose = new Pose(target)
                           * rotation0.Inverse
                           * new Pose(-target)
                           * _cameraNode.PoseWorld
                           * new Pose(new Vector3F(0, 0, -distance))
                           * rotation1.Inverse
                           * new Pose(new Vector3F(0, 0, distance));

                // Re-orthogonalize to remove numerical errors which could add up.
                var orientation = pose.Orientation;
                orientation.Orthogonalize();
                pose.Orientation = orientation;

                CameraNode.PoseWorld = pose;
            }

            _lastMousePosition = mousePosition;
        }
コード例 #16
0
        public static void Load(CollisionDomain collisionDomain)
        {
            // Create a box for the ground.
            AddObject("Ground", new Pose(new Vector3F(0, -5, 0)), new BoxShape(60, 10, 60), collisionDomain);

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

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

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

            //
            // Create stairs with increasing step height.
            //
            // Each step is a box. With this object we can test if our character can climb up
            // stairs. The character controller has a step height limit. Increasing step heights
            // let us test if the step height limit works.
            float       startHeight = 0;
            const float stepDepth   = 1f;

            for (int i = 0; i < 10; i++)
            {
                float    stepHeight = 0.1f + i * 0.05f;
                Pose     pose       = new Pose(new Vector3F(0, startHeight + stepHeight / 2, -2 - i * stepDepth));
                BoxShape shape      = new BoxShape(2, stepHeight, stepDepth);
                AddObject("Step" + i, pose, shape, collisionDomain);
                startHeight += stepHeight;
            }

            //
            // Create a height field.
            //
            // Terrain that is uneven is best modeled with a height field. Height fields are faster
            // than general triangle meshes.
            // The height direction is the y direction.
            // The height field lies in the x/z plane.
            var numberOfSamplesX = 20;
            var numberOfSamplesZ = 20;
            var samples          = new float[numberOfSamplesX * numberOfSamplesZ];

            // Create arbitrary height values.
            for (int z = 0; z < numberOfSamplesZ; z++)
            {
                for (int x = 0; x < numberOfSamplesX; x++)
                {
                    if (x == 0 || z == 0 || x == 19 || z == 19)
                    {
                        // Set this boundary elements to a low height, so that the height field is connected
                        // to the ground.
                        samples[z * numberOfSamplesX + x] = -1;
                    }
                    else
                    {
                        // A sine/cosine function that creates some interesting waves.
                        samples[z * numberOfSamplesX + x] = 1.0f + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1.0f);
                    }
                }
            }
            var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ);

            AddObject("Heightfield", new Pose(new Vector3F(10, 0, 10)), heightField, collisionDomain);

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

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

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

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

            // Create a mesh object to test walking on triangle meshes.
            // Normally, the mesh would be loaded from a file. Here, we make a composite shape and
            // let DigitalRune Geometry compute a mesh for it. Then we throw away the composite
            // shape and use only the mesh. - We do this to test triangle meshes. Using the composite
            // shape instead of the triangle mesh would be a lot faster.
            CompositeShape compositeShape = new CompositeShape();

            compositeShape.Children.Add(new GeometricObject(heightField, Pose.Identity));
            compositeShape.Children.Add(new GeometricObject(new CylinderShape(1, 2), new Pose(new Vector3F(10, 1, 10))));
            compositeShape.Children.Add(new GeometricObject(new SphereShape(3), new Pose(new Vector3F(15, 0, 15))));
            compositeShape.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Pose(new Vector3F(15, 0, 5))));
            ITriangleMesh     mesh      = compositeShape.GetMesh(0.01f, 3);
            TriangleMeshShape meshShape = new TriangleMeshShape(mesh);

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

            AddObject("Mesh", new Pose(new Vector3F(-30, 0, 10)), meshShape, collisionDomain);
        }
コード例 #17
0
        protected override void OnUpdate(TimeSpan deltaTime)
        {
            // Mouse centering (controlled by the MenuComponent) is disabled if the game
            // is inactive or if the GUI is active. In these cases, we do not want to move
            // the player.
            if (!_inputService.EnableMouseCentering)
            {
                return;
            }

            if (_inputService.IsPressed(Keys.Enter, true))
            {
                // Toggle between player camera and spectator view.
                _useSpectatorView = !_useSpectatorView;
            }
            else
            {
                float deltaTimeF = (float)deltaTime.TotalSeconds;

                // Compute new yaw and pitch from mouse movement.
                float deltaYaw = 0;
                deltaYaw -= _inputService.MousePositionDelta.X;
                deltaYaw -= _inputService.GetGamePadState(LogicalPlayerIndex.One).ThumbSticks.Right.X * 10;
                _yaw     += deltaYaw * deltaTimeF * 0.1f;

                float deltaPitch = 0;
                deltaPitch -= _inputService.MousePositionDelta.Y;
                deltaPitch += _inputService.GetGamePadState(LogicalPlayerIndex.One).ThumbSticks.Right.Y * 10;
                _pitch     += deltaPitch * deltaTimeF * 0.1f;

                // Limit the pitch angle to less than +/- 90°.
                float limit = ConstantsF.PiOver2 - 0.01f;
                _pitch = MathHelper.Clamp(_pitch, -limit, limit);
            }

            // Update SceneNode.LastPoseWorld - this is required for some effects, like
            // camera motion blur.
            CameraNode.LastPoseWorld = CameraNode.PoseWorld;

            var vehiclePose = _vehicle.Pose;

            if (_useSpectatorView)
            {
                // Spectator Mode:
                // Camera is looking at the car from a fixed location in the level.
                Vector3F position = new Vector3F(10, 8, 10);
                Vector3F target   = vehiclePose.Position;
                Vector3F up       = Vector3F.UnitY;

                // Set the new camera view matrix. (Setting the View matrix changes the Pose.
                // The pose is simply the inverse of the view matrix).
                CameraNode.View = Matrix44F.CreateLookAt(position, target, up);
            }
            else
            {
                // Player Camera:
                // Camera moves with the car. The look direction can be changed by moving the mouse.
                Matrix33F yaw         = Matrix33F.CreateRotationY(_yaw);
                Matrix33F pitch       = Matrix33F.CreateRotationX(_pitch);
                Matrix33F orientation = vehiclePose.Orientation * yaw * pitch;
                Vector3F  forward     = orientation * -Vector3F.UnitZ;
                Vector3F  up          = Vector3F.UnitY;
                Vector3F  position    = vehiclePose.Position - 10 * forward + 5 * up;
                Vector3F  target      = vehiclePose.Position + 1 * up;

                CameraNode.View = Matrix44F.CreateLookAt(position, target, up);
            }
        }
コード例 #18
0
        public DistortionSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            _graphicsScreen             = new DeferredGraphicsScreen(Services);
            _graphicsScreen.DrawReticle = true;
            GraphicsService.Screens.Insert(0, _graphicsScreen);
            GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

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

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

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

            GameObjectService.Objects.Add(cameraGameObject);
            _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode;

            GameObjectService.Objects.Add(new GrabObject(Services));
            GameObjectService.Objects.Add(new StaticSkyObject(Services)); // Skybox + some lights.

            //GameObjectService.Objects.Add(new GroundObject(Services));
            // Add a ground plane with some detail to see the water refractions.
            Simulation.RigidBodies.Add(new RigidBody(new PlaneShape(new Vector3F(0, 1, 0), 0)));
            GameObjectService.Objects.Add(new StaticObject(Services, "Gravel/Gravel", 1, new Pose(new Vector3F(0, 0.001f, 0))));

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

            // Add a few palm trees.
            Random random = new Random(12345);

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

            // Add DistortionFilter to post-processors.
            _distortionFilter = new DistortionFilter(GraphicsService, ContentManager);
            _graphicsScreen.PostProcessors.Add(_distortionFilter);

            // Add 3 particle systems.
            // The ParticleSystems are added to the IParticleSystemService.
            // The ParticleSystemNodes are added to the Scene of the DistortionFilter - not the usual Scene!
            _fireDistortionParticleSystemNode = new ParticleSystemNode(CreateFireDistortionParticleSystem())
            {
                PoseLocal = new Pose(new Vector3F(0, 0f, -1), Matrix33F.CreateRotationX(ConstantsF.PiOver2)),
            };
            ParticleSystemService.ParticleSystems.Add(_fireDistortionParticleSystemNode.ParticleSystem);
            _distortionFilter.Scene.Children.Add(_fireDistortionParticleSystemNode);

            _explosionDistortionParticleSystemNode = new ParticleSystemNode(CreateExplosionDistortionParticleSystem())
            {
                PoseLocal = new Pose(new Vector3F(0, 0, -1)),
            };
            ParticleSystemService.ParticleSystems.Add(_explosionDistortionParticleSystemNode.ParticleSystem);
            _distortionFilter.Scene.Children.Add(_explosionDistortionParticleSystemNode);

            _novaDistortionParticleSystemNode = new ParticleSystemNode(CreateNovaDistortionParticleSystem())
            {
                PoseLocal = new Pose(new Vector3F(0, 0.5f, -1), Matrix33F.CreateRotationX(ConstantsF.PiOver2)),
            };
            ParticleSystemService.ParticleSystems.Add(_novaDistortionParticleSystemNode.ParticleSystem);
            _distortionFilter.Scene.Children.Add(_novaDistortionParticleSystemNode);
        }
コード例 #19
0
        protected override void OnLoad()
        {
            var contentManager = _services.GetInstance <ContentManager>();

            _lights.Add(new LightNode(new AmbientLight
            {
                Color     = new Vector3F(0.9f, 0.9f, 1f),
                Intensity = 0.05f,
                HemisphericAttenuation = 1,
            })
            {
                Name = "AmbientLight",

                // This ambient light is "infinite", the pose is irrelevant for the lighting. It is only
                // used for the debug rendering below.
                PoseWorld = new Pose(new Vector3F(0, 4, 0)),
            });

            _lights.Add(new LightNode(new DirectionalLight
            {
                Color             = new Vector3F(0.6f, 0.8f, 1f),
                DiffuseIntensity  = 0.1f,
                SpecularIntensity = 0.1f,
            })
            {
                Name      = "DirectionalLightWithShadow",
                Priority  = 10, // This is the most important light.
                PoseWorld = new Pose(new Vector3F(0, 5, 0), Matrix33F.CreateRotationY(-1.4f) * Matrix33F.CreateRotationX(-0.6f)),
                Shadow    = new CascadedShadow
                {
                    PreferredSize     = 1024,
                    DepthBiasScale    = new Vector4F(0.99f),
                    DepthBiasOffset   = new Vector4F(0),
                    FadeOutDistance   = 20,
                    MaxDistance       = 30,
                    MinLightDistance  = 5,
                    ShadowFog         = 0.5f,
                    JitterResolution  = 3000,
                    SplitDistribution = 0.7f
                }
            });

            _lights.Add(new LightNode(new DirectionalLight
            {
                Color             = new Vector3F(0.8f, 0.4f, 0.0f),
                DiffuseIntensity  = 0.1f,
                SpecularIntensity = 0.0f,
            })
            {
                Name      = "DirectionalLight",
                PoseWorld = new Pose(new Vector3F(0, 6, 0), Matrix33F.CreateRotationY(-1.4f) * Matrix33F.CreateRotationX(-0.6f) * Matrix33F.CreateRotationX(ConstantsF.Pi)),
            });

            _lights.Add(new LightNode(new PointLight
            {
                Color             = new Vector3F(0, 1, 0),
                DiffuseIntensity  = 2,
                SpecularIntensity = 2,
                Range             = 3,
                Attenuation       = 1f,
            })
            {
                Name      = "PointLight",
                PoseWorld = new Pose(new Vector3F(-7, 1, 0))
            });

            _lights.Add(new LightNode(new PointLight
            {
                DiffuseIntensity  = 4,
                SpecularIntensity = 4,
                Range             = 3,
                Attenuation       = 1f,
                Texture           = contentManager.Load <TextureCube>("LavaBall/LavaCubeMap"),
            })
            {
                Name      = "PointLightWithTexture",
                PoseWorld = new Pose(new Vector3F(-2, 1, 0))
            });

            _lights.Add(new LightNode(new PointLight
            {
                Color             = new Vector3F(1, 1, 1),
                DiffuseIntensity  = 2,
                SpecularIntensity = 2,
                Range             = 3,
                Attenuation       = 1f,
            })
            {
                Name      = "PointLightWithShadow",
                PoseWorld = new Pose(new Vector3F(2, 1, 0)),
                Shadow    = new CubeMapShadow
                {
                    PreferredSize   = 128,
                    DepthBiasScale  = 0.9f,
                    DepthBiasOffset = -0.01f,
                }
            });

            _lights.Add(new LightNode(new PointLight
            {
                Color             = new Vector3F(1, 1, 1),
                DiffuseIntensity  = 4,
                SpecularIntensity = 4,
                Range             = 3,
                Attenuation       = 1f,
                Texture           = contentManager.Load <TextureCube>("MagicSphere/ColorCube"),
            })
            {
                Name      = "PointLightWithTextureAndShadow",
                PoseWorld = new Pose(new Vector3F(7, 1, 0)),
                Shadow    = new CubeMapShadow
                {
                    PreferredSize   = 128,
                    DepthBiasScale  = 0.9f,
                    DepthBiasOffset = -0.01f,
                }
            });

            _lights.Add(new LightNode(new ProjectorLight
            {
                Texture = contentManager.Load <Texture2D>("TVBox/TestCard"),
            })
            {
                Name      = "ProjectorLight",
                PoseWorld = Pose.FromMatrix(Matrix44F.CreateLookAt(new Vector3F(-1, 1, -6), new Vector3F(-5, 0, -6), new Vector3F(0, 1, 0))).Inverse,
            });

            _lights.Add(new LightNode(new ProjectorLight
            {
                Texture = contentManager.Load <Texture2D>("TVBox/TestCard"),
            })
            {
                Name      = "ProjectorLightWithShadow",
                PoseWorld = Pose.FromMatrix(Matrix44F.CreateLookAt(new Vector3F(5, 1, -6), new Vector3F(1, 0, -6), new Vector3F(0, 1, 0))).Inverse,
                Shadow    = new StandardShadow
                {
                    PreferredSize = 128,
                }
            });

            _lights.Add(new LightNode(new Spotlight
            {
                Color             = new Vector3F(0, 1, 0),
                DiffuseIntensity  = 2,
                SpecularIntensity = 2,
            })
            {
                Name      = "Spotlight",
                PoseWorld = Pose.FromMatrix(Matrix44F.CreateLookAt(new Vector3F(-7, 1, -12), new Vector3F(-10, 0, -12), new Vector3F(0, 1, 0))).Inverse,
            });

            _lights.Add(new LightNode(new Spotlight
            {
                DiffuseIntensity  = 2,
                SpecularIntensity = 2,
                Texture           = contentManager.Load <Texture2D>("TVBox/TestCard"),
            })
            {
                Name      = "SpotlightWithTexture",
                PoseWorld = Pose.FromMatrix(Matrix44F.CreateLookAt(new Vector3F(-1, 1, -12), new Vector3F(-5, 0, -12), new Vector3F(0, 1, 0))).Inverse,
            });

            _lights.Add(new LightNode(new Spotlight
            {
                DiffuseIntensity  = 2,
                SpecularIntensity = 2,
            })
            {
                Name      = "SpotlightWithShadow",
                PoseWorld = Pose.FromMatrix(Matrix44F.CreateLookAt(new Vector3F(5, 1, -12), new Vector3F(1, 0, -12), new Vector3F(0, 1, 0))).Inverse,
                Shadow    = new StandardShadow
                {
                    PreferredSize = 128,
                }
            });

            _lights.Add(new LightNode(new Spotlight
            {
                Color             = new Vector3F(1, 1, 0),
                DiffuseIntensity  = 2,
                SpecularIntensity = 2,
                Texture           = contentManager.Load <Texture2D>("TVBox/TestCard"),
            })
            {
                Name      = "SpotlightWithTextureAndShadow",
                PoseWorld = Pose.FromMatrix(Matrix44F.CreateLookAt(new Vector3F(11, 1, -12), new Vector3F(5, 0, -12), new Vector3F(0, 1, 0))).Inverse,
                Shadow    = new StandardShadow
                {
                    PreferredSize = 128,
                }
            });

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

            _debugRenderer = _services.GetInstance <DebugRenderer>();

            foreach (var lightNode in _lights)
            {
                scene.Children.Add(lightNode);
            }
        }
コード例 #20
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.
        }
コード例 #21
0
        protected override void OnLoad()
        {
            // Add rigid bodies to simulation.
            var simulation = _services.GetInstance <Simulation>();

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

            // ----- Create a height field.
            var numberOfSamplesX = 20;
            var numberOfSamplesZ = 20;
            var samples          = new float[numberOfSamplesX * numberOfSamplesZ];

            for (int z = 0; z < numberOfSamplesZ; z++)
            {
                for (int x = 0; x < numberOfSamplesX; x++)
                {
                    if (x == 0 || z == 0 || x == 19 || z == 19)
                    {
                        samples[z * numberOfSamplesX + x] = -1;
                    }
                    else
                    {
                        samples[z * numberOfSamplesX + x] = 1.0f + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1.0f);
                    }
                }
            }
            HeightField heightField = new HeightField(0, 0, 120, 120, samples, numberOfSamplesX, numberOfSamplesZ);

            //heightField.UseFastCollisionApproximation = true;
            AddBody(simulation, "HeightField", new Pose(new Vector3F(10, 0, 20)), heightField, MotionType.Static);

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

            // ----- Slopes with different tilt angles.
            // Create a loop.
            Vector3F slopePosition = new Vector3F(-20, -0.25f, -5);
            BoxShape slopeShape    = new BoxShape(8, 0.5f, 2);

            for (int i = 1; i < 33; i++)
            {
                Matrix33F oldRotation = Matrix33F.CreateRotationX((i - 1) * MathHelper.ToRadians(10));
                Matrix33F rotation    = Matrix33F.CreateRotationX(i * MathHelper.ToRadians(10));

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

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

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

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

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

            // ----- Create a mesh object.
            // We first build a composite shape out of several primitives and then convert the
            // composite shape to a triangle mesh. (Just for testing.)
            CompositeShape compositeShape = new CompositeShape();

            compositeShape.Children.Add(new GeometricObject(heightField, Pose.Identity));
            compositeShape.Children.Add(new GeometricObject(new CylinderShape(1, 2), new Pose(new Vector3F(10, 1, 10))));
            compositeShape.Children.Add(new GeometricObject(new SphereShape(3), new Pose(new Vector3F(15, 0, 15))));
            compositeShape.Children.Add(new GeometricObject(new BoxShape(1, 2, 3), new Pose(new Vector3F(15, 0, 5))));
            ITriangleMesh     mesh      = compositeShape.GetMesh(0.01f, 3);
            TriangleMeshShape meshShape = new TriangleMeshShape(mesh, true);

            meshShape.Partition = new AabbTree <int>()
            {
                BottomUpBuildThreshold = 0
            };
            AddBody(simulation, "Mesh", new Pose(new Vector3F(-120, 0, 20)), meshShape, MotionType.Static);

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

            seesaw.MassFrame.Mass = 500;
            seesaw.CanSleep       = false;

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


            // ----- Distribute a few dynamic spheres and boxes across the landscape.
            SphereShape sphereShape = new SphereShape(0.5f);

            for (int i = 0; i < 40; i++)
            {
                Vector3F position = RandomHelper.Random.NextVector3F(-60, 60);
                position.Y = 10;
                AddBody(simulation, "Sphere" + i, new Pose(position), sphereShape, MotionType.Dynamic);
            }

            BoxShape boxShape = new BoxShape(1.0f, 1.0f, 1.0f);

            for (int i = 0; i < 40; i++)
            {
                Vector3F position = RandomHelper.Random.NextVector3F(-60, 60);
                position.Y = 1;
                AddBody(simulation, "Box" + i, new Pose(position), boxShape, MotionType.Dynamic);
            }
        }
コード例 #22
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;
            }
        }
コード例 #23
0
        public FigurePickerObject(IGraphicsService graphicsService, Scene scene, CameraObject cameraObject, DebugRenderer debugRenderer)
        {
            _cameraObject  = cameraObject;
            _scene         = scene;
            _debugRenderer = debugRenderer;

            // Create a collision domain which manages all collision objects used for
            // picking: the picking object and the collision objects for figure nodes.
            _collisionDomain = new CollisionDomain(new CollisionDetection());

            // Create the picking object:
            // The picking object represents the mouse cursor or the reticle. Usually
            // a ray is used, but in this example we want to use a cylinder/cone. This
            // allows to check which objects within a certain radius of the reticle. A
            // picking cylinder/cone is helpful for touch devices where the picking is
            // done with an imprecise input method like the human finger.

            // We want to pick objects in 10 pixel radius around the reticle. To determine
            // the world space size of the required cylinder/cone, we can use the projection
            // and the viewport.
            const float pickingRadius = 10;
            var         projection    = _cameraObject.CameraNode.Camera.Projection;
            var         viewport      = graphicsService.GraphicsDevice.Viewport;

            Shape pickingShape;

            if (projection is OrthographicProjection)
            {
                // Use cylinder for orthographic projections:
                // The cylinder is centered at the camera position and reaches from the
                // camera position to the camera far plane. A TransformedShape is used
                // to rotate and translate the cylinder.
                float radius = projection.Width / viewport.Width * pickingRadius;
                pickingShape = new TransformedShape(
                    new GeometricObject(
                        new CylinderShape(radius, projection.Far),
                        new Pose(new Vector3F(0, 0, -projection.Far / 2), Matrix33F.CreateRotationX(ConstantsF.PiOver2))));
            }
            else
            {
                // Use cone for perspective projections:
                // The cone tip is at the camera position and the cone base is at the
                // camera far plane.

                // Compute the radius at the far plane that projects to 10 pixels in screen space.
                float radius = viewport.Unproject(
                    new Vector3(viewport.Width / 2.0f + pickingRadius, viewport.Height / 2.0f, 1),
                    (Matrix)_cameraObject.CameraNode.Camera.Projection.ToMatrix44F(),
                    Matrix.Identity,
                    Matrix.Identity).X;

                // A transformed shape is used to rotate and translate the cone.
                pickingShape = new TransformedShape(
                    new GeometricObject(
                        new ConeShape(radius, projection.Far),
                        new Pose(new Vector3F(0, 0, -projection.Far), Matrix33F.CreateRotationX(ConstantsF.PiOver2))));
            }

            // Create collision object with the picking shape.
            _pickingObject = new CollisionObject(new GeometricObject(pickingShape, _cameraObject.CameraNode.PoseWorld));
        }
コード例 #24
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

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

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

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

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

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

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

            // ----- Create stairs with increasing step height.
            // Each step is a box. With this object we can test if our character can climb up
            // stairs. The character controller has a step height limit. Increasing step heights
            // let us test if the step height limit works.
            float       startHeight = 0;
            const float stepDepth   = 1f;

            for (int i = 0; i < 10; i++)
            {
                float    stepHeight = 0.1f + i * 0.05f;
                Vector3F position   = new Vector3F(0, startHeight + stepHeight / 2, -2 - i * stepDepth);
                AddBody(simulation, "Step" + i, new Pose(position), new BoxShape(2, stepHeight, stepDepth), MotionType.Static);

                startHeight += stepHeight;
            }

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

            // ----- Create a height field.
            // Terrain that is uneven is best modeled with a height field. Height fields are faster
            // than general triangle meshes.
            // The height direction is the y direction.
            // The height field lies in the x/z plane.
            var numberOfSamplesX = 20;
            var numberOfSamplesZ = 20;
            var samples          = new float[numberOfSamplesX * numberOfSamplesZ];

            // Create arbitrary height values.
            for (int z = 0; z < numberOfSamplesZ; z++)
            {
                for (int x = 0; x < numberOfSamplesX; x++)
                {
                    if (x == 0 || z == 0 || x == 19 || z == 19)
                    {
                        // Set this boundary elements to a low height, so that the height field is connected
                        // to the ground.
                        samples[z * numberOfSamplesX + x] = -1;
                    }
                    else
                    {
                        // A sine/cosine function that creates some interesting waves.
                        samples[z * numberOfSamplesX + x] = 1.0f + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1.0f);
                    }
                }
            }
            var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ);

            AddBody(simulation, "HeightField", new Pose(new Vector3F(10, 0, 10)), heightField, MotionType.Static);

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

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

            // Create slopes with increasing tilt angles.
            // The character controller has a slope limit. Only flat slopes should be climbable.
            // Movement between slopes should be smooth.
            Vector3F slopePosition = new Vector3F(-17, -0.25f, 6);
            BoxShape slopeShape    = new BoxShape(8, 0.5f, 5);

            for (int i = 1; i < 8; i++)
            {
                Matrix33F oldRotation = Matrix33F.CreateRotationX((i - 1) * MathHelper.ToRadians(10));
                Matrix33F rotation    = Matrix33F.CreateRotationX(i * MathHelper.ToRadians(10));

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

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

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

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

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

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

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

            ladder.CollisionObject.Type = CollisionObjectType.Trigger;

            // ----- Create a mesh object to test walking on triangle meshes.
            // Normally, the mesh would be loaded from a file. Here, we make a composite shape and
            // let DigitalRune Geometry compute a mesh for it. Then we throw away the composite
            // shape and use only the mesh. (We do this to test triangle meshes. Using the composite
            // shape instead of the triangle mesh would be a lot faster.)
            CompositeShape compositeShape = new CompositeShape();

            compositeShape.Children.Add(new GeometricObject(heightField, Pose.Identity));
            compositeShape.Children.Add(new GeometricObject(new CylinderShape(1, 2), new Pose(new Vector3F(10, 1, 10))));
            compositeShape.Children.Add(new GeometricObject(new SphereShape(3), new Pose(new Vector3F(15, 0, 15))));
            compositeShape.Children.Add(new GeometricObject(new BoxShape(4, 4, 3), new Pose(new Vector3F(15, 1.5f, 5))));
            compositeShape.Children.Add(new GeometricObject(new BoxShape(4, 4, 3), new Pose(new Vector3F(15, 1.5f, 0))));
            ITriangleMesh     mesh      = compositeShape.GetMesh(0.01f, 3);
            TriangleMeshShape meshShape = new TriangleMeshShape(mesh);

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

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

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

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

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

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

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

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

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

            conveyorBelt.Material = materialWithSurfaceMotion;

            // ----- Distribute a few dynamic spheres and boxes across the landscape.
            SphereShape sphereShape = new SphereShape(0.5f);

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

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

            BoxShape boxShape = new BoxShape(1, 1, 1);

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

                AddBody(simulation, "Box" + i, new Pose(position), boxShape, MotionType.Dynamic);
            }
        }
コード例 #25
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);
        }
コード例 #26
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
        }
コード例 #27
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
        }
コード例 #28
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);
        }
コード例 #29
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);
        }
コード例 #30
0
        public FacialAnimationSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            _graphicsScreen = new DeferredGraphicsScreen(Services)
            {
                DrawReticle = false
            };
            GraphicsService.Screens.Insert(0, _graphicsScreen);
            Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer);
            Services.Register(typeof(IScene), null, _graphicsScreen.Scene);

            // Add a game object which adds some GUI controls for the deferred graphics
            // screen to the Options window.
            GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

            // Use a fixed camera.
            var projection = new PerspectiveProjection();

            projection.SetFieldOfView(
                ConstantsF.PiOver4,
                GraphicsService.GraphicsDevice.Viewport.AspectRatio,
                0.1f,
                10);
            var cameraNode = new CameraNode(new Camera(projection));

            cameraNode.LookAt(new Vector3F(0.15f, 0.15f, 0.5f), new Vector3F(0.1f, 0.15f, 0), Vector3F.Up);
            _graphicsScreen.Scene.Children.Add(cameraNode);
            _graphicsScreen.ActiveCameraNode = cameraNode;

            // Lighting setup:
            var keyLight = new LightNode(new Spotlight {
                DiffuseIntensity = 0.6f, SpecularIntensity = 0.4f
            });

            keyLight.LookAt(new Vector3F(-2, 2, 2), new Vector3F(), Vector3F.Up);
            _graphicsScreen.Scene.Children.Add(keyLight);

            var backLight = new LightNode(new Spotlight {
                DiffuseIntensity = 0.3f, SpecularIntensity = 0.3f
            });

            backLight.LookAt(new Vector3F(1, 0.5f, -2), new Vector3F(), Vector3F.Up);
            _graphicsScreen.Scene.Children.Add(backLight);

            var fillLight = new LightNode(new AmbientLight {
                HemisphericAttenuation = 1, Intensity = 0.1f
            });

            _graphicsScreen.Scene.Children.Add(fillLight);

            // The scene does not have a proper background. That's why the exposure is a
            // bit off. --> Reduce the max exposure.
            var hdrFilter = _graphicsScreen.PostProcessors.OfType <HdrFilter>().First();

            hdrFilter.MaxExposure = 6;

            // Load the customized "Sintel" model (original: Durian Open Movie Project - http://www.sintel.org/).
            var model = ContentManager.Load <ModelNode>("Sintel/Sintel-Head").Clone();

            model.PoseWorld = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(MathHelper.ToRadians(10)) * Matrix33F.CreateRotationX(-MathHelper.ToRadians(90)));
            _graphicsScreen.Scene.Children.Add(model);

            // The model consists of a root node and a mesh node.
            //  ModelNode "Sintel-Head"
            //    MeshNode "Sintel"
            _sintel = (MeshNode)model.Children[0];

            // The model contains two skeletal animations:
            // - "MOUTH-open" is just a single frame.
            // - "Test" is a short animation (250 frames).

            // In the Options window, we will add a slider to move the jaw.
            // Slider.Value = 0 ... mouth closed (default)
            _mouthClosedPose = SkeletonPose.Create(_sintel.Mesh.Skeleton);
            // Slider.Value = 1 ... mouth open (copied from the "MOUTH-open" animation)
            SkeletonKeyFrameAnimation mouthOpen = _sintel.Mesh.Animations["MOUTH-open"];

            _mouthOpenPose = SkeletonPose.Create(_sintel.Mesh.Skeleton);
            mouthOpen.GetValue(TimeSpan.Zero, ref _mouthOpenPose, ref _mouthOpenPose, ref _mouthOpenPose);

            // Turn the "Test" animation into an endless loop.
            _skeletalAnimation = new AnimationClip <SkeletonPose>(_sintel.Mesh.Animations["Test"])
            {
                Duration     = TimeSpan.MaxValue,
                LoopBehavior = LoopBehavior.Cycle
            };

            // Mesh has several morph targets for facial animation, which are imported
            // automatically via the content pipeline. Unfortunately, the XNA content
            // pipeline cannot import morph target animations automatically.
            // In this demo, we will create a morph target animation in code.
            _morphingAnimation = CreateMorphingAnimation();

            CreateGuiControls();
        }