private void InitializeSimulation(Simulation simulation, Vector3F offset) { // Add default force effects. simulation.ForceEffects.Add(new Gravity()); simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", MotionType = MotionType.Static, }; simulation.RigidBodies.Add(groundPlane); // Add a stack of boxes. const float boxSize = 0.8f; float overlap = simulation.Settings.Constraints.AllowedPenetration * 0.5f; float yPosition = boxSize / 2 - overlap; BoxShape boxShape = new BoxShape(boxSize, boxSize, boxSize); for (int i = 0; i < 15; i++) { RigidBody stackBox = new RigidBody(boxShape) { Name = "StackBox" + i, Pose = new Pose(new Vector3F(0, yPosition, 0) + offset), }; simulation.RigidBodies.Add(stackBox); yPosition += boxSize - overlap; } }
public RigidBodyRenderer(Game game, Simulation simulation) : base(game) { Simulation = simulation; DrawWireFrame = true; }
public ParallelSimulationsSample(Microsoft.Xna.Framework.Game game) : base(game) { // Initialize the default simulation with a box stack on the left. Simulation firstSimulation = Simulation; InitializeSimulation(firstSimulation, new Vector3F(-3, 0, 0)); // Initialize a second simulation with a box stack on the right. _secondSimulation = new Simulation(); InitializeSimulation(_secondSimulation, new Vector3F(3, 0, 0)); // Disable sleeping so that we can see the result of changed simulation settings and // bodies are not automatically disabled. firstSimulation.Settings.Sleeping.TimeThreshold = float.PositiveInfinity; _secondSimulation.Settings.Sleeping.TimeThreshold = float.PositiveInfinity; // ----- Let's play around with simulation settings. // Reduce the number of constraint iterations. - This makes the simulation faster and // less accurate/stable. _secondSimulation.Settings.Constraints.NumberOfConstraintIterations = 4; // The "BaumgarteRatio" is an experimental parameter that changes error correction method. // Setting this value to 0 makes the simulation a bit slower but less "bouncy". //_secondSimulation.Settings.Constraints.BaumgarteRatio = 0; // If we set a stacking factor > 0, we can make right stack stable - even with reduced // constraint iteration count. //_secondSimulation.Settings.Constraints.StackingFactor = 5; }
public override void Initialize() { simulation = ((GenericGame)Game).Simulation; //Floor AddBody("GroundPlane", Pose.Identity, new PlaneShape(Vector3F.UnitY, -2.5F), MotionType.Static); //Loaf Map01 model from content pipeline. model = Game.Content.Load<Model>("map01"); //Collision map vertices (Map01 is concave, so automatic generation is not possible with this engine) CreateWall(0F, -7F, 16F); CreateWall(0F, 7F, 16F); CreateWall(-7F, 0F, 16F, true); CreateWall(7F, 0F, 16F, true); CreateWall(-5F, -6F, 4F); CreateWall(1.5F, -6F, 3F); CreateWall(5F, -6F, 2F); CreateWall(-6F, -5F, 2F); CreateWall(-1.5F, -5F, 1F); CreateWall(6.5F, -5F, 1F); CreateWall(2F, -4F, 2F); CreateWall(-4.5F, -3F, 1F); CreateWall(-0.5F, -3F, 3F); CreateWall(5F, -3F, 2F); CreateWall(-5.5F, -2F, 1F); CreateWall(-0.5F, -2F, 3F); CreateWall(5F, -2F, 2F); CreateWall(-3.5F, -1F, 1F); CreateWall(-1F, -1F, 2F); CreateWall(3F, -1F, 2F); CreateWall(-4.5F, 0F, 1F); CreateWall(-2F, 0F, 2F); CreateWall(5F, 0F, 2F); CreateWall(-0.5F, 1F, 1F); CreateWall(4.5F, 1F, 1F); CreateWall(6.5F, 1F, 1F); CreateWall(2.5F, 2F, 1F); CreateWall(-5.5F, 3F, 1F); CreateWall(-3.5F, 3F, 1F); CreateWall(-0.5F, 3F, 3F); CreateWall(-6.5F, 4F, 1F); CreateWall(0.5F, 4F, 3F); CreateWall(6.5F, 4F, 1F); CreateWall(-5.5F, 5F, 1F); CreateWall(-2.5F, 5F, 1F); CreateWall(-0.5F, 5F, 1F); CreateWall(3.5F, 5F, 1F); CreateWall(5.5F, 5F, 1F); CreateWall(-5F, 6F, 4F); CreateWall(-1.5F, 6F, 1F); CreateWall(0.5F, 6F, 1F); CreateWall(5F, 6F, 2F); CreateWall(-6F, 0.5F, 5F, true); CreateWall(-6F, 4.5F, 1F, true); CreateWall(-5F, -4F, 2F, true); CreateWall(-5F, -1F, 2F, true); CreateWall(-5F, 4F, 2F, true); CreateWall(-4F, -2F, 2F, true); CreateWall(-4F, 1.5F, 3F, true); CreateWall(-3F, -3.5F, 5F, true); CreateWall(-3F, 1.5F, 3F, true); CreateWall(-3F, 5.5F, 1F, true); CreateWall(-2F, -4F, 2F, true); CreateWall(-2F, -1.5F, 1F, true); CreateWall(-2F, 4F, 2F, true); CreateWall(-2F, 6.5F, 1F, true); CreateWall(-1F, -6F, 2F, true); CreateWall(-1F, 0.5F, 1F, true); CreateWall(-1F, 4.5F, 1F, true); CreateWall(-1F, 6.5F, 1F, true); CreateWall(0F, -6.5F, 1F, true); CreateWall(0F, 0F, 2F, true); CreateWall(0F, 5.5F, 1F, true); CreateWall(1F, -3.5F, 1F, true); CreateWall(1F, 0.5F, 5F, true); CreateWall(1F, 6.5F, 1F, true); CreateWall(2F, 0.5F, 3F, true); CreateWall(2F, 5.5F, 3F, true); CreateWall(3F, -5F, 2F, true); CreateWall(3F, 3.5F, 3F, true); CreateWall(4F, -4.5F, 3F, true); CreateWall(4F, -1.5F, 1F, true); CreateWall(4F, 0.5F, 1F, true); CreateWall(4F, 5.5F, 1F, true); CreateWall(5F, 3F, 4F, true); CreateWall(6F, -6.5F, 1F, true); CreateWall(6F, -4F, 2F, true); CreateWall(6F, -1F, 2F, true); CreateWall(6F, 2.5F, 3F, true); CreateWall(6F, 5.5F, 1F, true); base.Initialize(); }
protected Sample(Microsoft.Xna.Framework.Game game) : base(game) { // Get services from the global service container. var services = (ServiceContainer)ServiceLocator.Current; SampleFramework = services.GetInstance<SampleFramework>(); ContentManager = services.GetInstance<ContentManager>(); UIContentManager = services.GetInstance<ContentManager>("UIContent"); InputService = services.GetInstance<IInputService>(); AnimationService = services.GetInstance<IAnimationService>(); Simulation = services.GetInstance<Simulation>(); ParticleSystemService = services.GetInstance<IParticleSystemService>(); GraphicsService = services.GetInstance<IGraphicsService>(); GameObjectService = services.GetInstance<IGameObjectService>(); UIService = services.GetInstance<IUIService>(); // Create a local service container which can be modified in samples: // The local service container is a child container, i.e. it inherits the // services of the global service container. Samples can add new services // or override existing entries without affecting the global services container // or other samples. Services = services.CreateChildContainer(); // Store a copy of the original graphics screens. _originalGraphicsScreens = GraphicsService.Screens.ToArray(); // Mouse is visible by default. SampleFramework.IsMouseVisible = true; }
public ExplosionObject(IServiceLocator services) { Name = "Explosion"; _inputService = services.GetInstance<IInputService>(); _simulation = services.GetInstance<Simulation>(); _gameObjectService = services.GetInstance<IGameObjectService>(); }
private bool _showSleeping = true; // Determines whether sleeping objects should be visualized. #endregion Fields #region Constructors public RigidBodyRenderer(Game game) : base(game) { _inputService = (IInputService)game.Services.GetService(typeof(IInputService)); _simulation = (Simulation)game.Services.GetService(typeof(Simulation)); DrawWireFrame = true; }
public BallShooterObject(IServiceLocator services) { Name = "BallShooter"; Speed = 100; _inputService = services.GetInstance<IInputService>(); _simulation = services.GetInstance<Simulation>(); _gameObjectService = services.GetInstance<IGameObjectService>(); }
public MyGameComponent(Microsoft.Xna.Framework.Game game, IServiceLocator services) : base(game) { // Get the services that this component needs regularly. _services = services; _inputService = services.GetInstance<IInputService>(); _simulation = services.GetInstance<Simulation>(); _graphicsService = services.GetInstance<IGraphicsService>(); _gameObjectService = services.GetInstance<IGameObjectService>(); _uiService = services.GetInstance<IUIService>(); // Add gravity and damping to the physics simulation. _simulation.ForceEffects.Add(new Gravity()); _simulation.ForceEffects.Add(new Damping()); // Create the DeferredGraphicsScreen and some 3D objects. _deferredGraphicsScreen = new DeferredGraphicsScreen(services); _deferredGraphicsScreen.DrawReticle = true; _graphicsService.Screens.Insert(0, _deferredGraphicsScreen); // The GameObjects below expect try to retrieve DebugRenderer and Scene via // service container. var serviceContainer = (ServiceContainer)services; serviceContainer.Register(typeof(DebugRenderer), null, _deferredGraphicsScreen.DebugRenderer); serviceContainer.Register(typeof(IScene), null, _deferredGraphicsScreen.Scene); _cameraGameObject = new CameraObject(services); _gameObjectService.Objects.Add(_cameraGameObject); _deferredGraphicsScreen.ActiveCameraNode = _cameraGameObject.CameraNode; _gameObjectService.Objects.Add(new GrabObject(services)); _gameObjectService.Objects.Add(new StaticSkyObject(services)); _gameObjectService.Objects.Add(new GroundObject(services)); for (int i = 0; i < 10; i++) _gameObjectService.Objects.Add(new DynamicObject(services, 1)); // Get the "SampleUI" screen that was created by the StartScreenComponent. _uiScreen = _uiService.Screens["SampleUI"]; // Add a second GraphicsScreen. This time it is a DelegateGraphicsScreen that // draws the UI over DeferredGraphicsScreen. _delegateGraphicsScreen = new DelegateGraphicsScreen(_graphicsService) { RenderCallback = context => _uiScreen.Draw(context.DeltaTime) }; _graphicsService.Screens.Insert(1, _delegateGraphicsScreen); // Create the game menu window. But do not display it yet. _gameMenuWindow = new GameMenuWindow { // If the menu is opened and closed a lot, it is more efficient when _gameMenuWindow.Close() // makes the window invisible but does not remove it from the screen. HideOnClose = true, }; }
public DigitalRuneSimulator() { _wrappedSimulation = new Simulation(); ((MaterialPropertyCombiner)_wrappedSimulation.Settings.MaterialPropertyCombiner).RestitutionMode = MaterialPropertyCombiner.Mode.ArithmeticMean; ((MaterialPropertyCombiner)_wrappedSimulation.Settings.MaterialPropertyCombiner).FrictionMode = MaterialPropertyCombiner.Mode.ArithmeticMean; _wrappedSimulation.ForceEffects.Add(new Damping()); Configurator = new SimulatorConfigurator(this); Queries = new SimulatorQueries(this); ActorsFactory = new SimulatorRigidBodyFactory(this); ConstraintsFactory = new SimulatorConstraintsFactory(this); }
protected override void Initialize() { // ----- Initialize Services. // The services are stored in Game.Services to make them accessible for all // game components. // Add the input service, which manages device input, button presses, etc. _inputManager = new InputManager(false); Services.AddService(typeof(IInputService), _inputManager); // Add the animation service. _animationManager = new AnimationManager(); Services.AddService(typeof(IAnimationService), _animationManager); // Add the physics simulation to the service and add some force effects. // (TODO: Create a IPhysicsService that owns the simulation.) _simulation = new Simulation(); _simulation.ForceEffects.Add(new Gravity()); _simulation.ForceEffects.Add(new Damping()); Services.AddService(typeof(Simulation), _simulation); // ----- Add GameComponents Components.Add(new GamerServicesComponent(this)); // XNA gamer services needed for avatars. Components.Add(new Camera(this)); // Controls the camera. Components.Add(new BallShooter(this)); // Shoot balls at the target position. Components.Add(new Grab(this)); // Allows to grab objects with the mouse/gamepad Components.Add(new RigidBodyRenderer(this) { DrawOrder = 10 }); // Renders all rigid bodies of the simulation. Components.Add(new Reticle(this) { DrawOrder = 20 }); // Draws a cross-hair for aiming. Components.Add(new Help(this) { DrawOrder = 30 }); // Draws help text. Components.Add(new Profiler(this) { DrawOrder = 40 }); // Displays profiling data. // Initialize the sample factory methods. All samples must be added to this // array to be shown. _createSampleDelegates = new Func<Sample>[] { () => new BasicAvatarSample(this), () => new WrappedAnimationSample(this), () => new BakedAnimationSample(this), () => new CustomAnimationSample(this), () => new AttachmentSample(this), () => new RagdollSample(this), () => new AdvancedRagdollSample(this), }; // Start the first sample in the array. _activeSampleIndex = 0; _activeSample = _createSampleDelegates[0](); Components.Add(_activeSample); base.Initialize(); }
public InGameUIScreen(IServiceLocator services, IUIRenderer renderer) : base("InGame", renderer) { var gameObjectService = services.GetInstance<IGameObjectService>(); _cameraObject = (CameraObject)gameObjectService.Objects["Camera"]; _simulation = services.GetInstance<Simulation>(); Background = Color.White; // Add one window to the screen. Window window = new InGameWindow(services) { X = 175, Y = 30 }; window.Show(this); }
protected override void Initialize() { //Create a new simulation with common settings. Simulation = new Simulation(); Simulation.Settings.Timing.MaxNumberOfSteps = 1; Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); //Add game components. Components.Add(new Map(this)); //Creates level with test obstacles. Components.Add(new Camera(this)); //Defines the camera position, orientation and projection. Components.Add(new Player(this)); //Controls the player vehicle. Components.Add(new KeyboardBinding(this)); //Creates a keyboard binding object Components.Add(new MouseBinding(this)); //Creates a mouse binding object base.Initialize(); }
private void DigitalRuneAdaptorScene() { //creating the simulation _simulation = new Simulation(); _simulation.ForceEffects.Add(new Gravity()); _simulation.ForceEffects.Add(new Damping()); //definig a material var material = new UniformMaterial { StaticFriction = 0.5f, DynamicFriction = 0.5f, Restitution = 0.7f }; //creating the ground CreateGround(material); ////creating a Tower CreateTower(material, new BoxShapeDescriptor(1, 1, 1), xCount: 3, yCount: 3, zCount: 3, xSpace: 2, ySpace: 2, zSpace: 2, xOffset: 0, yOffset: 2 + 10 / 2, zOffset: 0); }
protected override void Initialize() { // ----- Initialize Services. // The services are stored in Game.Services to make them accessible for all // game components. // Add the input service, which manages device input, button presses, etc. _inputManager = new InputManager(false); Services.AddService(typeof(IInputService), _inputManager); // Add the physics simulation to the service. _simulation = new Simulation(); // We do not add the standard force effects because our bodies should only // be modified by Kinect data! //_simulation.ForceEffects.Add(new Gravity()); //_simulation.ForceEffects.Add(new Damping()); Services.AddService(typeof(Simulation), _simulation); // ----- Add GameComponents Components.Add(new Camera(this)); // Controls the camera. Components.Add(new RigidBodyRenderer(this, _simulation)); // Renders rigid bodies for debugging. Components.Add(new Help(this) { DrawOrder = 30 }); // Draws help text. Components.Add(new KinectWrapper(this)); // Wraps the Kinect sensor. // Initialize the sample factory methods. All samples must be added to this // array to be shown. _createSampleDelegates = new Func<SampleBase>[] { () => new SkeletonMappingSample(this), () => new RagdollMarionetteSample(this), }; // Start the first sample in the array. _activeSampleIndex = 0; _activeSample = _createSampleDelegates[0](); Components.Add(_activeSample); base.Initialize(); }
//-------------------------------------------------------------- #region Methods //-------------------------------------------------------------- protected override void OnLoad() { // Get common services and game objects. _graphicsService = _services.GetInstance<IGraphicsService>(); _graphicsScreen = _graphicsService.Screens.OfType<DeferredGraphicsScreen>().First(); var content = _services.GetInstance<ContentManager>(); var scene = _services.GetInstance<IScene>(); _simulation = _services.GetInstance<Simulation>(); var gameObjectService = _services.GetInstance<IGameObjectService>(); _cameraObject = gameObjectService.Objects.OfType<CameraObject>().First(); _previousCameraFar = _cameraObject.CameraNode.Camera.Projection.Far; // Create a new terrain. var terrain = new Terrain(); // The terrain is made up of terrain tiles which can be loaded independently. // Each terrain tile consists of height and normal textures which define the terrain // geometry and terrain layers which define the material (detail textures). // In this sample we create 2x2 tiles. _tiles = new Tile[2, 2]; for (int row = 0; row < 2; row++) { for (int column = 0; column < 2; column++) { // Create a tile and add it to the terrain. // (The tile content is loaded later.) var terrainTile = new TerrainTile(_graphicsService) { CellSize = 1, // The terrain has a resolution of 1 height sample per world space unit. }; terrain.Tiles.Add(terrainTile); // Create a rigid body with a height field for collision detection and add // it to the simulation. (The height data is loaded later.) var heightField = new HeightField { Depth = 1, UseFastCollisionApproximation = false, }; var rigidBody = new RigidBody(heightField, new MassFrame(), null) { MotionType = MotionType.Static, UserData = terrainTile, }; _simulation.RigidBodies.Add(rigidBody); // Store the tile for use later in this sample. _tiles[row, column] = new Tile { TerrainTile = terrainTile, RigidBody = rigidBody, }; } } // Create a terrain node which represents the terrain in the scene graph. // The terrain node is rendered by the TerrainRenderer (see DeferredGraphicsScreen). // The material used to render the terrain is customizable. The material must specify // the effects for the different render passes which we use in the DeferredGraphicsScreen // ("ShadowMap", "GBuffer", "Material"). // The prebuilt DigitalRune content contains standard terrain effects. However, you could // change the effects to change how the material is rendered. // We can create the material by loading a .drmat file. Or we can create the material in // code like this: var shadowMapEffect = content.Load<Effect>("DigitalRune/Terrain/TerrainShadowMap"); var gBufferEffect = content.Load<Effect>("DigitalRune/Terrain/TerrainGBuffer"); var materialEffect = content.Load<Effect>("DigitalRune/Terrain/TerrainMaterial"); var material = new Material { { "ShadowMap", new EffectBinding(_graphicsService, shadowMapEffect, null, EffectParameterHint.Material) }, { "GBuffer", new EffectBinding(_graphicsService, gBufferEffect, null, EffectParameterHint.Material) }, { "Material", new EffectBinding(_graphicsService, materialEffect, null, EffectParameterHint.Material) } }; TerrainNode = new TerrainNode(terrain, material) { // The terrain rendering uses clipmaps. // The clipmaps are updated by the TerrainClipmapRenderer (see DeferredGraphicsScreen) // when the camera moves. // The base clipmap contains the basic geometry info (height, normals, hole info). // It also determines the terrain mesh resolution. BaseClipmap = { CellsPerLevel = 128, NumberOfLevels = 6 }, // The detail clipmap contains the splatted detail textures (e.g. grass, rock, ...). // (The max texture size in XNA is 4096x4096. That means we can fit 9 clipmap levels // into a single texture.) DetailClipmap = { CellsPerLevel = 1365, NumberOfLevels = 9, }, }; scene.Children.Add(TerrainNode); // Load the height and normal maps which define the terrain geometry. InitializeHeightsAndNormals(); // Set the clipmap cell sizes. InitializeClipmapCellSizes(); // Create the terrain layers which define the detail textures (e.g. grass, rock, ...) InitializeTerrainLayers(content); // Special note for AMD GPUs: // If we want anisotropic filtering for the terrain, then we need to enable mipmaps for // AMD GPUs. NVIDIA and Intel can do anisotropic filtering without mipmaps. //TerrainNode.DetailClipmap.EnableMipMap = true; CreateGuiControls(); }
protected override void Initialize() { // ----- Initialize Services. // The services are stored in Game.Services to make them accessible for all // game components. // Add the input service, which manages device input, button presses, etc. _inputManager = new InputManager(false); Services.AddService(typeof(IInputService), _inputManager); // Add the animation service. _animationManager = new AnimationManager(); Services.AddService(typeof(IAnimationService), _animationManager); // Add the physics simulation to the service. // (TODO: Create a IPhysicsService that owns the simulation.) _simulation = new Simulation(); // Add standard force effects: _simulation.ForceEffects.Add(new Gravity()); _simulation.ForceEffects.Add(new Damping()); Services.AddService(typeof(Simulation), _simulation); // ----- Add GameComponents Components.Add(new Camera(this)); // Controls the camera. Components.Add(new BallShooter(this)); // Shoot balls at the target position. Components.Add(new Grab(this)); // Allows to grab objects with the mouse/gamepad Components.Add(new RigidBodyRenderer(this) { DrawOrder = 10 }); // Renders all rigid bodies of the simulation. Components.Add(new Reticle(this) { DrawOrder = 20 }); // Draws a cross-hair for aiming. Components.Add(new Help(this) { DrawOrder = 30 }); // Draws help text. Components.Add(new Profiler(this) { DrawOrder = 40 }); // Displays profiling data. // Initialize the sample factory methods. All samples must be added to this // array to be shown. _createSampleDelegates = new Func<Sample>[] { () => new BindPoseSample(this), () => new SkeletonManipulationSample(this), () => new DudeWalkingSample(this), () => new AttachmentSample(this), () => new CrossFadeSample(this), () => new StressTestSample(this), () => new CompressionSample(this), () => new MixingSample(this), () => new BoneJiggleSample(this), () => new SkeletonMappingSample(this), () => new LookAtIKSample(this), () => new JacobianTransposeIKSample(this), () => new CcdIKSample(this), () => new ClosedFormIKSample(this), () => new TwoJointIKSample(this), () => new CollisionDetectionOnlyRagdollSample(this), () => new KinematicRagdollSample(this), () => new PassiveRagdollSample(this), () => new ActiveRagdollSample(this), }; // Start the first sample in the array. _activeSampleIndex = 0; _activeSample = _createSampleDelegates[0](); Components.Add(_activeSample); base.Initialize(); }
public BallShooter(Game game) : base(game) { _inputService = (IInputService)game.Services.GetService(typeof(IInputService)); _simulation = (Simulation)game.Services.GetService(typeof(Simulation)); }
public override void Initialize() { // Get a reference to all of the other dependent components camera = Game.Components.OfType<Camera>().First(); simulation = ((GenericGame)Game).Simulation; //Need to differentiate between the IBinding objects as we need both of them //We COULD fetch them by actual type, but I'd rather get them in a generic fashion with and interface foreach (var binding in Game.Components.OfType<IBinding>()) { if (binding is KeyboardBinding) keyboardBinding = binding; else if (binding is MouseBinding) mouseBinding = binding; } //Bind thw WASD keys to the keyboard controller with the appropriate movement actions //Also, lambdas are very SEXY -Nick keyboardBinding.Bind(Keys.W, () => { moveDirection[0].Z--; }); keyboardBinding.Bind(Keys.S, () => { moveDirection[0].Z++; }); keyboardBinding.Bind(Keys.A, () => { moveDirection[0].X--; }); keyboardBinding.Bind(Keys.D, () => { moveDirection[0].X++; }); //Same with the mouse x and y axes mouseBinding.Bind(MState.XAxis, () => { var deltaTime = (float)gTime.ElapsedGameTime.TotalSeconds; //Compute new yaw from mouse delta x. float deltaYaw = 0; deltaYaw -= Mouse.GetState().X - MouseOrigin; yaw += deltaYaw * deltaTime * 0.1f; }); mouseBinding.Bind(MState.YAxis, () => { var deltaTime = (float)gTime.ElapsedGameTime.TotalSeconds; //Compute new pitch from mouse delta y. float deltaPitch = 0; deltaPitch -= Mouse.GetState().Y - MouseOrigin; pitch += deltaPitch * deltaTime * 0.1f; //Only reset on Y because we need BOTH x and y to evaluate before the reset happens Mouse.SetPosition(MouseOrigin, MouseOrigin); }); CharacterController = new KinematicCharacterController(simulation) { Position = new Vector3F(-0.5F, 0, 0.5F), Gravity = 10 }; gun = Game.Content.Load<Model>("gun"); Mouse.SetPosition(MouseOrigin, MouseOrigin); base.Initialize(); }
private static void AddDamping(Simulation simulation, RigidBody bodyA, RigidBody bodyB, float softness, float maxForce) { // Usually an AngularVelocityMotor rotates bodies, but in this case the // TargetVelocity is set to 0 (default). The AngularVelocityMotor acts as // a damping. AngularVelocityMotor damping = new AngularVelocityMotor { BodyA = bodyA, BodyB = bodyB, // A softness of 0 would make the joint stiff. A softness value > 0 is important to // mimic damping. Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(damping); }
/// <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> public static void Create(SkeletonPose skeletonPose, Ragdoll ragdoll, Simulation simulation) { 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, 0.4f, 0.55f), massFrame, material); ragdoll.BodyOffsets[pelvis] = new Pose(new Vector3F(0.0f, 0, 0)); var backLower = skeleton.GetIndex("Spine"); ragdoll.Bodies[backLower] = new RigidBody(new BoxShape(0.36f, 0.4f, 0.55f), massFrame, material); ragdoll.BodyOffsets[backLower] = new Pose(new Vector3F(0.18f, 0, 0)); var backUpper = skeleton.GetIndex("Spine2"); ragdoll.Bodies[backUpper] = new RigidBody(new BoxShape(0.5f, 0.4f, 0.65f), massFrame, material); ragdoll.BodyOffsets[backUpper] = new Pose(new Vector3F(0.25f, 0, 0)); var neck = skeleton.GetIndex("Neck"); ragdoll.Bodies[neck] = new RigidBody(new CapsuleShape(0.12f, 0.3f), massFrame, material); ragdoll.BodyOffsets[neck] = new Pose(new Vector3F(0.15f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); ragdoll.Bodies[neck].CollisionObject.Enabled = false; ragdoll.Bodies[head] = new RigidBody(new SphereShape(0.2f), massFrame, material); ragdoll.BodyOffsets[head] = new Pose(new Vector3F(0.15f, 0.02f, 0)); var armUpperLeft = skeleton.GetIndex("L_UpperArm"); ragdoll.Bodies[armUpperLeft] = new RigidBody(new CapsuleShape(0.12f, 0.6f), massFrame, material); ragdoll.BodyOffsets[armUpperLeft] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var armLowerLeft = skeleton.GetIndex("L_Forearm"); ragdoll.Bodies[armLowerLeft] = new RigidBody(new CapsuleShape(0.08f, 0.5f), massFrame, material); ragdoll.BodyOffsets[armLowerLeft] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var handLeft = skeleton.GetIndex("L_Hand"); ragdoll.Bodies[handLeft] = new RigidBody(new BoxShape(0.2f, 0.06f, 0.15f), massFrame, material); ragdoll.BodyOffsets[handLeft] = new Pose(new Vector3F(0.1f, 0, 0)); var armUpperRight = skeleton.GetIndex("R_UpperArm"); ragdoll.Bodies[armUpperRight] = new RigidBody(new CapsuleShape(0.12f, 0.6f), massFrame, material); ragdoll.BodyOffsets[armUpperRight] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var armLowerRight = skeleton.GetIndex("R_Forearm"); ragdoll.Bodies[armLowerRight] = new RigidBody(new CapsuleShape(0.08f, 0.5f), massFrame, material); ragdoll.BodyOffsets[armLowerRight] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var handRight = skeleton.GetIndex("R_Hand"); ragdoll.Bodies[handRight] = new RigidBody(new BoxShape(0.2f, 0.06f, 0.15f), massFrame, material); ragdoll.BodyOffsets[handRight] = new Pose(new Vector3F(0.1f, 0, 0)); var legUpperLeft = skeleton.GetIndex("L_Thigh1"); ragdoll.Bodies[legUpperLeft] = new RigidBody(new CapsuleShape(0.16f, 0.8f), massFrame, material); ragdoll.BodyOffsets[legUpperLeft] = new Pose(new Vector3F(0.4f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var legLowerLeft = skeleton.GetIndex("L_Knee2"); ragdoll.Bodies[legLowerLeft] = new RigidBody(new CapsuleShape(0.12f, 0.65f), massFrame, material); ragdoll.BodyOffsets[legLowerLeft] = new Pose(new Vector3F(0.32f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); //var footLeft = skeleton.GetIndex("L_Ankle1"); ragdoll.Bodies[footLeft] = new RigidBody(new BoxShape(0.20f, 0.5f, 0.3f), massFrame, material); ragdoll.BodyOffsets[footLeft] = new Pose(new Vector3F(0.16f, 0.15f, 0)); var legUpperRight = skeleton.GetIndex("R_Thigh"); ragdoll.Bodies[legUpperRight] = new RigidBody(new CapsuleShape(0.16f, 0.8f), massFrame, material); ragdoll.BodyOffsets[legUpperRight] = new Pose(new Vector3F(0.4f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var legLowerRight = skeleton.GetIndex("R_Knee"); ragdoll.Bodies[legLowerRight] = new RigidBody(new CapsuleShape(0.12f, 0.65f), massFrame, material); ragdoll.BodyOffsets[legLowerRight] = new Pose(new Vector3F(0.32f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var footRight = skeleton.GetIndex("R_Ankle"); ragdoll.Bodies[footRight] = new RigidBody(new BoxShape(0.20f, 0.5f, 0.3f), massFrame, material); ragdoll.BodyOffsets[footRight] = new Pose(new Vector3F(0.16f, 0.15f, 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 }
// Using a softness value > 0 is important to give the ragdoll a more natural movement and to // avoid jittering. public static void AddRagdoll(Simulation simulation, float scale, Vector3F ragdollPosition, float softness, bool addDamping) { // Ragdolls are usually used in games to create realistic death animations of // characters. The character is usually rendered using a skinned triangle mesh. // But in the physics simulation the body parts of the character are represented // using simple shapes, such as spheres, capsules, boxes, or convex polyhedra, // which are connected with joints. // The physics simulations computes how these parts collide and fall. The positions // and orientations are then read back each frame to update the animation of the // triangle mesh. // In this example the ragdoll is built from spheres, capsules and boxes. The // rigid bodies are created in code. In practice, ragdolls should be built using // external tools, such as a 3D modeler or a game editor. #region ----- Create rigid bodies for the most relevant body parts ----- // The density used for all bodies. const float density = 1000; BoxShape pelvisShape = new BoxShape(0.3f * scale, 0.22f * scale, 0.20f * scale); MassFrame pelvisMass = MassFrame.FromShapeAndDensity(pelvisShape, Vector3F.One, density, 0.01f, 3); RigidBody pelvis = new RigidBody(pelvisShape, pelvisMass, null) { Pose = new Pose(new Vector3F(0f, 0.01f * scale, -0.03f * scale) + ragdollPosition), }; simulation.RigidBodies.Add(pelvis); BoxShape torsoShape = new BoxShape(0.35f * scale, 0.22f * scale, 0.44f * scale); MassFrame torsoMass = MassFrame.FromShapeAndDensity(torsoShape, Vector3F.One, density, 0.01f, 3); RigidBody torso = new RigidBody(torsoShape, torsoMass, null) { Pose = new Pose(new Vector3F(0f, 0.01f * scale, -0.4f * scale) + ragdollPosition), }; simulation.RigidBodies.Add(torso); SphereShape headShape = new SphereShape(0.13f * scale); MassFrame headMass = MassFrame.FromShapeAndDensity(headShape, Vector3F.One, density, 0.01f, 3); RigidBody head = new RigidBody(headShape, headMass, null) { Pose = new Pose(new Vector3F(0f * scale, 0f, -0.776f * scale) + ragdollPosition), }; simulation.RigidBodies.Add(head); CapsuleShape upperArmShape = new CapsuleShape(0.08f * scale, 0.3f * scale); MassFrame upperArmMass = MassFrame.FromShapeAndDensity(upperArmShape, Vector3F.One, density, 0.01f, 3); RigidBody leftUpperArm = new RigidBody(upperArmShape, upperArmMass, null) { Pose = new Pose(new Vector3F(-0.32f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(leftUpperArm); RigidBody rightUpperArm = new RigidBody(upperArmShape, upperArmMass, null) { Pose = new Pose(new Vector3F(0.32f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(rightUpperArm); CapsuleShape lowerArmShape = new CapsuleShape(0.08f * scale, 0.4f * scale); MassFrame lowerArmMass = MassFrame.FromShapeAndDensity(lowerArmShape, Vector3F.One, density, 0.01f, 3); RigidBody leftLowerArm = new RigidBody(lowerArmShape, lowerArmMass, null) { Pose = new Pose(new Vector3F(-0.62f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(leftLowerArm); RigidBody rightLowerArm = new RigidBody(lowerArmShape, lowerArmMass, null) { Pose = new Pose(new Vector3F(0.62f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(rightLowerArm); CapsuleShape upperLegShape = new CapsuleShape(0.09f * scale, 0.5f * scale); MassFrame upperLegMass = MassFrame.FromShapeAndDensity(upperLegShape, Vector3F.One, density, 0.01f, 3); RigidBody leftUpperLeg = new RigidBody(upperLegShape, upperLegMass, null) { Pose = new Pose(new Vector3F(-0.10f * scale, 0.01f * scale, 0.233f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(leftUpperLeg); RigidBody rightUpperLeg = new RigidBody(upperLegShape, upperLegMass, null) { Pose = new Pose(new Vector3F(0.10f * scale, 0.01f * scale, 0.233f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(rightUpperLeg); CapsuleShape lowerLegShape = new CapsuleShape(0.08f * scale, 0.4f * scale); MassFrame lowerLegMass = MassFrame.FromShapeAndDensity(pelvisShape, Vector3F.One, density, 0.01f, 3); RigidBody leftLowerLeg = new RigidBody(lowerLegShape, lowerLegMass, null) { Pose = new Pose(new Vector3F(-0.11f * scale, 0.01f * scale, 0.7f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(leftLowerLeg); RigidBody rightLowerLeg = new RigidBody(lowerLegShape, lowerLegMass, null) { Pose = new Pose(new Vector3F(0.11f * scale, 0.01f * scale, 0.7f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; simulation.RigidBodies.Add(rightLowerLeg); BoxShape footShape = new BoxShape(0.12f * scale, 0.28f * scale, 0.07f * scale); MassFrame footMass = MassFrame.FromShapeAndDensity(footShape, Vector3F.One, density, 0.01f, 3); RigidBody leftFoot = new RigidBody(footShape, footMass, null) { Pose = new Pose(new Vector3F(-0.11f * scale, -0.06f * scale, 0.94f * scale) + ragdollPosition), }; simulation.RigidBodies.Add(leftFoot); RigidBody rightFoot = new RigidBody(footShape, footMass, null) { Pose = new Pose(new Vector3F(0.11f * scale, -0.06f * scale, 0.94f * scale) + ragdollPosition), }; simulation.RigidBodies.Add(rightFoot); #endregion #region ----- Add joints between body parts ----- float errorReduction = 0.3f; float maxForce = float.PositiveInfinity; Vector3F pelvisJointPosition = new Vector3F(0f, 0.026f * scale, -0.115f * scale) + ragdollPosition; HingeJoint pelvisJoint = new HingeJoint { BodyA = torso, BodyB = pelvis, AnchorPoseALocal = new Pose(torso.Pose.ToLocalPosition(pelvisJointPosition)), AnchorPoseBLocal = new Pose(pelvis.Pose.ToLocalPosition(pelvisJointPosition)), Minimum = -0.5f, Maximum = 1.1f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(pelvisJoint); Vector3F neckJointPosition = new Vector3F(0f, 0.026f * scale, -0.690f * scale) + ragdollPosition; HingeJoint neckJoint = new HingeJoint { BodyA = head, BodyB = torso, AnchorPoseALocal = new Pose(head.Pose.ToLocalPosition(neckJointPosition)), AnchorPoseBLocal = new Pose(torso.Pose.ToLocalPosition(neckJointPosition)), Minimum = -1f, Maximum = 1f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(neckJoint); Vector3F leftShoulderJointPosition = new Vector3F(-0.193f * scale, 0.056f * scale, -0.528f * scale) + ragdollPosition; Vector3F leftShoulderJointAxis = new Vector3F(0, -1, -1).Normalized; Matrix33F leftShoulderJointOrientation = new Matrix33F(); leftShoulderJointOrientation.SetColumn(0, leftShoulderJointAxis); leftShoulderJointOrientation.SetColumn(1, leftShoulderJointAxis.Orthonormal1); leftShoulderJointOrientation.SetColumn(2, leftShoulderJointAxis.Orthonormal2); BallJoint leftShoulderJoint = new BallJoint { BodyA = leftUpperArm, BodyB = torso, AnchorPositionALocal = leftUpperArm.Pose.ToLocalPosition(leftShoulderJointPosition), AnchorPositionBLocal = torso.Pose.ToLocalPosition(leftShoulderJointPosition), CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(leftShoulderJoint); Vector3F rightShoulderJointPosition = new Vector3F(0.193f * scale, 0.056f * scale, -0.528f * scale) + ragdollPosition; Vector3F rightShoulderJointAxis = new Vector3F(0, 1, 1).Normalized; Matrix33F rightShoulderJointOrientation = new Matrix33F(); rightShoulderJointOrientation.SetColumn(0, rightShoulderJointAxis); rightShoulderJointOrientation.SetColumn(1, rightShoulderJointAxis.Orthonormal1); rightShoulderJointOrientation.SetColumn(2, rightShoulderJointAxis.Orthonormal2); BallJoint rightShoulderJoint = new BallJoint { BodyA = rightUpperArm, BodyB = torso, AnchorPositionALocal = rightUpperArm.Pose.ToLocalPosition(rightShoulderJointPosition), AnchorPositionBLocal = torso.Pose.ToLocalPosition(rightShoulderJointPosition), CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(rightShoulderJoint); Vector3F leftElbowJointPosition = new Vector3F(-0.451f * scale, 0.071f * scale, -0.538f * scale) + ragdollPosition; Matrix33F elbowAxisOrientation = new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0); HingeJoint leftElbowJoint = new HingeJoint { BodyA = leftLowerArm, BodyB = leftUpperArm, AnchorPoseALocal = new Pose(leftLowerArm.Pose.ToLocalPosition(leftElbowJointPosition), leftLowerArm.Pose.Orientation.Inverse * elbowAxisOrientation), AnchorPoseBLocal = new Pose(leftUpperArm.Pose.ToLocalPosition(leftElbowJointPosition), leftUpperArm.Pose.Orientation.Inverse * elbowAxisOrientation), Minimum = -2, Maximum = 0, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(leftElbowJoint); Vector3F rightElbowJointPosition = new Vector3F(0.451f * scale, 0.071f * scale, -0.538f * scale) + ragdollPosition; HingeJoint rightElbowJoint = new HingeJoint { BodyA = rightLowerArm, BodyB = rightUpperArm, AnchorPoseALocal = new Pose(rightLowerArm.Pose.ToLocalPosition(rightElbowJointPosition), rightLowerArm.Pose.Orientation.Inverse * elbowAxisOrientation), AnchorPoseBLocal = new Pose(rightUpperArm.Pose.ToLocalPosition(rightElbowJointPosition), rightUpperArm.Pose.Orientation.Inverse * elbowAxisOrientation), Minimum = 0, Maximum = 2, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(rightElbowJoint); Vector3F leftHipJointPosition = new Vector3F(-0.107f * scale, 0.049f * scale, 0.026f * scale) + ragdollPosition; HingeJoint leftHipJoint = new HingeJoint { BodyA = pelvis, BodyB = leftUpperLeg, AnchorPoseALocal = new Pose(pelvis.Pose.ToLocalPosition(leftHipJointPosition)), AnchorPoseBLocal = new Pose(leftUpperLeg.Pose.ToLocalPosition(leftHipJointPosition), leftUpperLeg.Pose.Orientation.Inverse), Minimum = -0.1f, Maximum = 1.2f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(leftHipJoint); Vector3F rightHipJointPosition = new Vector3F(0.107f * scale, 0.049f * scale, 0.026f * scale) + ragdollPosition; HingeJoint rightHipJoint = new HingeJoint { BodyA = pelvis, BodyB = rightUpperLeg, AnchorPoseALocal = new Pose(pelvis.Pose.ToLocalPosition(rightHipJointPosition)), AnchorPoseBLocal = new Pose(rightUpperLeg.Pose.ToLocalPosition(rightHipJointPosition), rightUpperLeg.Pose.Orientation.Inverse), Minimum = -0.1f, Maximum = 1.2f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(rightHipJoint); Vector3F leftKneeJointPosition = new Vector3F(-0.118f * scale, -0.012f * scale, 0.439f * scale) + ragdollPosition; HingeJoint leftKneeJoint = new HingeJoint { BodyA = leftLowerLeg, BodyB = leftUpperLeg, AnchorPoseALocal = new Pose(leftLowerLeg.Pose.ToLocalPosition(leftKneeJointPosition)), AnchorPoseBLocal = new Pose(leftUpperLeg.Pose.ToLocalPosition(leftKneeJointPosition)), Minimum = 0, Maximum = 1.7f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(leftKneeJoint); Vector3F rightKneeJointPosition = new Vector3F(0.118f * scale, -0.012f * scale, 0.439f * scale) + ragdollPosition; HingeJoint rightKneeJoint = new HingeJoint { BodyA = rightLowerLeg, BodyB = rightUpperLeg, AnchorPoseALocal = new Pose(rightLowerLeg.Pose.ToLocalPosition(rightKneeJointPosition)), AnchorPoseBLocal = new Pose(rightUpperLeg.Pose.ToLocalPosition(rightKneeJointPosition)), Minimum = 0, Maximum = 1.7f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(rightKneeJoint); Vector3F leftAnkleJointPosition = new Vector3F(-0.118f * scale, -0.016f * scale, 0.861f * scale) + ragdollPosition; HingeJoint leftAnkleJoint = new HingeJoint { BodyA = leftFoot, BodyB = leftLowerLeg, AnchorPoseALocal = new Pose(leftFoot.Pose.ToLocalPosition(leftAnkleJointPosition)), AnchorPoseBLocal = new Pose(leftLowerLeg.Pose.ToLocalPosition(leftAnkleJointPosition), leftLowerLeg.Pose.Orientation.Inverse), Minimum = -0.4f, Maximum = 0.9f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(leftAnkleJoint); Vector3F rightAnkleJointPosition = new Vector3F(0.118f * scale, -0.016f * scale, 0.861f * scale) + ragdollPosition; HingeJoint rightAnkleJoint = new HingeJoint { BodyA = rightFoot, BodyB = rightLowerLeg, AnchorPoseALocal = new Pose(rightFoot.Pose.ToLocalPosition(rightAnkleJointPosition)), AnchorPoseBLocal = new Pose(rightLowerLeg.Pose.ToLocalPosition(rightAnkleJointPosition), rightLowerLeg.Pose.Orientation.Inverse), Minimum = -0.4f, Maximum = 0.9f, CollisionEnabled = false, ErrorReduction = errorReduction, Softness = softness, MaxForce = maxForce, }; simulation.Constraints.Add(rightAnkleJoint); #endregion #region ----- Add damping to improve stability ----- if (addDamping) { // Damping removes jiggling and improves stability. softness = 0.05f; maxForce = float.PositiveInfinity; AddDamping(simulation, pelvis, torso, softness, maxForce); AddDamping(simulation, torso, head, softness, maxForce); AddDamping(simulation, torso, leftUpperArm, softness, maxForce); AddDamping(simulation, leftUpperArm, leftLowerArm, softness, maxForce); AddDamping(simulation, torso, rightUpperArm, softness, maxForce); AddDamping(simulation, rightUpperArm, rightLowerArm, softness, maxForce); AddDamping(simulation, pelvis, leftUpperLeg, softness, maxForce); AddDamping(simulation, pelvis, rightUpperLeg, softness, maxForce); AddDamping(simulation, leftUpperLeg, leftLowerLeg, softness, maxForce); AddDamping(simulation, rightUpperLeg, rightLowerLeg, softness, maxForce); AddDamping(simulation, leftLowerLeg, leftFoot, softness, maxForce); AddDamping(simulation, rightLowerLeg, rightFoot, softness, maxForce); } #endregion }
// Creates a new rigid body and adds it to the simulation. private static RigidBody AddBody(Simulation simulation, string name, Pose pose, Shape shape, MotionType motionType) { var rigidBody = new RigidBody(shape) { Name = name, Pose = pose, MotionType = motionType, }; simulation.RigidBodies.Add(rigidBody); return rigidBody; }
//-------------------------------------------------------------- /// <summary> /// Resets this simulation island. /// </summary> internal void Clear() { Simulation = null; ConstraintsInternal.Clear(); ContactConstraintsInternal.Clear(); RigidBodiesInternal.Clear(); }
//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- public CharacterControllerObject(IServiceLocator services) { Name = "CharacterController"; _inputService = services.GetInstance<IInputService>(); _debugRenderer = services.GetInstance<DebugRenderer>(); _simulation = services.GetInstance<Simulation>(); // Create character controller. #if USE_DYNAMIC_CHARACTER_CONTROLLER CharacterController = new DynamicCharacterController(_simulation); #else CharacterController = new KinematicCharacterController(_simulation); #endif CharacterController.Enabled = false; CharacterController.Position = new Vector3F(0, 0, 10); CharacterController.Gravity = 10; // Setting gravity to 0 switches to fly mode (instead of walking). // Special: No gravity and damping for character controller. // The character controller uses a rigid body. The gravity and damping force effects // should not influence this body. The character controller handles gravity itself. // Gravity and Damping are ForceEffects. Each force effect has an AreaOfEffect which, // by default, is a GlobalAreaOfEffect (= affects all bodies in the simulation). We can // set a predicate method that excludes the rigid body of the character controller. GlobalAreaOfEffect areaOfEffect = new GlobalAreaOfEffect { Exclude = body => body == CharacterController.Body, }; _simulation.ForceEffects.OfType<Gravity>().First().AreaOfEffect = areaOfEffect; _simulation.ForceEffects.OfType<Damping>().First().AreaOfEffect = areaOfEffect; // Special: Collision filtering. // We will have some collision objects that should not collide with the character controller. // We will use collision group 3 for the character and 4 for objects that should not collide // with it. CharacterController.CollisionGroup = 3; ICollisionFilter filter = (ICollisionFilter)_simulation.CollisionDomain.CollisionDetection.CollisionFilter; filter.Set(3, 4, false); // Disable collisions between group 3 and 4. }
//-------------------------------------------------------------- #region Methods //-------------------------------------------------------------- protected override void OnLoad() { // Get common services and game objects. _graphicsService = _services.GetInstance<IGraphicsService>(); var content = _services.GetInstance<ContentManager>(); var scene = _services.GetInstance<IScene>(); _simulation = _services.GetInstance<Simulation>(); var gameObjectService = _services.GetInstance<IGameObjectService>(); _cameraObject = gameObjectService.Objects.OfType<CameraObject>().First(); _previousCameraFar = _cameraObject.CameraNode.Camera.Projection.Far; // Create a new terrain. var terrain = new Terrain(); _terrainTile = new TerrainTile(_graphicsService) { CellSize = 2, }; terrain.Tiles.Add(_terrainTile); var shadowMapEffect = content.Load<Effect>("DigitalRune/Terrain/TerrainShadowMap"); var gBufferEffect = content.Load<Effect>("DigitalRune/Terrain/TerrainGBuffer"); var materialEffect = content.Load<Effect>("DigitalRune/Terrain/TerrainMaterial"); var material = new Material { { "ShadowMap", new EffectBinding(_graphicsService, shadowMapEffect, null, EffectParameterHint.Material) }, { "GBuffer", new EffectBinding(_graphicsService, gBufferEffect, null, EffectParameterHint.Material) }, { "Material", new EffectBinding(_graphicsService, materialEffect, null, EffectParameterHint.Material) } }; TerrainNode = new TerrainNode(terrain, material) { BaseClipmap = { CellsPerLevel = 128, NumberOfLevels = 6, }, DetailClipmap = { CellsPerLevel = 1364, NumberOfLevels = 9, }, }; scene.Children.Add(TerrainNode); // Create a rigid body with a height field for collision detection. var heightField = new HeightField { Depth = 1, UseFastCollisionApproximation = false, }; _rigidBody = new RigidBody(heightField, new MassFrame(), null) { MotionType = MotionType.Static, UserData = _terrainTile, }; _simulation.RigidBodies.Add(_rigidBody); InitializeHeightsAndNormals(); InitializeClipmapCellSizes(); InitializeTerrainLayers(content); // Enable mipmaps when using anisotropic filtering on AMD graphics cards: //TerrainNode.DetailClipmap.EnableMipMap = true; CreateGuiControls(); }
//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- public VehicleObject(IServiceLocator services) { _services = services; Name = "Vehicle"; _inputService = _services.GetInstance<IInputService>(); _simulation = _services.GetInstance<Simulation>(); // Load models for rendering. var contentManager = _services.GetInstance<ContentManager>(); _vehicleModelNode = contentManager.Load<ModelNode>("Car/Car").Clone(); _wheelModelNodes = new ModelNode[4]; _wheelModelNodes[0] = contentManager.Load<ModelNode>("Car/Wheel").Clone(); _wheelModelNodes[1] = _wheelModelNodes[0].Clone(); _wheelModelNodes[2] = _wheelModelNodes[0].Clone(); _wheelModelNodes[3] = _wheelModelNodes[0].Clone(); // Add wheels under the car model node. _vehicleModelNode.Children.Add(_wheelModelNodes[0]); _vehicleModelNode.Children.Add(_wheelModelNodes[1]); _vehicleModelNode.Children.Add(_wheelModelNodes[2]); _vehicleModelNode.Children.Add(_wheelModelNodes[3]); // ----- Create the chassis of the car. // The Vehicle needs a rigid body that represents the chassis. This can be any shape (e.g. // a simple BoxShape). In this example we will build a convex polyhedron from the car model. // 1. Extract the vertices from the car model. // The car model has ~10,000 vertices. It consists of a MeshNode for the glass // parts and a MeshNode "Car" for the chassis. var meshNode = _vehicleModelNode.GetDescendants() .OfType<MeshNode>() .First(mn => mn.Name == "Car"); var mesh = MeshHelper.ToTriangleMesh(meshNode.Mesh); // Apply the transformation of the mesh node. mesh.Transform(meshNode.PoseWorld * Matrix44F.CreateScale(meshNode.ScaleWorld)); // 2. (Optional) Create simplified convex hull from mesh. // We could also skip this step and directly create a convex polyhedron from the mesh using // var chassisShape = new ConvexPolyhedron(mesh.Vertices); // However, the convex polyhedron would still have 500-600 vertices. // We can reduce the number of vertices by using the GeometryHelper. // Create a convex hull for mesh with max. 64 vertices. Additional, shrink the hull by 4 cm. var convexHull = GeometryHelper.CreateConvexHull(mesh.Vertices, 64, -0.04f); // 3. Create convex polyhedron shape using the vertices of the convex hull. var chassisShape = new ConvexPolyhedron(convexHull.Vertices.Select(v => v.Position)); // (Note: Building convex hulls and convex polyhedra are time-consuming. To save loading time // we should build the shape in the XNA content pipeline. See other DigitalRune Physics // Samples.) // The mass properties of the car. We use a mass of 800 kg. var mass = MassFrame.FromShapeAndMass(chassisShape, Vector3F.One, 800, 0.1f, 1); // Trick: We artificially modify the center of mass of the rigid body. Lowering the center // of mass makes the car more stable against rolling in tight curves. // We could also modify mass.Inertia for other effects. var pose = mass.Pose; pose.Position.Y -= 0.5f; // Lower the center of mass. pose.Position.Z = -0.5f; // The center should be below the driver. // (Note: The car model is not exactly centered.) mass.Pose = pose; // Material for the chassis. var material = new UniformMaterial { Restitution = 0.1f, StaticFriction = 0.2f, DynamicFriction = 0.2f }; var chassis = new RigidBody(chassisShape, mass, material) { Pose = new Pose(new Vector3F(0, 2, 0)), // Start position UserData = "NoDraw", // (Remove this line to render the collision model.) }; // ----- Create the vehicle. Vehicle = new Vehicle(_simulation, chassis); // Add 4 wheels. Vehicle.Wheels.Add(new Wheel { Offset = new Vector3F(-0.9f, 0.6f, -2.0f), Radius = 0.36f, SuspensionRestLength = 0.55f, MinSuspensionLength = 0.25f, Friction = 2 }); // Front left Vehicle.Wheels.Add(new Wheel { Offset = new Vector3F(0.9f, 0.6f, -2.0f), Radius = 0.36f, SuspensionRestLength = 0.55f, MinSuspensionLength = 0.25f, Friction = 2 }); // Front right Vehicle.Wheels.Add(new Wheel { Offset = new Vector3F(-0.9f, 0.6f, 0.98f), Radius = 0.36f, SuspensionRestLength = 0.55f, MinSuspensionLength = 0.25f, Friction = 1.8f });// Back left Vehicle.Wheels.Add(new Wheel { Offset = new Vector3F(0.9f, 0.6f, 0.98f), Radius = 0.36f, SuspensionRestLength = 0.55f, MinSuspensionLength = 0.25f, Friction = 1.8f }); // Back right // Vehicles are disabled per default. This way we can create the vehicle and the simulation // objects are only added when needed. Vehicle.Enabled = false; }
public void ResetPhysicsSimulation() { _simulation = new Simulation(); // Limit max. number of internal simulation steps to 2. // (Simulation.Settings.Timing.FixedTimeStep is 1/60 s per default. If the game is // running with 60 fps, Simulation.Update() internally makes on simulation step. If // the game is running with 30 fps, Simulation.Update() makes two internal steps with // 1/60s. If the game is running with less than 30 fps, the simulation will run in // slow motion because more than 2 internal steps would have to be made but the // limit is two. - This way the game will not freeze.) _simulation.Settings.Timing.MaxNumberOfSteps = 2; // When the simulation is updated with Simulation.Update() the collision detection is // updated first and then the physics simulation computes new forces, velocities and // positions. That means, that after Simulation.Update() the collision detection information // (Simulation.CollisionDomain) is not up-to-date! If we manually query the collision // detection using Simulation.CollisionDomain, then we can set the SynchronizeCollisionDomain // flag. If this flag is set, the collision detection info is updated at the beginning // and at the end of Simulation.Update(). //Simulation.Settings.SynchronizeCollisionDomain = true; // The collision domain computes collision information between non-moving bodies only once // and caches this information - in case someone wants to check if two static bodies touch. // Nevertheless, on less powerful systems, like the Xbox 360, it can still improve performance // to filter collisions between static bodies. This can be done in a broad phase filter based // on collision groups, or with a simple filter like this: _simulation.CollisionDomain.BroadPhase.Filter = new DelegatePairFilter<CollisionObject>( pair => { var bodyA = pair.First.GeometricObject as RigidBody; if (bodyA == null || bodyA.MotionType != MotionType.Static) return true; var bodyB = pair.Second.GeometricObject as RigidBody; if (bodyB == null || bodyB.MotionType != MotionType.Static) return true; return false; // Do not compute collisions between two static bodies. }); // Another way to filter collisions is to use the CollisionDetection.CollisionFilter. // Filtering on this level is slower because the filter is applied after the broad phase and // the broad phase filter. However, it is more flexible. It can be changed at runtime, whereas // a broad phase filter should not change after the simulation was initialized. var filter = (ICollisionFilter)_simulation.CollisionDomain.CollisionDetection.CollisionFilter; // We can disable collision for pairs of collision objects or for collision groups. Here, // we disable collisions between collision group 1 and 2. The ray for mouse picking will // use collision group 2 (see GrabObject.cs). Any objects that should not be pickable can use // collision group 1. filter.Set(1, 2, false); _services.Register(typeof(Simulation), null, _simulation); }