Exemplo n.º 1
0
        private void Render(RenderContext context)
        {
            // Set the current camera node in the render context. This info is used
            // by the renderers.
            context.CameraNode = _cameraObject.CameraNode;

            var device = context.GraphicsService.GraphicsDevice;

            device.Clear(Color.CornflowerBlue);

            device.DepthStencilState = DepthStencilState.Default;
            device.RasterizerState   = RasterizerState.CullCounterClockwise;
            device.BlendState        = BlendState.Opaque;

            // Render the meshes one by one (The next sample, SceneSample, shows how to
            // do this more efficiently.)
            // We have to select a render pass. This info is needed by the MeshRenderer
            // to decide which shaders must be used.
            context.RenderPass = "******";
            foreach (var meshNode in _model.GetSubtree().OfType <MeshNode>())
            {
                _meshRenderer.Render(meshNode, context);
            }

            _debugRenderer.Render(context);

            // Clean up.
            context.RenderPass = null;
            context.CameraNode = null;
        }
Exemplo n.º 2
0
        public ManualMeshRenderSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService)
            {
                RenderCallback = Render,
            };

            GraphicsService.Screens.Insert(0, delegateGraphicsScreen);

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

            _scene = new Scene();
            SceneSample.InitializeDefaultXnaLights(_scene);

            // For advanced users: Set this flag if you want to analyze the imported opaque data of
            // effect bindings.
            EffectBinding.KeepOpaqueData = true;

            _model = ContentManager.Load <ModelNode>("Dude/Dude").Clone();
            var meshNode = _model.GetSubtree().OfType <MeshNode>().First();

            meshNode.ScaleLocal = new Vector3(1, 2, 1);
            var mesh     = meshNode.Mesh;
            var timeline = new TimelineClip(mesh.Animations.Values.First())
            {
                Duration     = TimeSpan.MaxValue,
                LoopBehavior = LoopBehavior.Cycle,
            };

            AnimationService.StartAnimation(timeline, (IAnimatableProperty)meshNode.SkeletonPose);
        }
Exemplo n.º 3
0
        // OnLoad() is called when the GameObject is added to the IGameObjectService.
        protected override void OnLoad()
        {
            // Load model.
            var contentManager = _services.GetInstance <ContentManager>();

            _modelNode = contentManager.Load <ModelNode>(_assetName).Clone();

            // Optional: Create rigid body using the triangle mesh of the model.
            if (_addRigidBody)
            {
                CreateRigidBody();
            }

            _modelNode.ScaleLocal = _scale;
            _modelNode.PoseLocal  = _pose;

            foreach (var node in _modelNode.GetSubtree())
            {
                node.CastsShadows = _castsShadows;

                // If models will never move, set the IsStatic flag. This gives the engine
                // more room for optimizations. Additionally, some effects, like certain
                // decals, may only affect static geometry.
                node.IsStatic = true;
            }

            // Add model node to scene graph.
            var scene = _services.GetInstance <IScene>();

            scene.Children.Add(_modelNode);
        }
Exemplo n.º 4
0
        public SkinnedEffectSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            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.
            _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);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Positions the camera so that it sees the whole model and is not to near or to far away.
        /// </summary>
        private void ResetCameraPose()
        {
            if (ModelNode == null && Document.Model == null)
            {
                var lookAtMatrix = Matrix.CreateLookAt(new Vector3(10, 10, 10), new Vector3(0, 1, 0), new Vector3(0, 1, 0));
                _cameraNode.PoseWorld = Pose.FromMatrix(lookAtMatrix).Inverse;
                ModelCenter           = new Vector3(0, 1, 0);
                MoveSpeed             = 5;
                ZoomSpeed             = MoveSpeed / 10;
                return;
            }

            // Get combined AABB of scene nodes.
            Aabb aabb = new Aabb();

            if (ModelNode != null)
            {
                foreach (var meshNode in ModelNode.GetSubtree().OfType <MeshNode>())
                {
                    aabb.Grow(meshNode.Aabb);
                }
            }
            else
            {
                Matrix[] boneTransforms = new Matrix[Document.Model.Bones.Count];
                Document.Model.CopyAbsoluteBoneTransformsTo(boneTransforms);
                foreach (var mesh in Document.Model.Meshes)
                {
                    var sphere = mesh.BoundingSphere;
                    sphere = sphere.Transform(boneTransforms[mesh.ParentBone.Index]);
                    var partCenter = (Vector3)sphere.Center;
                    var partRadius = new Vector3(sphere.Radius);
                    aabb.Grow(new Aabb(partCenter - partRadius, partCenter + partRadius));
                }
            }

            // Set camera position.
            var center   = aabb.Center;
            var radius   = aabb.Extent.Length / 2;
            var gamma    = _cameraNode.Camera.Projection.FieldOfViewY / 2;
            var distance = Math.Max((float)(radius / Math.Tan(gamma)) * 0.7f, 1);  // * 0.x to move a bit closer otherwise distance is usually to large.

            _cameraNode.PoseWorld = Pose.FromMatrix(
                Matrix.CreateLookAt(center + new Vector3(distance), center, Vector3.Up)).Inverse;

            // Center for camera orbiting.
            ModelCenter = center;

            // Make navigation speed relative to model size.
            MoveSpeed = Math.Max(radius * 4, 1);
            ZoomSpeed = MoveSpeed / 10;
        }
Exemplo n.º 6
0
        private void CreateRigidBody()
        {
            var triangleMesh = new TriangleMesh();

            foreach (var meshNode in _modelNode.GetSubtree().OfType <MeshNode>())
            {
                // Extract the triangle mesh from the DigitalRune Graphics Mesh instance.
                var subTriangleMesh = new TriangleMesh();
                foreach (var submesh in meshNode.Mesh.Submeshes)
                {
                    submesh.ToTriangleMesh(subTriangleMesh);
                }

                // Apply the transformation of the mesh node.
                subTriangleMesh.Transform(meshNode.PoseWorld * Matrix.CreateScale(meshNode.ScaleWorld));

                // Combine into final triangle mesh.
                triangleMesh.Add(subTriangleMesh);
            }

            // Create a collision shape that uses the mesh.
            var triangleMeshShape = new TriangleMeshShape(triangleMesh);

            // Optional: Assign a spatial partitioning scheme to the triangle mesh. (A spatial partition
            // adds an additional memory overhead, but it improves collision detection speed tremendously!)
            triangleMeshShape.Partition = new CompressedAabbTree
            {
                // 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,
            };

            _rigidBody = new RigidBody(triangleMeshShape, new MassFrame(), null)
            {
                Pose       = _pose,
                Scale      = _scale,
                MotionType = MotionType.Static
            };

            // Add rigid body to physics simulation and model to scene.
            var simulation = _services.GetInstance <Simulation>();

            simulation.RigidBodies.Add(_rigidBody);
        }
Exemplo n.º 7
0
        // OnLoad() is called when the GameObject is added to the IGameObjectService.
        protected override void OnLoad()
        {
            // Load model.
            var contentManager = _services.GetInstance <ContentManager>();

            _modelNode            = contentManager.Load <ModelNode>("Ground/Ground").Clone();
            _modelNode.ScaleLocal = new Vector3(0.5f);

            foreach (var node in _modelNode.GetSubtree())
            {
                // Disable the CastsShadows flag for ground meshes. No need to render
                // this model into the shadow map. (This also avoids any shadow acne on
                // the ground model.)
                node.CastsShadows = false;

                // If models will never move, set the IsStatic flag. This gives the engine
                // more room for optimizations. Additionally, some effects, like certain
                // decals, may only affect static geometry.
                node.IsStatic = true;
            }

            // Add model node to scene graph.
            var scene = _services.GetInstance <IScene>();

            scene.Children.Add(_modelNode);

            // Create rigid body.
            _rigidBody = new RigidBody(new PlaneShape(Vector3.UnitY, 0))
            {
                MotionType = MotionType.Static,
            };

            // Add rigid body to the physics simulation.
            var simulation = _services.GetInstance <Simulation>();

            simulation.RigidBodies.Add(_rigidBody);
        }
        public override void Update(GameTime gameTime)
        {
            Random random = new Random(1234567);

            // The debug renderer stores all draw commands. In this sample we recreate
            // the draw jobs each frame. --> Clear draw jobs of last frame.
            _debugRenderer.Clear();

            // The DebugRenderer can draw stuff "in" the scene (enabled z test) or "over"
            // the scene (disabled z test).

            // Draw some points and line "in" and "over" the scene.
            for (int i = 0; i < 10; i++)
            {
                var position = new Vector3F(-6, 0, -3) + random.NextVector3F(-0.5f, 0.5f);
                _debugRenderer.DrawPoint(position, Color.Green, false);
            }

            for (int i = 0; i < 10; i++)
            {
                var position = new Vector3F(-4, 0, -3) + random.NextVector3F(-0.5f, 0.5f);
                _debugRenderer.DrawPoint(position, Color.Yellow, true);
            }

            for (int i = 0; i < 10; i++)
            {
                var start = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f);
                var end   = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f);
                _debugRenderer.DrawLine(start, end, Color.Green, false);
            }

            for (int i = 0; i < 10; i++)
            {
                var start = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f);
                var end   = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f);
                _debugRenderer.DrawLine(start, end, Color.Yellow, true);
            }

            // Text without a specified position is drawn at a default position.
            _debugRenderer.DefaultTextPosition = new Vector2F(10, 100);
            _debugRenderer.DrawText("White objects are positioned in screen space.");
            _debugRenderer.DrawText("Yellow objects are positioned in world space. Depth test disabled.");
            _debugRenderer.DrawText("Other objects are positioned in world space. Depth test enabled.");

            // Text can also be drawn in world space coordinates or in screen space coordinates.
            _debugRenderer.DrawText("WorldSpacePosition (0, 0, 0)", new Vector3F(0, 0, 0), Color.Green, false);
            _debugRenderer.DrawText("WorldSpacePosition (0, 0, -1)", new Vector3F(0, 0, -1), Color.Yellow, true);
            _debugRenderer.DrawText("ScreenPosition (600, 40)", new Vector2F(600, 40), Color.White);
            _debugRenderer.DrawText("ScreenPosition (640, 360)", new Vector2F(640, 360), Color.White);

            // It is often useful to copy textures to the screen for debugging.
            _debugRenderer.DrawTexture(NoiseHelper.GetGrainTexture(GraphicsService, 128), new Rectangle(1000, 10, 128, 128));

            // Axes can be drawn to display poses (positions and orientations).
            _debugRenderer.DrawAxes(new Pose(new Vector3F(0, 0, 0)), 1, true);

            // Axis-aligned bounding boxes (AABB)
            _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(2, 0, -3)), Color.Green, false);
            _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(4, 0, -3)), Color.Yellow, true);

            // Box shapes
            var orientation = random.NextQuaternionF();

            _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), new Color(255, 0, 0, 100), false, false);
            _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), Color.Green, true, false);
            _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-4, 0, -5), orientation), Color.Yellow, true, true);

            // View volumes (frustums)
            var viewVolume = new PerspectiveViewVolume(1, 2, 0.1f, 1f);

            _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), new Color(0, 255, 0, 100), false, false);
            _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), Color.Green, true, false);
            _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(0, 0, -5), orientation), Color.Yellow, true, true);

            // Spheres
            _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), new Color(0, 0, 255, 100), false, false);
            _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), Color.Green, true, false);
            _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(4, 0, -5), orientation), Color.Yellow, true, true);

            // Capsules
            _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), new Color(255, 255, 0, 100), false, false);
            _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), Color.Green, true, false);
            _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-4, 0, -7), orientation), Color.Yellow, true, true);

            // Cylinders
            _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), new Color(255, 0, 255, 100), false, false);
            _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), Color.Green, true, false);
            _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(0, 0, -7), orientation), Color.Yellow, true, true);

            // Cones
            _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), new Color(0, 255, 255, 100), false, false);
            _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), Color.Green, true, false);
            _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(4, 0, -7), orientation), Color.Yellow, true, true);

            // The debug renderer can draw any IGeometricObjects, like SceneNodes, RigidBodies, etc.
            _debugRenderer.DrawObject(_geometricObject, Color.Brown, false, false);
            _debugRenderer.DrawObject(_geometricObject, Color.Yellow, true, true);

            // The debug renderer can also an XNA model (without materials).
            _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), new Color(128, 255, 64, 100), false, false);
            _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), Color.LightCyan, true, false);

            // Draw a DigitalRune model.
            _debugRenderer.DrawModel(_modelNode, Color.Peru, true, false);

            // Draw the bounding shapes of the meshes in this model.
            foreach (var node in _modelNode.GetSubtree())
            {
                _debugRenderer.DrawObject(node, Color.PeachPuff, true, false);
            }
        }
Exemplo n.º 9
0
        private void Render(RenderContext context)
        {
            // Set the current camera node in the render context. This info is used
            // by the renderers.
            context.CameraNode = _cameraObject.CameraNode;
            context.Scene      = _scene;

            var device = context.GraphicsService.GraphicsDevice;

            device.Clear(Color.CornflowerBlue);

            device.DepthStencilState = DepthStencilState.Default;
            device.RasterizerState   = RasterizerState.CullCounterClockwise;
            device.BlendState        = BlendState.Opaque;

            context.RenderPass = "******";
            foreach (var meshNode in _model.GetSubtree().OfType <MeshNode>())
            {
                context.SceneNode = meshNode;

                foreach (var submesh in meshNode.Mesh.Submeshes)
                {
                    var materialIndex           = submesh.MaterialIndex;
                    var materialInstance        = meshNode.MaterialInstances[materialIndex];
                    var material                = materialInstance.Material;
                    var materialInstanceBinding = materialInstance[context.RenderPass];
                    var materialBinding         = material[context.RenderPass];
                    var effect = materialBinding.Effect;

                    context.MaterialBinding         = materialBinding;
                    context.MaterialInstanceBinding = materialInstanceBinding;

                    // Update and apply global bindings.
                    foreach (var binding in effect.GetParameterBindings())
                    {
                        if (binding.Description.Hint == EffectParameterHint.Global)
                        {
                            binding.Update(context);
                            binding.Apply(context);
                        }
                    }

                    // Update and apply material bindings.
                    foreach (var binding in materialBinding.ParameterBindings)
                    {
                        binding.Update(context);
                        binding.Apply(context);
                    }

                    // Update and apply local and per-instance bindings.
                    foreach (var binding in materialInstanceBinding.ParameterBindings)
                    {
                        if (binding.Description.Hint != EffectParameterHint.PerPass)
                        {
                            binding.Update(context);
                            binding.Apply(context);
                        }
                    }

                    // Select and apply effect technique.
                    var techniqueBinding = materialInstanceBinding.TechniqueBinding;
                    techniqueBinding.Update(context);
                    var technique = techniqueBinding.GetTechnique(effect, context);
                    effect.CurrentTechnique = technique;

                    // Select and apply effect passes.
                    var passBinding = techniqueBinding.GetPassBinding(technique, context);
                    foreach (var pass in passBinding)
                    {
                        // Update and apply per-pass bindings.
                        foreach (var binding in materialInstanceBinding.ParameterBindings)
                        {
                            if (binding.Description.Hint == EffectParameterHint.PerPass)
                            {
                                binding.Update(context);
                                binding.Apply(context);
                            }
                        }

                        pass.Apply();
                        submesh.Draw();
                    }


                    context.MaterialBinding         = null;
                    context.MaterialInstanceBinding = null;
                }
            }
            context.SceneNode  = null;
            context.RenderPass = null;

            // Clean up.
            context.CameraNode = null;
            context.Scene      = null;
        }
Exemplo n.º 10
0
        public MeshNodeSample(Microsoft.Xna.Framework.Game game)
            : base(game)
        {
            SampleFramework.IsMouseVisible = false;
            var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService)
            {
                RenderCallback = Render,
            };

            GraphicsService.Screens.Insert(0, delegateGraphicsScreen);

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

            // For advanced users: Set this flag if you want to analyze the imported opaque data of
            // effect bindings.
            //EffectBinding.KeepOpaqueData = true;

            // Load a model. The model is processed using the DigitalRune Model Processor - not
            // the default XNA model processor!
            // In the folder that contains tank.fbx, there is an XML file tank.drmdl which defines
            // properties of the model. These XML files are automatically processed by the
            // DigitalRune Model Processor.
            // Each model itself is a tree of scene nodes. The grid model contains one mesh
            // node. The tank model contains several mesh nodes (turret, cannon, hatch,
            // wheels, ...).
            _model = ContentManager.Load <ModelNode>("Tank/tank");

            // The XNA ContentManager manages a single instance of each model. We clone
            // the model, to get a copy that we can modify without changing the original
            // instance. Cloning is fast because it only duplicates the scene nodes - but
            // not the mesh and material information.
            _model = _model.Clone();

            // _model is the root of a tree of scene nodes. The mesh nodes are the child
            // nodes. When we scale or move the _model, we automatically scale and move
            // all child nodes.
            _model.ScaleLocal = new Vector3F(0.8f);
            _model.PoseWorld  = new Pose(new Vector3F(0, 0, -2), Matrix33F.CreateRotationY(-0.3f));

            // Let's loop through the mesh nodes of the model:
            foreach (var meshNode in _model.GetSubtree().OfType <MeshNode>())
            {
                // Each MeshNode references a Mesh.
                Mesh mesh = meshNode.Mesh;

                // The mesh consists of several submeshes and several materials - usually
                // one material per submesh, but several submeshes could reference the same
                // materials.

                // Let's loop through the materials of this mesh.
                foreach (var material in mesh.Materials)
                {
                    // A material is a collection of EffectBindings - one EffectBinding for each
                    // render pass. For example, a complex game uses several render passes, like
                    // a pre-Z pass, a G-buffer pass, a shadow map pass, a deferred material pass,
                    // etc.In simple games there is only one pass which is called "Default".
                    var effectBinding = material["Default"];

                    // An EffectBinding references an Effect (the XNA Effect class) and it has
                    // "parameter bindings" and "technique bindings". These bindings select the
                    // values for the shader parameters when the mesh node is rendered.

                    // Let's change the binding for the DiffuseColor of the shader to give tank
                    // a red color.
                    effectBinding.Set("DiffuseColor", new Vector4(1, 0.7f, 0.7f, 1));

                    // The tank uses the default effect binding which is a BasicEffectBinding - this
                    // effect binding uses the XNA BasicEffect.
                    // In this sample we do not define any lights, therefore we disable the lighting
                    // in the shader.
                    ((BasicEffectBinding)effectBinding).LightingEnabled = false;
                }
            }

            _meshRenderer = new MeshRenderer();

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

            _debugRenderer = new DebugRenderer(GraphicsService, spriteFont);
        }
Exemplo n.º 11
0
        // OnLoad() is called when the GameObject is added to the IGameObjectService.
        protected override void OnLoad()
        {
            // Load sandbox model.
            var contentManager = _services.GetInstance <ContentManager>();

            _modelNode = contentManager.Load <ModelNode>("Sandbox/Sandbox").Clone();

            foreach (var node in _modelNode.GetSubtree())
            {
                // Disable the CastsShadows flag. The inside of the box should be fully lit.
                node.CastsShadows = false;

                // If models will never move, set the IsStatic flag. This gives the engine
                // more room for optimizations. Additionally, some effects, like certain
                // decals, may only affect static geometry.
                node.IsStatic = true;
            }

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

            scene.Children.Add(_modelNode);

            // Create rigid bodies for the sides of the sandbox.
            _floorRigidBody = new RigidBody(new PlaneShape(new Vector3(0, 1, 0), 0))
            {
                Name       = "Floor",
                MotionType = MotionType.Static,
            };
            _floorRigidBody.CollisionObject.CollisionGroup = 1;
            _leftWallRigidBody = new RigidBody(new PlaneShape(new Vector3(1, 0, 0), -10))
            {
                Name       = "WallLeft",
                MotionType = MotionType.Static,
            };
            _leftWallRigidBody.CollisionObject.CollisionGroup = 1;
            _rightWallRigidBody = new RigidBody(new PlaneShape(new Vector3(-1, 0, 0), -10))
            {
                Name       = "WallRight",
                MotionType = MotionType.Static,
            };
            _rightWallRigidBody.CollisionObject.CollisionGroup = 1;
            _backWallRigidBody = new RigidBody(new PlaneShape(new Vector3(0, 0, 1), -10))
            {
                Name       = "WallBack",
                MotionType = MotionType.Static,
            };
            _backWallRigidBody.CollisionObject.CollisionGroup = 1;
            _frontWallRigidBody = new RigidBody(new PlaneShape(new Vector3(0, 0, -1), -10))
            {
                Name       = "WallFront",
                MotionType = MotionType.Static,
            };
            _frontWallRigidBody.CollisionObject.CollisionGroup = 1;

            // Add rigid bodies to simulation.
            var simulation = _services.GetInstance <Simulation>();

            simulation.RigidBodies.Add(_floorRigidBody);
            simulation.RigidBodies.Add(_leftWallRigidBody);
            simulation.RigidBodies.Add(_rightWallRigidBody);
            simulation.RigidBodies.Add(_backWallRigidBody);
            simulation.RigidBodies.Add(_frontWallRigidBody);
        }