예제 #1
0
        protected override void OnUpdate(TimeSpan deltaTime)
        {
            // A random new wind change is chosen at regular intervals.
            const float WindInterval = 3;

            _timeSinceWindChange += (float)deltaTime.TotalSeconds;
            if (_timeSinceWindChange > WindInterval)
            {
                _lastAngle           = _nextAngle;
                _lastSpeed           = _nextSpeed;
                _timeSinceWindChange = 0;

                // Get random target angle.
                float a = RandomHelper.Random.NextFloat(-1, 1);
                // Apply non-linear curve to make smaller changes more likely.
                a = (float)Math.Pow(a, 3);
                // Convert to angle and limit variation.
                _nextAngle = _lastAngle + ConstantsF.PiOver2 * a * DirectionVariation;

                // Get random target speed.
                float s = RandomHelper.Random.NextFloat(0, 1);
                _nextSpeed = MaxSpeed * (1 - s * SpeedVariation);
            }

            // Update current wind.
            float p     = _timeSinceWindChange / WindInterval;
            float speed = InterpolationHelper.Lerp(_lastSpeed, _nextSpeed, p);
            float angle = InterpolationHelper.Lerp(_lastAngle, _nextAngle, p);

            Wind = speed * Matrix33F.CreateRotationY(angle) * Vector3F.UnitX;
        }
예제 #2
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);
            }
        }
        public SkeletonMappingSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            // Get dude model and start animation on the dude.
            var modelNode = ContentManager.Load <ModelNode>("Dude/Dude");

            _dudeMeshNode           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _dudeMeshNode.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(_dudeMeshNode);
            GraphicsScreen.Scene.Children.Add(_dudeMeshNode);

            var animations       = _dudeMeshNode.Mesh.Animations;
            var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First())
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_dudeMeshNode.SkeletonPose);

            // Get marine model - do not start any animations on the marine model.
            modelNode                 = ContentManager.Load <ModelNode>("Marine/PlayerMarine");
            _marineMeshNode           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _marineMeshNode.PoseLocal = new Pose(new Vector3F(0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(_marineMeshNode);
            GraphicsScreen.Scene.Children.Add(_marineMeshNode);

            CreateSkeletonMapper();
        }
예제 #4
0
        public BoneJiggleSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            var modelNode = ContentManager.Load <ModelNode>("Dude/Dude");

            _meshNode           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(_meshNode);
            GraphicsScreen.Scene.Children.Add(_meshNode);

            var animations    = _meshNode.Mesh.Animations;
            var walkAnimation = new AnimationClip <SkeletonPose>(animations.Values.First())
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            _walkAnimationController = AnimationService.StartAnimation(walkAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
            _walkAnimationController.AutoRecycle();

            // Create a BoneJiggler instance for the head bone (bone index 7).
            _boneJiggler = new BoneJiggler(_meshNode.SkeletonPose, 7, new Vector3F(1.1f, 0, 0))
            {
                Spring  = 100,
                Damping = 3,
            };
        }
예제 #5
0
        public SkinnedEffectSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            GraphicsScreen.ClearBackground = true;
            GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
            SetCamera(new Vector3F(1, 1, 3), 0.2f, 0);

            // Create a sky mesh and add an instance of this mesh to the scene.
            var skyMesh = ProceduralSkyDome.CreateMesh(GraphicsService, ContentManager.Load <Texture2D>("sky"));

            _sky      = new MeshNode(skyMesh);
            _sky.Name = "Sky"; // Always set a name - very useful for debugging!
            GraphicsScreen.Scene.Children.Add(_sky);

            // Load the skinned model. This model is processed using the DigitalRune Model
            // Processor - not the default XNA model processor!
            // In the folder that contains dude.fbx, there are several XML files (*.drmdl and *.drmat)
            // which define the materials of the model. These material description files are
            // automatically processed by the DigitalRune Model Processor. Please browse
            // to the content folder and have a look at the *.drmdl and *.drmat files.
            var dudeModel = ContentManager.Load <ModelNode>("Dude/Dude");

            dudeModel           = dudeModel.Clone();
            dudeModel.PoseWorld = new Pose(Matrix33F.CreateRotationY(ConstantsF.Pi));
            GraphicsScreen.Scene.Children.Add(dudeModel);

            // The dude model consists of a single mesh.
            var dudeMeshNode = dudeModel.GetSubtree().OfType <MeshNode>().First();
            var mesh         = dudeMeshNode.Mesh;

            /*
             * // The dude mesh consists of different materials (head, eyes, torso, ...).
             * // We could change some of the material properties...
             * foreach (var material in mesh.Materials)
             * {
             *  // Get all SkinnedEffectBindings which wrap the XNA SkinnedEffect.
             *  // A material can consist of several effects - one effect for each render pass.
             *  // (Per default there is only one render pass called "Default".)
             *  foreach (var effectBinding in material.EffectBindings.OfType<SkinnedEffectBinding>())
             *  {
             *    // We could change effect parameters here, for example:
             *    effectBinding.PreferPerPixelLighting = true;
             *  }
             * }
             */

            // The DigitalRune Model Processor also loads animations.
            // Start the first animation of the dude and let it loop forever.
            // (We keep the animation controller to be able to stop the animation in
            // Dispose() below.)
            var timeline = new TimelineClip(mesh.Animations.Values.First())
            {
                Duration     = TimeSpan.MaxValue,
                LoopBehavior = LoopBehavior.Cycle,
            };

            _animationController = AnimationService.StartAnimation(timeline, (IAnimatableProperty)dudeMeshNode.SkeletonPose);
        }
예제 #6
0
        public SkySample(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 GroundObject(Services));
            GameObjectService.Objects.Add(new DudeObject(Services));
            GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
            GameObjectService.Objects.Add(new LavaBallsObject(Services));
            GameObjectService.Objects.Add(new FogObject(Services));
            GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Barrier", 0.9f, new Pose(new Vector3F(0, 0, -2))));
            GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Cylinder", 0.9f, new Pose(new Vector3F(3, 0, 0), QuaternionF.CreateRotationY(MathHelper.ToRadians(-20)))));

            // The DynamicSkyObject creates the dynamic sky and lights.
            GameObjectService.Objects.Add(new DynamicSkyObject(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 a grain filter to add some noise in the night.
            _graphicsScreen.PostProcessors.Add(new GrainFilter(GraphicsService)
            {
                IsAnimated         = true,
                LuminanceThreshold = 0.3f,
                ScaleWithLuminance = true,
                Strength           = 0.04f,
                GrainScale         = 1.5f,
            });
        }
예제 #7
0
        public SplitScreenSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            _graphicsScreen             = new SplitScreen(Services);
            _graphicsScreen.DrawReticle = true;
            GraphicsService.Screens.Insert(0, _graphicsScreen);

            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 of player A.
            var cameraGameObject = new CameraObject(Services);

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

            var projection = (PerspectiveProjection)cameraGameObject.CameraNode.Camera.Projection;

            projection.SetFieldOfView(
                projection.FieldOfViewY,
                GraphicsService.GraphicsDevice.Viewport.AspectRatio / 2,
                projection.Near,
                projection.Far);
            cameraGameObject.CameraNode.Camera = new Camera(projection);

            // A second camera for player B.
            _cameraNodeB = new CameraNode(cameraGameObject.CameraNode.Camera);
            _graphicsScreen.ActiveCameraNodeB = _cameraNodeB;

            GameObjectService.Objects.Add(new GrabObject(Services));
            GameObjectService.Objects.Add(new GroundObject(Services));
            GameObjectService.Objects.Add(new DudeObject(Services));
            GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
            GameObjectService.Objects.Add(new LavaBallsObject(Services));
            GameObjectService.Objects.Add(new FogObject(Services));
            GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Barrier", 0.9f, new Pose(new Vector3F(0, 0, -2))));
            GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Cylinder", 0.9f, new Pose(new Vector3F(3, 0, 0), QuaternionF.CreateRotationY(MathHelper.ToRadians(-20)))));
            GameObjectService.Objects.Add(new StaticSkyObject(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)));
            }

            GameObjectService.Objects.Add(new OptionsObject(Services));
        }
예제 #8
0
        public WaterFallSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            _particleSystem      = WaterFall.CreateWaterFall(ContentManager);
            _particleSystem.Pose = new Pose(new Vector3F(0, 2, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            ParticleSystemService.ParticleSystems.Add(_particleSystem);

            _particleSystemNode = new ParticleSystemNode(_particleSystem);
            GraphicsScreen.Scene.Children.Add(_particleSystemNode);
        }
예제 #9
0
        public FlameJetSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            _flameJet      = FlameJet.Create(ContentManager);
            _flameJet.Pose = new Pose(new Vector3F(0, 2, 0), Matrix33F.CreateRotationY(ConstantsF.PiOver2));
            ParticleSystemService.ParticleSystems.Add(_flameJet);

            _particleSystemNode = new ParticleSystemNode(_flameJet);
            GraphicsScreen.Scene.Children.Add(_particleSystemNode);
        }
예제 #10
0
        public CollisionDetectionOnlyRagdollSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            GraphicsScreen.DrawReticle = true;
            SetCamera(new Vector3F(0, 1, 6), 0, 0);

            // Add a game object which allows to shoot balls.
            _ballShooterObject = new BallShooterObject(Services);
            GameObjectService.Objects.Add(_ballShooterObject);

            var modelNode = ContentManager.Load <ModelNode>("Dude/Dude");

            _meshNode           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(_meshNode);
            GraphicsScreen.Scene.Children.Add(_meshNode);

            var animations       = _meshNode.Mesh.Animations;
            var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First())
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);

            // Create a ragdoll for the Dude model.
            _ragdoll = new Ragdoll();
            DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

            // Set the world space pose of the whole ragdoll.
            _ragdoll.Pose = _meshNode.PoseWorld;
            // And copy the bone poses of the current skeleton pose.
            _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

            foreach (var body in _ragdoll.Bodies)
            {
                if (body != null)
                {
                    // Set all bodies to kinematic - they should not be affected by forces.
                    body.MotionType = MotionType.Kinematic;

                    // Disable collision response.
                    body.CollisionResponseEnabled = false;
                }
            }

            // In this sample, we do not need joints, limits or motors.
            _ragdoll.DisableJoints();
            _ragdoll.DisableLimits();
            _ragdoll.DisableMotors();

            // Add ragdoll rigid bodies to the simulation.
            _ragdoll.AddToSimulation(Simulation);
        }
예제 #11
0
        public override void Update(GameTime gameTime)
        {
            // This sample clears the debug renderer each frame.
            _graphicsScreen.DebugRenderer.Clear();

            // A second camera for player B.
            var totalTime = (float)gameTime.TotalGameTime.TotalSeconds;
            var position  = Matrix33F.CreateRotationY(totalTime * 0.1f) * new Vector3F(4, 2, 4);

            _cameraNodeB.View = Matrix44F.CreateLookAt(position, new Vector3F(0, 0, 0), new Vector3F(0, 1, 0));
        }
예제 #12
0
        public void CreateRotationY()
        {
            float     angle = (float)MathHelper.ToRadians(30);
            Matrix33F m     = Matrix33F.CreateRotationY(angle);

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

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

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

            Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.CreateRotation(Vector3F.UnitY, angle), m));
        }
예제 #13
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);
        }
예제 #14
0
        protected override void OnUpdate(TimeSpan deltaTime)
        {
            // Rotate camera around origin.
            _cameraRotation += 0.1f * (float)deltaTime.TotalSeconds;
            var cameraPosition = Matrix33F.CreateRotationY(_cameraRotation) * new Vector3F(10, 5, 10);
            var targetPosition = new Vector3F(0, 1, 0);
            var up             = new Vector3F(0, 1, 0);
            var viewMatrix     = Matrix44F.CreateLookAt(cameraPosition, targetPosition, up);

            CameraNode.PoseWorld = Pose.FromMatrix(viewMatrix.Inverse);

            Scene.Update(deltaTime);
        }
예제 #15
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;
            }

            float deltaTimeF = (float)deltaTime.TotalSeconds;

            // Update steering direction from left/right arrow keys.
            UpdateSteeringAngle(deltaTimeF);

            // Update acceleration from up/down arrow keys.
            UpdateAcceleration(deltaTimeF);

            // Pressing <Space> activates handbrake
            if (_inputService.IsDown(Keys.Space) || _inputService.IsDown(Buttons.A, LogicalPlayerIndex.One))
            {
                // Braking force from handbrake needs to be applied to back wheels.
                const float brakeForce = 6000;
                Vehicle.Wheels[2].MotorForce = 0;
                Vehicle.Wheels[3].MotorForce = 0;
                Vehicle.Wheels[2].BrakeForce = brakeForce;
                Vehicle.Wheels[3].BrakeForce = brakeForce;
            }
            else
            {
                Vehicle.Wheels[2].BrakeForce = 0;
                Vehicle.Wheels[3].BrakeForce = 0;
            }

            // Update poses of graphics models.
            // Update SceneNode.LastPoseWorld (required for optional effects, like motion blur).
            _vehicleModelNode.SetLastPose(true);
            _vehicleModelNode.PoseWorld = Vehicle.Chassis.Pose;
            for (int i = 0; i < _wheelModelNodes.Length; i++)
            {
                var pose = Vehicle.Wheels[i].Pose;
                if (Vehicle.Wheels[i].Offset.X < 0)
                {
                    // Left wheel.
                    pose.Orientation = pose.Orientation * Matrix33F.CreateRotationY(ConstantsF.Pi);
                }
                _wheelModelNodes[i].SetLastPose(true);
                _wheelModelNodes[i].PoseWorld = pose;
            }
        }
        /// <summary>
        /// Adds test objects (walls, palm trees, ...) to the scene.
        /// </summary>
        private void AddTestObjects()
        {
            // Add a few palm trees.
            Random random = new Random(12345);

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

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

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

            // Create a ceiling using a rotated wall.
            GameObjectService.Objects.Add(
                new StaticObject(
                    Services,
                    "Building/wall_brick_1",
                    new Vector3F(1.8f, 2.8f, 1),
                    _globalRotation * new Pose(new Vector3F(0.3f, 4, -4), Matrix33F.CreateRotationZ(ConstantsF.PiOver2) * Matrix33F.CreateRotationY(ConstantsF.PiOver2)),
                    true,
                    false));
        }
예제 #17
0
        public override void Update(GameTime gameTime)
        {
            // Move models in circles.
            _angle += (float)gameTime.ElapsedGameTime.TotalSeconds * 0.6f;

            // Set SceneNode.LastPoseWorld to the current pose. This is only required
            // when advanced effects are used, like post-process motion blur. Since this
            // is not the case in this sample, we could skip this step. However, it is a
            // good practice to always update SceneNode.LastPoseWorld and LastScaleWorld
            // before the pose or scale is changed.
            _model0.SetLastPose(true);
            _model1.SetLastPose(true);

            // Update the position and orientation of the models.
            _model0.PoseWorld = new Pose(new Vector3F(2, 0, 0))
                                * new Pose(Matrix33F.CreateRotationY(_angle))
                                * new Pose(new Vector3F(2, 0, 0));
            _model1.PoseWorld = new Pose(new Vector3F(-2, 0, 0))
                                * new Pose(Matrix33F.CreateRotationY(-_angle + 0.5f))
                                * new Pose(new Vector3F(-2, 0, 0));

            // Draw the bounding shapes of the meshes.
            //
            // Note - Bounding shapes of skinned models:
            // The model description file (dude.drmdl) specifies a custom bounding shape
            // (see the attributes AabbMinimum and AabbMaximum in this file). For
            // skinned models this bounding shape must be chosen manually. It must be big
            // enough to contain all poses of the model. - In future DigitalRune Graphics
            // versions we will automatically compute suitable bounding shapes for
            // animated models.
            _debugRenderer.Clear();
            foreach (var sceneNode in _scene.GetSubtree().OfType <MeshNode>())
            {
                _debugRenderer.DrawObject(sceneNode, Color.Orange, true, false);
            }

            // Draw a coordinate cross at the world space origin.
            _debugRenderer.DrawAxes(Pose.Identity, 1, false);

            // Update the scene - this must be called once per frame.
            // The scene will compute internal collision information for camera frustum
            // culling or light culling (which lights overlap with which mesh nodes).
            _scene.Update(gameTime.ElapsedGameTime);

            base.Update(gameTime);
        }
예제 #18
0
        public DudeWalkingSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            var modelNode = ContentManager.Load <ModelNode>("Dude/Dude");
            var meshNode  = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();

            meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(meshNode);
            GraphicsScreen.Scene.Children.Add(meshNode);

            // The imported animations are stored in the mesh.
            Dictionary <string, SkeletonKeyFrameAnimation> animations = meshNode.Mesh.Animations;

            // The Dude model contains only one animation, which is a SkeletonKeyFrameAnimation with
            // a walk cycle.
            SkeletonKeyFrameAnimation walkAnimation = animations.Values.First();

            // Wrap the walk animation in an animation clip that loops the animation forever.
            AnimationClip <SkeletonPose> loopingAnimation = new AnimationClip <SkeletonPose>(walkAnimation)
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };

            // Start the animation and keep the created AnimationController.
            // We must cast the SkeletonPose to IAnimatableProperty because SkeletonPose implements
            // IAnimatableObject and IAnimatableProperty. We must tell the AnimationService if we want
            // to animate an animatable property of the SkeletonPose (IAnimatableObject), or if we want to
            // animate the whole SkeletonPose (IAnimatableProperty).
            _animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)meshNode.SkeletonPose);

            // The animation will be applied the next time AnimationManager.ApplyAnimations() is called
            // in the main loop. ApplyAnimations() is called before this method is called, therefore
            // the model will be rendered in the bind pose in this frame and in the first animation key
            // frame in the next frame - this creates an annoying visual popping effect.
            // We can avoid this if we call AnimationController.UpdateAndApply(). This will immediately
            // change the model pose to the first key frame pose.
            _animationController.UpdateAndApply();

            // (Optional) Enable Auto-Recycling:
            // After the animation is stopped, the animation service will recycle all
            // intermediate data structures.
            _animationController.AutoRecycle();
        }
        public AutoRagdollShapesSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            var modelNode = ContentManager.Load <ModelNode>("Dude/Dude");

            _meshNode           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            SampleHelper.EnablePerPixelLighting(_meshNode);
            GraphicsScreen.Scene.Children.Add(_meshNode);

            var animations       = _meshNode.Mesh.Animations;
            var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First())
            {
                LoopBehavior = LoopBehavior.Cycle,
                Duration     = TimeSpan.MaxValue,
            };
            var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);

            animationController.AutoRecycle();
            animationController.UpdateAndApply();

            // Create a ragdoll for the Dude model.
            _ragdoll = CreateRagdoll(_meshNode);

            // Set the world space pose of the whole ragdoll.
            _ragdoll.Pose = _meshNode.PoseWorld;
            // And copy the bone poses of the current skeleton pose.
            _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

            foreach (var body in _ragdoll.Bodies)
            {
                if (body != null)
                {
                    // Set all bodies to kinematic - they should not be affected by forces.
                    body.MotionType = MotionType.Kinematic;

                    // Disable collision response.
                    body.CollisionResponseEnabled = false;
                }
            }

            // Add ragdoll rigid bodies to the simulation.
            _ragdoll.AddToSimulation(Simulation);
        }
예제 #20
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;
        }
예제 #21
0
        public CompressionSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            var modelNode = ContentManager.Load <ModelNode>("Dude/Dude");

            SampleHelper.EnablePerPixelLighting(modelNode);

            _meshNodeUncompressed           = modelNode.GetSubtree().OfType <MeshNode>().First().Clone();
            _meshNodeUncompressed.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            GraphicsScreen.Scene.Children.Add(_meshNodeUncompressed);

            _meshNodeCompressed           = _meshNodeUncompressed.Clone();
            _meshNodeCompressed.PoseLocal = new Pose(new Vector3F(0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
            GraphicsScreen.Scene.Children.Add(_meshNodeCompressed);

            Dictionary <string, SkeletonKeyFrameAnimation> animations = _meshNodeUncompressed.Mesh.Animations;

            _animation = animations.Values.First();

            RestartAnimations();
        }
 public override void Update(GameTime gameTime)
 {
     if (_avatarPose == null)
     {
         if (_avatarRenderer.State == AvatarRendererState.Ready)
         {
             _avatarPose = new AvatarPose(_avatarRenderer);
             AnimationService.StartAnimation(_walkAnimation, _avatarPose).AutoRecycle();
         }
     }
     else
     {
         // Update pose of attached baseball bat.
         // The offset of the baseball bat origin to the bone origin (in bone space)
         Pose offset = new Pose(new Vector3F(0.01f, 0.05f, 0.0f), Matrix33F.CreateRotationY(MathHelper.ToRadians(-20)));
         // The bone position in model space
         SrtTransform bonePose = _avatarPose.SkeletonPose.GetBonePoseAbsolute((int)AvatarBone.SpecialRight);
         // The baseball bat matrix in world space
         _baseballBatMeshNode.PoseWorld = _pose * (Pose)bonePose * offset;
     }
 }
예제 #23
0
        protected override void OnLoad()
        {
            var contentManager = _services.GetInstance <ContentManager>();

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

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

            // We do not want to change the shared Saucer instance in the content manager.
            // Let's create a clone. But we do not want to clone the shape in the UserData,
            // this would be a waste of time and memory.
            originalModelNode.UserData = null;
            _modelNode = originalModelNode.Clone(); // Clone without UserData.
            originalModelNode.UserData = shape;

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

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

            scene.Children.Add(_modelNode);

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

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

            var collisionDomain = _services.GetInstance <CollisionDomain>();

            collisionDomain.CollisionObjects.Add(_collisionObject);
        }
예제 #24
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));
        }
예제 #25
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;
        }
예제 #26
0
        protected override void OnLoad()
        {
            var contentManager = _services.GetInstance <ContentManager>();

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

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

            scene.Children.Add(_modelNode);

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

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

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

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

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

            // Add the collision object to the collision domain of the game.
            var collisionDomain = _services.GetInstance <CollisionDomain>();

            collisionDomain.CollisionObjects.Add(_collisionObject);
        }
예제 #27
0
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            var debugRenderer = GraphicsScreen.DebugRenderer;

            debugRenderer.Clear();

            // <Space> --> Reset skeleton pose to bind pose.
            if (InputService.IsDown(Keys.Space))
            {
                _meshNode.SkeletonPose.ResetBoneTransforms();
            }

            // ----- Detect collisions
            // Get all contact sets of the head.
            RigidBody headBody     = _ragdoll.Bodies[7];
            var       headContacts = Simulation.CollisionDomain.GetContacts(headBody.CollisionObject);

            GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
            foreach (var contactSet in headContacts)
            {
                // Get the rigid body that collided with the head.
                RigidBody otherBody;
                if (contactSet.ObjectA.GeometricObject == headBody)
                {
                    otherBody = contactSet.ObjectB.GeometricObject as RigidBody;
                }
                else
                {
                    otherBody = contactSet.ObjectA.GeometricObject as RigidBody;
                }

                // If the head collided with a ball (from the BallShooter.cs), then set the hit flag.
                if (otherBody != null && otherBody.Name.StartsWith("Ball"))
                {
                    debugRenderer.DrawText("\n\nHIT DETECTED!!!");
                    GraphicsScreen.BackgroundColor = Color.DarkRed;
                    break;
                }
            }

            // Move model in a circle.
            var rotation = Matrix33F.CreateRotationY((float)gameTime.TotalGameTime.TotalSeconds * 0.3f);

            _meshNode.PoseWorld = new Pose(rotation * new Vector3F(3, 0, 0), rotation);

            // Sync pose with ragdoll.
            _ragdoll.Pose = _meshNode.PoseWorld;

            // Update the bodies to match the current skeleton pose.
            // This method changes the body poses directly.
            _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

            // Use DebugRenderer to visualize rigid bodies.
            foreach (var body in Simulation.RigidBodies)
            {
                if (body.Name.StartsWith("Ball"))
                {
                    debugRenderer.DrawObject(body, Color.Gray, false, false);
                }
                else
                {
                    debugRenderer.DrawObject(body, Color.Gray, true, false);
                }
            }
        }
예제 #28
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
        }
        //--------------------------------------------------------------
        #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);
            }
        }
예제 #30
0
        public RefractionSample(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 GroundObject(Services));
            var lavaBallsObject = new LavaBallsObject(Services);

            GameObjectService.Objects.Add(lavaBallsObject);
            GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
            GameObjectService.Objects.Add(new FogObject(Services));
            GameObjectService.Objects.Add(new StaticSkyObject(Services));
            GameObjectService.Objects.Add(new CampfireObject(Services));
            for (int i = 0; i < 10; i++)
            {
                GameObjectService.Objects.Add(new DynamicObject(Services, 1));
                GameObjectService.Objects.Add(new DynamicObject(Services, 2));
                GameObjectService.Objects.Add(new DynamicObject(Services, 3));
            }

            // 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 a few dudes which use the refraction effect.
            for (int i = 0; i < 5; i++)
            {
                Vector3F  position    = new Vector3F(random.NextFloat(-4, 4), 0, random.NextFloat(2, -5));
                Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
                var       dudeObject  = new DudeObject(Services, "DudeRefracted/Dude")
                {
                    Pose = new Pose(position, orientation)
                };
                GameObjectService.Objects.Add(dudeObject);
                //dudeObject.AnimationController.Pause();
            }

            // The DeferredGraphicsScreen has a SceneRenderer, which contains all
            // renderers necessary to render transparent objects (e.g. BillboardRenderer
            // for particles, MeshRenderer for meshes, etc.).
            // We remove the MeshRenderer and add our own RefractionMeshRenderer instead.
            var meshRenderer = _graphicsScreen.AlphaBlendSceneRenderer.Renderers.OfType <MeshRenderer>().First();

            _graphicsScreen.AlphaBlendSceneRenderer.Renderers.Remove(meshRenderer);
            _graphicsScreen.AlphaBlendSceneRenderer.Renderers.Add(new RefractionMeshRenderer(GraphicsService));
        }