protected override void OnUpdate(TimeSpan deltaTime) { // A random new wind change is chosen at regular intervals. const float WindInterval = 3; _timeSinceWindChange += (float)deltaTime.TotalSeconds; if (_timeSinceWindChange > WindInterval) { _lastAngle = _nextAngle; _lastSpeed = _nextSpeed; _timeSinceWindChange = 0; // Get random target angle. float a = RandomHelper.Random.NextFloat(-1, 1); // Apply non-linear curve to make smaller changes more likely. a = (float)Math.Pow(a, 3); // Convert to angle and limit variation. _nextAngle = _lastAngle + ConstantsF.PiOver2 * a * DirectionVariation; // Get random target speed. float s = RandomHelper.Random.NextFloat(0, 1); _nextSpeed = MaxSpeed * (1 - s * SpeedVariation); } // Update current wind. float p = _timeSinceWindChange / WindInterval; float speed = InterpolationHelper.Lerp(_lastSpeed, _nextSpeed, p); float angle = InterpolationHelper.Lerp(_lastAngle, _nextAngle, p); Wind = speed * Matrix33F.CreateRotationY(angle) * Vector3F.UnitX; }
private void SetCameraPose() { var vehiclePose = _vehicle.Pose; if (_useSpectatorView) { // Spectator Mode: // Camera is looking at the car from a fixed location in the level. Vector3F position = new Vector3F(10, 8, 10); Vector3F target = vehiclePose.Position; Vector3F up = Vector3F.UnitY; // Set the new camera view matrix. (Setting the View matrix changes the Pose. // The pose is simply the inverse of the view matrix). CameraNode.View = Matrix44F.CreateLookAt(position, target, up); } else { // Player Camera: // Camera moves with the car. The look direction can be changed by moving the mouse. Matrix33F yaw = Matrix33F.CreateRotationY(_yaw); Matrix33F pitch = Matrix33F.CreateRotationX(_pitch); Matrix33F orientation = vehiclePose.Orientation * yaw * pitch; Vector3F forward = orientation * -Vector3F.UnitZ; Vector3F up = Vector3F.UnitY; Vector3F position = vehiclePose.Position - 10 * forward + 5 * up; Vector3F target = vehiclePose.Position + 1 * up; CameraNode.View = Matrix44F.CreateLookAt(position, target, up); } }
public SkeletonMappingSample(Microsoft.Xna.Framework.Game game) : base(game) { // Get dude model and start animation on the dude. var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _dudeMeshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _dudeMeshNode.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(_dudeMeshNode); GraphicsScreen.Scene.Children.Add(_dudeMeshNode); var animations = _dudeMeshNode.Mesh.Animations; var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_dudeMeshNode.SkeletonPose); // Get marine model - do not start any animations on the marine model. modelNode = ContentManager.Load <ModelNode>("Marine/PlayerMarine"); _marineMeshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _marineMeshNode.PoseLocal = new Pose(new Vector3F(0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(_marineMeshNode); GraphicsScreen.Scene.Children.Add(_marineMeshNode); CreateSkeletonMapper(); }
public BoneJiggleSample(Microsoft.Xna.Framework.Game game) : base(game) { var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); var animations = _meshNode.Mesh.Animations; var walkAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; _walkAnimationController = AnimationService.StartAnimation(walkAnimation, (IAnimatableProperty)_meshNode.SkeletonPose); _walkAnimationController.AutoRecycle(); // Create a BoneJiggler instance for the head bone (bone index 7). _boneJiggler = new BoneJiggler(_meshNode.SkeletonPose, 7, new Vector3F(1.1f, 0, 0)) { Spring = 100, Damping = 3, }; }
public SkinnedEffectSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; GraphicsScreen.ClearBackground = true; GraphicsScreen.BackgroundColor = Color.CornflowerBlue; SetCamera(new Vector3F(1, 1, 3), 0.2f, 0); // Create a sky mesh and add an instance of this mesh to the scene. var skyMesh = ProceduralSkyDome.CreateMesh(GraphicsService, ContentManager.Load <Texture2D>("sky")); _sky = new MeshNode(skyMesh); _sky.Name = "Sky"; // Always set a name - very useful for debugging! GraphicsScreen.Scene.Children.Add(_sky); // Load the skinned model. This model is processed using the DigitalRune Model // Processor - not the default XNA model processor! // In the folder that contains dude.fbx, there are several XML files (*.drmdl and *.drmat) // which define the materials of the model. These material description files are // automatically processed by the DigitalRune Model Processor. Please browse // to the content folder and have a look at the *.drmdl and *.drmat files. var dudeModel = ContentManager.Load <ModelNode>("Dude/Dude"); dudeModel = dudeModel.Clone(); dudeModel.PoseWorld = new Pose(Matrix33F.CreateRotationY(ConstantsF.Pi)); GraphicsScreen.Scene.Children.Add(dudeModel); // The dude model consists of a single mesh. var dudeMeshNode = dudeModel.GetSubtree().OfType <MeshNode>().First(); var mesh = dudeMeshNode.Mesh; /* * // The dude mesh consists of different materials (head, eyes, torso, ...). * // We could change some of the material properties... * foreach (var material in mesh.Materials) * { * // Get all SkinnedEffectBindings which wrap the XNA SkinnedEffect. * // A material can consist of several effects - one effect for each render pass. * // (Per default there is only one render pass called "Default".) * foreach (var effectBinding in material.EffectBindings.OfType<SkinnedEffectBinding>()) * { * // We could change effect parameters here, for example: * effectBinding.PreferPerPixelLighting = true; * } * } */ // The DigitalRune Model Processor also loads animations. // Start the first animation of the dude and let it loop forever. // (We keep the animation controller to be able to stop the animation in // Dispose() below.) var timeline = new TimelineClip(mesh.Animations.Values.First()) { Duration = TimeSpan.MaxValue, LoopBehavior = LoopBehavior.Cycle, }; _animationController = AnimationService.StartAnimation(timeline, (IAnimatableProperty)dudeMeshNode.SkeletonPose); }
public SkySample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics Simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new GroundObject(Services)); GameObjectService.Objects.Add(new DudeObject(Services)); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); GameObjectService.Objects.Add(new LavaBallsObject(Services)); GameObjectService.Objects.Add(new FogObject(Services)); GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Barrier", 0.9f, new Pose(new Vector3F(0, 0, -2)))); GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Cylinder", 0.9f, new Pose(new Vector3F(3, 0, 0), QuaternionF.CreateRotationY(MathHelper.ToRadians(-20))))); // The DynamicSkyObject creates the dynamic sky and lights. GameObjectService.Objects.Add(new DynamicSkyObject(Services)); // Add a few palm trees. Random random = new Random(12345); for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation))); } // Add a grain filter to add some noise in the night. _graphicsScreen.PostProcessors.Add(new GrainFilter(GraphicsService) { IsAnimated = true, LuminanceThreshold = 0.3f, ScaleWithLuminance = true, Strength = 0.04f, GrainScale = 1.5f, }); }
public SplitScreenSample(Microsoft.Xna.Framework.Game game) : base(game) { _graphicsScreen = new SplitScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics Simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera of player A. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNodeA = cameraGameObject.CameraNode; var projection = (PerspectiveProjection)cameraGameObject.CameraNode.Camera.Projection; projection.SetFieldOfView( projection.FieldOfViewY, GraphicsService.GraphicsDevice.Viewport.AspectRatio / 2, projection.Near, projection.Far); cameraGameObject.CameraNode.Camera = new Camera(projection); // A second camera for player B. _cameraNodeB = new CameraNode(cameraGameObject.CameraNode.Camera); _graphicsScreen.ActiveCameraNodeB = _cameraNodeB; GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new GroundObject(Services)); GameObjectService.Objects.Add(new DudeObject(Services)); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); GameObjectService.Objects.Add(new LavaBallsObject(Services)); GameObjectService.Objects.Add(new FogObject(Services)); GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Barrier", 0.9f, new Pose(new Vector3F(0, 0, -2)))); GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Cylinder", 0.9f, new Pose(new Vector3F(3, 0, 0), QuaternionF.CreateRotationY(MathHelper.ToRadians(-20))))); GameObjectService.Objects.Add(new StaticSkyObject(Services)); // Add a few palm trees. Random random = new Random(12345); for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation))); } GameObjectService.Objects.Add(new OptionsObject(Services)); }
public WaterFallSample(Microsoft.Xna.Framework.Game game) : base(game) { _particleSystem = WaterFall.CreateWaterFall(ContentManager); _particleSystem.Pose = new Pose(new Vector3F(0, 2, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); ParticleSystemService.ParticleSystems.Add(_particleSystem); _particleSystemNode = new ParticleSystemNode(_particleSystem); GraphicsScreen.Scene.Children.Add(_particleSystemNode); }
public FlameJetSample(Microsoft.Xna.Framework.Game game) : base(game) { _flameJet = FlameJet.Create(ContentManager); _flameJet.Pose = new Pose(new Vector3F(0, 2, 0), Matrix33F.CreateRotationY(ConstantsF.PiOver2)); ParticleSystemService.ParticleSystems.Add(_flameJet); _particleSystemNode = new ParticleSystemNode(_flameJet); GraphicsScreen.Scene.Children.Add(_particleSystemNode); }
public CollisionDetectionOnlyRagdollSample(Microsoft.Xna.Framework.Game game) : base(game) { GraphicsScreen.DrawReticle = true; SetCamera(new Vector3F(0, 1, 6), 0, 0); // Add a game object which allows to shoot balls. _ballShooterObject = new BallShooterObject(Services); GameObjectService.Objects.Add(_ballShooterObject); var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); var animations = _meshNode.Mesh.Animations; var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose); // Create a ragdoll for the Dude model. _ragdoll = new Ragdoll(); DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f); // Set the world space pose of the whole ragdoll. _ragdoll.Pose = _meshNode.PoseWorld; // And copy the bone poses of the current skeleton pose. _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose); foreach (var body in _ragdoll.Bodies) { if (body != null) { // Set all bodies to kinematic - they should not be affected by forces. body.MotionType = MotionType.Kinematic; // Disable collision response. body.CollisionResponseEnabled = false; } } // In this sample, we do not need joints, limits or motors. _ragdoll.DisableJoints(); _ragdoll.DisableLimits(); _ragdoll.DisableMotors(); // Add ragdoll rigid bodies to the simulation. _ragdoll.AddToSimulation(Simulation); }
public override void Update(GameTime gameTime) { // This sample clears the debug renderer each frame. _graphicsScreen.DebugRenderer.Clear(); // A second camera for player B. var totalTime = (float)gameTime.TotalGameTime.TotalSeconds; var position = Matrix33F.CreateRotationY(totalTime * 0.1f) * new Vector3F(4, 2, 4); _cameraNodeB.View = Matrix44F.CreateLookAt(position, new Vector3F(0, 0, 0), new Vector3F(0, 1, 0)); }
public void CreateRotationY() { float angle = (float)MathHelper.ToRadians(30); Matrix33F m = Matrix33F.CreateRotationY(angle); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F((float)Math.Sin(angle), 0, (float)Math.Cos(angle)), m * Vector3F.UnitZ)); QuaternionF q = QuaternionF.CreateRotation(Vector3F.UnitY, angle); Assert.IsTrue(Vector3F.AreNumericallyEqual(q.Rotate(Vector3F.One), m * Vector3F.One)); Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.CreateRotation(Vector3F.UnitY, angle), m)); }
public override void Update(GameTime gameTime) { // Update the poses of the animated scene nodes. var frontWheelSteeringRotation = Matrix33F.CreateRotationY(_frontWheelSteeringAngle.Value); _frontWheelLeft.PoseLocal = _frontWheelLeftRestPose * new Pose(frontWheelSteeringRotation); _frontWheelRight.PoseLocal = _frontWheelRightRestPose * new Pose(frontWheelSteeringRotation); _hatch.PoseLocal = _hatchRestPose * new Pose(Matrix33F.CreateRotationX(_hatchAngle.Value)); _turret.PoseLocal = _turretRestPose * new Pose(Matrix33F.CreateRotationY(_turretAngle.Value)); _cannon.PoseLocal = _cannonRestPose * new Pose(Matrix33F.CreateRotationX(_cannonAngle.Value)); base.Update(gameTime); }
protected override void OnUpdate(TimeSpan deltaTime) { // Rotate camera around origin. _cameraRotation += 0.1f * (float)deltaTime.TotalSeconds; var cameraPosition = Matrix33F.CreateRotationY(_cameraRotation) * new Vector3F(10, 5, 10); var targetPosition = new Vector3F(0, 1, 0); var up = new Vector3F(0, 1, 0); var viewMatrix = Matrix44F.CreateLookAt(cameraPosition, targetPosition, up); CameraNode.PoseWorld = Pose.FromMatrix(viewMatrix.Inverse); Scene.Update(deltaTime); }
protected override void OnUpdate(TimeSpan deltaTime) { // Mouse centering (controlled by the MenuComponent) is disabled if the game // is inactive or if the GUI is active. In these cases, we do not want to move // the player. if (!_inputService.EnableMouseCentering) { return; } float deltaTimeF = (float)deltaTime.TotalSeconds; // Update steering direction from left/right arrow keys. UpdateSteeringAngle(deltaTimeF); // Update acceleration from up/down arrow keys. UpdateAcceleration(deltaTimeF); // Pressing <Space> activates handbrake if (_inputService.IsDown(Keys.Space) || _inputService.IsDown(Buttons.A, LogicalPlayerIndex.One)) { // Braking force from handbrake needs to be applied to back wheels. const float brakeForce = 6000; Vehicle.Wheels[2].MotorForce = 0; Vehicle.Wheels[3].MotorForce = 0; Vehicle.Wheels[2].BrakeForce = brakeForce; Vehicle.Wheels[3].BrakeForce = brakeForce; } else { Vehicle.Wheels[2].BrakeForce = 0; Vehicle.Wheels[3].BrakeForce = 0; } // Update poses of graphics models. // Update SceneNode.LastPoseWorld (required for optional effects, like motion blur). _vehicleModelNode.SetLastPose(true); _vehicleModelNode.PoseWorld = Vehicle.Chassis.Pose; for (int i = 0; i < _wheelModelNodes.Length; i++) { var pose = Vehicle.Wheels[i].Pose; if (Vehicle.Wheels[i].Offset.X < 0) { // Left wheel. pose.Orientation = pose.Orientation * Matrix33F.CreateRotationY(ConstantsF.Pi); } _wheelModelNodes[i].SetLastPose(true); _wheelModelNodes[i].PoseWorld = pose; } }
/// <summary> /// Adds test objects (walls, palm trees, ...) to the scene. /// </summary> private void AddTestObjects() { // Add a few palm trees. Random random = new Random(12345); for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(3.5f, 0, 2.5f - i / 2.0f); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); Pose pose = _globalRotation * new Pose(position, orientation); GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, pose)); } // Add a vertical concrete wall. GameObjectService.Objects.Add( new StaticObject( Services, "Building/concrete_small_window_1", #if XNA new Vector3F(1.0f, 1.6f, 1.8f), _globalRotation * new Pose(new Vector3F(3.5f, 1.8f, -4f), Matrix33F.CreateRotationY(0)), #else new Vector3F(1.8f, 1.6f, 1.0f), _globalRotation * new Pose(new Vector3F(3.5f, 1.8f, -4f), Matrix33F.CreateRotationY(ConstantsF.PiOver2)), #endif true, false)); // Add a vertical brick wall. GameObjectService.Objects.Add( new StaticObject( Services, "Building/wall_brick_1", new Vector3F(1.8f, 1.6f, 1), _globalRotation * new Pose(new Vector3F(-3f, 1.8f, -4f), Matrix33F.CreateRotationY(ConstantsF.PiOver2)), true, false)); // Create a ceiling using a rotated wall. GameObjectService.Objects.Add( new StaticObject( Services, "Building/wall_brick_1", new Vector3F(1.8f, 2.8f, 1), _globalRotation * new Pose(new Vector3F(0.3f, 4, -4), Matrix33F.CreateRotationZ(ConstantsF.PiOver2) * Matrix33F.CreateRotationY(ConstantsF.PiOver2)), true, false)); }
public override void Update(GameTime gameTime) { // Move models in circles. _angle += (float)gameTime.ElapsedGameTime.TotalSeconds * 0.6f; // Set SceneNode.LastPoseWorld to the current pose. This is only required // when advanced effects are used, like post-process motion blur. Since this // is not the case in this sample, we could skip this step. However, it is a // good practice to always update SceneNode.LastPoseWorld and LastScaleWorld // before the pose or scale is changed. _model0.SetLastPose(true); _model1.SetLastPose(true); // Update the position and orientation of the models. _model0.PoseWorld = new Pose(new Vector3F(2, 0, 0)) * new Pose(Matrix33F.CreateRotationY(_angle)) * new Pose(new Vector3F(2, 0, 0)); _model1.PoseWorld = new Pose(new Vector3F(-2, 0, 0)) * new Pose(Matrix33F.CreateRotationY(-_angle + 0.5f)) * new Pose(new Vector3F(-2, 0, 0)); // Draw the bounding shapes of the meshes. // // Note - Bounding shapes of skinned models: // The model description file (dude.drmdl) specifies a custom bounding shape // (see the attributes AabbMinimum and AabbMaximum in this file). For // skinned models this bounding shape must be chosen manually. It must be big // enough to contain all poses of the model. - In future DigitalRune Graphics // versions we will automatically compute suitable bounding shapes for // animated models. _debugRenderer.Clear(); foreach (var sceneNode in _scene.GetSubtree().OfType <MeshNode>()) { _debugRenderer.DrawObject(sceneNode, Color.Orange, true, false); } // Draw a coordinate cross at the world space origin. _debugRenderer.DrawAxes(Pose.Identity, 1, false); // Update the scene - this must be called once per frame. // The scene will compute internal collision information for camera frustum // culling or light culling (which lights overlap with which mesh nodes). _scene.Update(gameTime.ElapsedGameTime); base.Update(gameTime); }
public DudeWalkingSample(Microsoft.Xna.Framework.Game game) : base(game) { var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); var meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(meshNode); GraphicsScreen.Scene.Children.Add(meshNode); // The imported animations are stored in the mesh. Dictionary <string, SkeletonKeyFrameAnimation> animations = meshNode.Mesh.Animations; // The Dude model contains only one animation, which is a SkeletonKeyFrameAnimation with // a walk cycle. SkeletonKeyFrameAnimation walkAnimation = animations.Values.First(); // Wrap the walk animation in an animation clip that loops the animation forever. AnimationClip <SkeletonPose> loopingAnimation = new AnimationClip <SkeletonPose>(walkAnimation) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; // Start the animation and keep the created AnimationController. // We must cast the SkeletonPose to IAnimatableProperty because SkeletonPose implements // IAnimatableObject and IAnimatableProperty. We must tell the AnimationService if we want // to animate an animatable property of the SkeletonPose (IAnimatableObject), or if we want to // animate the whole SkeletonPose (IAnimatableProperty). _animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)meshNode.SkeletonPose); // The animation will be applied the next time AnimationManager.ApplyAnimations() is called // in the main loop. ApplyAnimations() is called before this method is called, therefore // the model will be rendered in the bind pose in this frame and in the first animation key // frame in the next frame - this creates an annoying visual popping effect. // We can avoid this if we call AnimationController.UpdateAndApply(). This will immediately // change the model pose to the first key frame pose. _animationController.UpdateAndApply(); // (Optional) Enable Auto-Recycling: // After the animation is stopped, the animation service will recycle all // intermediate data structures. _animationController.AutoRecycle(); }
public AutoRagdollShapesSample(Microsoft.Xna.Framework.Game game) : base(game) { var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); var animations = _meshNode.Mesh.Animations; var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose); animationController.AutoRecycle(); animationController.UpdateAndApply(); // Create a ragdoll for the Dude model. _ragdoll = CreateRagdoll(_meshNode); // Set the world space pose of the whole ragdoll. _ragdoll.Pose = _meshNode.PoseWorld; // And copy the bone poses of the current skeleton pose. _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose); foreach (var body in _ragdoll.Bodies) { if (body != null) { // Set all bodies to kinematic - they should not be affected by forces. body.MotionType = MotionType.Kinematic; // Disable collision response. body.CollisionResponseEnabled = false; } } // Add ragdoll rigid bodies to the simulation. _ragdoll.AddToSimulation(Simulation); }
private void UpdateOrientation(Vector delta) { Pose pose = _cameraNode.PoseWorld; // Get previous yaw and pitch angles. float yaw, pitch; GetYawPitch(pose.Orientation, out yaw, out pitch); // Apply delta. float speed = (float)Speed; yaw -= (float)delta.X * speed; pitch -= (float)delta.Y * speed; // Set new camera orientation. pose.Orientation = Matrix33F.CreateRotationY(yaw) * Matrix33F.CreateRotationX(pitch); _cameraNode.PoseWorld = pose; }
public CompressionSample(Microsoft.Xna.Framework.Game game) : base(game) { var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); SampleHelper.EnablePerPixelLighting(modelNode); _meshNodeUncompressed = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNodeUncompressed.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); GraphicsScreen.Scene.Children.Add(_meshNodeUncompressed); _meshNodeCompressed = _meshNodeUncompressed.Clone(); _meshNodeCompressed.PoseLocal = new Pose(new Vector3F(0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi)); GraphicsScreen.Scene.Children.Add(_meshNodeCompressed); Dictionary <string, SkeletonKeyFrameAnimation> animations = _meshNodeUncompressed.Mesh.Animations; _animation = animations.Values.First(); RestartAnimations(); }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); AnimationService.StartAnimation(_walkAnimation, _avatarPose).AutoRecycle(); } } else { // Update pose of attached baseball bat. // The offset of the baseball bat origin to the bone origin (in bone space) Pose offset = new Pose(new Vector3F(0.01f, 0.05f, 0.0f), Matrix33F.CreateRotationY(MathHelper.ToRadians(-20))); // The bone position in model space SrtTransform bonePose = _avatarPose.SkeletonPose.GetBonePoseAbsolute((int)AvatarBone.SpecialRight); // The baseball bat matrix in world space _baseballBatMeshNode.PoseWorld = _pose * (Pose)bonePose * offset; } }
protected override void OnLoad() { var contentManager = _services.GetInstance <ContentManager>(); // ----- Graphics // Load graphics model (created using the ModelWithCollisionMeshProcessor). var originalModelNode = contentManager.Load <ModelNode>("Saucer/saucer"); // The collision shape is stored in the UserData. var shape = (Shape)originalModelNode.UserData; // We do not want to change the shared Saucer instance in the content manager. // Let's create a clone. But we do not want to clone the shape in the UserData, // this would be a waste of time and memory. originalModelNode.UserData = null; _modelNode = originalModelNode.Clone(); // Clone without UserData. originalModelNode.UserData = shape; _modelNode.PoseWorld = new Pose(Vector3F.Zero, Matrix33F.CreateRotationY(-ConstantsF.PiOver2)); // Add model to the scene for rendering. var scene = _services.GetInstance <IScene>(); scene.Children.Add(_modelNode); // ----- Collision Detection // Create a collision object and add it to the collision domain. _geometricObject = new GeometricObject(shape, _modelNode.PoseWorld); _collisionObject = new CollisionObject(_geometricObject); // Important: We do not need detailed contact information when a collision // is detected. The information of whether we have contact or not is sufficient. // Therefore, we can set the type to "Trigger". This increases the performance // dramatically. _collisionObject.Type = CollisionObjectType.Trigger; var collisionDomain = _services.GetInstance <CollisionDomain>(); collisionDomain.CollisionObjects.Add(_collisionObject); }
public void Orthogonalize() { var m = Matrix33F.CreateRotationX(0.1f) * Matrix33F.CreateRotationY(20) * Matrix33F.CreateRotationZ(1000); // Introduce error. m.M01 += 0.1f; m.M22 += 0.1f; Assert.IsFalse(m.IsOrthogonal); Assert.IsFalse(m.IsRotation); m.Orthogonalize(); Assert.IsTrue(m.IsOrthogonal); Assert.IsTrue(m.IsRotation); // Orthogonalizing and orthogonal matrix does not change the matrix. var n = m; n.Orthogonalize(); Assert.IsTrue(Matrix33F.AreNumericallyEqual(m, n)); }
private void OnMouseMove(object sender, MouseEventArgs eventArgs) { var mousePosition = eventArgs.GetPosition(AssociatedObject); if (eventArgs.LeftButton == MouseButtonState.Pressed) { var target = CameraTarget; float speed = (float)Speed; Vector delta = mousePosition - _lastMousePosition; // Rotation around y-axis in world space float angle0 = (float)delta.X * speed * _upDirection; Pose rotation0 = new Pose(Matrix33F.CreateRotationY(angle0)); // Rotation around x-axis in view space. float angle1 = (float)delta.Y * speed; Pose rotation1 = new Pose(Matrix33F.CreateRotationX(angle1)); float distance = (CameraTarget - _cameraNode.PoseWorld.Position).Length; // Variant #1: Set camera pose. var pose = new Pose(target) * rotation0.Inverse * new Pose(-target) * _cameraNode.PoseWorld * new Pose(new Vector3F(0, 0, -distance)) * rotation1.Inverse * new Pose(new Vector3F(0, 0, distance)); // Re-orthogonalize to remove numerical errors which could add up. var orientation = pose.Orientation; orientation.Orthogonalize(); pose.Orientation = orientation; CameraNode.PoseWorld = pose; } _lastMousePosition = mousePosition; }
protected override void OnLoad() { var contentManager = _services.GetInstance <ContentManager>(); // ----- Graphics // Load a graphics model and add it to the scene for rendering. _modelNode = contentManager.Load <ModelNode>("Ship/Ship").Clone(); _modelNode.PoseWorld = new Pose(Vector3F.Zero, Matrix33F.CreateRotationY(-ConstantsF.PiOver2)); var scene = _services.GetInstance <IScene>(); scene.Children.Add(_modelNode); // ----- Collision Detection // Create a collision object and add it to the collision domain. // Load collision shape from a separate model (created using the CollisionShapeProcessor). var shape = contentManager.Load <Shape>("Ship/Ship_CollisionModel"); // Create a GeometricObject (= Shape + Pose + Scale). _geometricObject = new GeometricObject(shape, _modelNode.PoseWorld); // Create a collision object and add it to the collision domain. _collisionObject = new CollisionObject(_geometricObject); // Important: We do not need detailed contact information when a collision // is detected. The information of whether we have contact or not is sufficient. // Therefore, we can set the type to "Trigger". This increases the performance // dramatically. _collisionObject.Type = CollisionObjectType.Trigger; // Add the collision object to the collision domain of the game. var collisionDomain = _services.GetInstance <CollisionDomain>(); collisionDomain.CollisionObjects.Add(_collisionObject); }
public override void Update(GameTime gameTime) { base.Update(gameTime); var debugRenderer = GraphicsScreen.DebugRenderer; debugRenderer.Clear(); // <Space> --> Reset skeleton pose to bind pose. if (InputService.IsDown(Keys.Space)) { _meshNode.SkeletonPose.ResetBoneTransforms(); } // ----- Detect collisions // Get all contact sets of the head. RigidBody headBody = _ragdoll.Bodies[7]; var headContacts = Simulation.CollisionDomain.GetContacts(headBody.CollisionObject); GraphicsScreen.BackgroundColor = Color.CornflowerBlue; foreach (var contactSet in headContacts) { // Get the rigid body that collided with the head. RigidBody otherBody; if (contactSet.ObjectA.GeometricObject == headBody) { otherBody = contactSet.ObjectB.GeometricObject as RigidBody; } else { otherBody = contactSet.ObjectA.GeometricObject as RigidBody; } // If the head collided with a ball (from the BallShooter.cs), then set the hit flag. if (otherBody != null && otherBody.Name.StartsWith("Ball")) { debugRenderer.DrawText("\n\nHIT DETECTED!!!"); GraphicsScreen.BackgroundColor = Color.DarkRed; break; } } // Move model in a circle. var rotation = Matrix33F.CreateRotationY((float)gameTime.TotalGameTime.TotalSeconds * 0.3f); _meshNode.PoseWorld = new Pose(rotation * new Vector3F(3, 0, 0), rotation); // Sync pose with ragdoll. _ragdoll.Pose = _meshNode.PoseWorld; // Update the bodies to match the current skeleton pose. // This method changes the body poses directly. _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose); // Use DebugRenderer to visualize rigid bodies. foreach (var body in Simulation.RigidBodies) { if (body.Name.StartsWith("Ball")) { debugRenderer.DrawObject(body, Color.Gray, false, false); } else { debugRenderer.DrawObject(body, Color.Gray, true, false); } } }
/// <summary> /// Initializes the ragdoll for the given skeleton pose. /// </summary> /// <param name="skeletonPose">The skeleton pose.</param> /// <param name="ragdoll">The ragdoll.</param> /// <param name="simulation">The simulation in which the ragdoll will be used.</param> /// <param name="scale">A scaling factor to scale the size of the ragdoll.</param> public static void Create(SkeletonPose skeletonPose, Ragdoll ragdoll, Simulation simulation, float scale) { var skeleton = skeletonPose.Skeleton; const float totalMass = 80; // The total mass of the ragdoll. const int numberOfBodies = 17; // Get distance from foot to head as a measure for the size of the ragdoll. int head = skeleton.GetIndex("Head"); int footLeft = skeleton.GetIndex("L_Ankle1"); var headPosition = skeletonPose.GetBonePoseAbsolute(head).Translation; var footPosition = skeletonPose.GetBonePoseAbsolute(footLeft).Translation; var headToFootDistance = (headPosition - footPosition).Length; // We use the same mass properties for all bodies. This is not realistic but more stable // because large mass differences or thin bodies (arms!) are less stable. // We use the mass properties of sphere proportional to the size of the model. var massFrame = MassFrame.FromShapeAndMass(new SphereShape(headToFootDistance / 8), Vector3F.One, totalMass / numberOfBodies, 0.1f, 1); var material = new UniformMaterial(); #region ----- Add Bodies and Body Offsets ----- var numberOfBones = skeleton.NumberOfBones; ragdoll.Bodies.AddRange(Enumerable.Repeat <RigidBody>(null, numberOfBones)); ragdoll.BodyOffsets.AddRange(Enumerable.Repeat(Pose.Identity, numberOfBones)); var pelvis = skeleton.GetIndex("Pelvis"); ragdoll.Bodies[pelvis] = new RigidBody(new BoxShape(0.3f * scale, 0.4f * scale, 0.55f * scale), massFrame, material); ragdoll.BodyOffsets[pelvis] = new Pose(new Vector3F(0, 0, 0)); var backLower = skeleton.GetIndex("Spine"); ragdoll.Bodies[backLower] = new RigidBody(new BoxShape(0.36f * scale, 0.4f * scale, 0.55f * scale), massFrame, material); ragdoll.BodyOffsets[backLower] = new Pose(new Vector3F(0.18f * scale, 0, 0)); var backUpper = skeleton.GetIndex("Spine2"); ragdoll.Bodies[backUpper] = new RigidBody(new BoxShape(0.5f * scale, 0.4f * scale, 0.65f * scale), massFrame, material); ragdoll.BodyOffsets[backUpper] = new Pose(new Vector3F(0.25f * scale, 0, 0)); var neck = skeleton.GetIndex("Neck"); ragdoll.Bodies[neck] = new RigidBody(new CapsuleShape(0.12f * scale, 0.3f * scale), massFrame, material); ragdoll.BodyOffsets[neck] = new Pose(new Vector3F(0.15f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); ragdoll.Bodies[neck].CollisionObject.Enabled = false; ragdoll.Bodies[head] = new RigidBody(new SphereShape(0.2f * scale), massFrame, material); ragdoll.BodyOffsets[head] = new Pose(new Vector3F(0.15f * scale, 0.02f * scale, 0)); var armUpperLeft = skeleton.GetIndex("L_UpperArm"); ragdoll.Bodies[armUpperLeft] = new RigidBody(new CapsuleShape(0.12f * scale, 0.6f * scale), massFrame, material); ragdoll.BodyOffsets[armUpperLeft] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var armLowerLeft = skeleton.GetIndex("L_Forearm"); ragdoll.Bodies[armLowerLeft] = new RigidBody(new CapsuleShape(0.08f * scale, 0.5f * scale), massFrame, material); ragdoll.BodyOffsets[armLowerLeft] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var handLeft = skeleton.GetIndex("L_Hand"); ragdoll.Bodies[handLeft] = new RigidBody(new BoxShape(0.2f * scale, 0.06f * scale, 0.15f * scale), massFrame, material); ragdoll.BodyOffsets[handLeft] = new Pose(new Vector3F(0.1f * scale, 0, 0)); var armUpperRight = skeleton.GetIndex("R_UpperArm"); ragdoll.Bodies[armUpperRight] = new RigidBody(new CapsuleShape(0.12f * scale, 0.6f * scale), massFrame, material); ragdoll.BodyOffsets[armUpperRight] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var armLowerRight = skeleton.GetIndex("R_Forearm"); ragdoll.Bodies[armLowerRight] = new RigidBody(new CapsuleShape(0.08f * scale, 0.5f * scale), massFrame, material); ragdoll.BodyOffsets[armLowerRight] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var handRight = skeleton.GetIndex("R_Hand"); ragdoll.Bodies[handRight] = new RigidBody(new BoxShape(0.2f * scale, 0.06f * scale, 0.15f * scale), massFrame, material); ragdoll.BodyOffsets[handRight] = new Pose(new Vector3F(0.1f * scale, 0, 0)); var legUpperLeft = skeleton.GetIndex("L_Thigh1"); ragdoll.Bodies[legUpperLeft] = new RigidBody(new CapsuleShape(0.16f * scale, 0.8f * scale), massFrame, material); ragdoll.BodyOffsets[legUpperLeft] = new Pose(new Vector3F(0.4f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var legLowerLeft = skeleton.GetIndex("L_Knee2"); ragdoll.Bodies[legLowerLeft] = new RigidBody(new CapsuleShape(0.12f * scale, 0.65f * scale), massFrame, material); ragdoll.BodyOffsets[legLowerLeft] = new Pose(new Vector3F(0.32f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); //var footLeft = skeleton.GetIndex("L_Ankle1"); ragdoll.Bodies[footLeft] = new RigidBody(new BoxShape(0.20f * scale, 0.5f * scale, 0.3f * scale), massFrame, material); ragdoll.BodyOffsets[footLeft] = new Pose(new Vector3F(0.16f * scale, 0.15f * scale, 0)); var legUpperRight = skeleton.GetIndex("R_Thigh"); ragdoll.Bodies[legUpperRight] = new RigidBody(new CapsuleShape(0.16f * scale, 0.8f * scale), massFrame, material); ragdoll.BodyOffsets[legUpperRight] = new Pose(new Vector3F(0.4f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var legLowerRight = skeleton.GetIndex("R_Knee"); ragdoll.Bodies[legLowerRight] = new RigidBody(new CapsuleShape(0.12f * scale, 0.65f * scale), massFrame, material); ragdoll.BodyOffsets[legLowerRight] = new Pose(new Vector3F(0.32f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var footRight = skeleton.GetIndex("R_Ankle"); ragdoll.Bodies[footRight] = new RigidBody(new BoxShape(0.20f * scale, 0.5f * scale, 0.3f * scale), massFrame, material); ragdoll.BodyOffsets[footRight] = new Pose(new Vector3F(0.16f * scale, 0.15f * scale, 0)); #endregion #region ----- Set Collision Filters ----- // Collisions between connected bodies will be disabled in AddJoint(). (A BallJoint // has a property CollisionEnabled which decides whether connected bodies can // collide.) // But we need to disable some more collision between bodies that are not directly // connected but still too close to each other. var filter = (ICollisionFilter)simulation.CollisionDomain.CollisionDetection.CollisionFilter; filter.Set(ragdoll.Bodies[backUpper].CollisionObject, ragdoll.Bodies[head].CollisionObject, false); filter.Set(ragdoll.Bodies[armUpperRight].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false); filter.Set(ragdoll.Bodies[armUpperLeft].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false); filter.Set(ragdoll.Bodies[legUpperLeft].CollisionObject, ragdoll.Bodies[legUpperRight].CollisionObject, false); #endregion #region ----- Add Joints ----- AddJoint(skeletonPose, ragdoll, pelvis, backLower); AddJoint(skeletonPose, ragdoll, backLower, backUpper); AddJoint(skeletonPose, ragdoll, backUpper, neck); AddJoint(skeletonPose, ragdoll, neck, head); AddJoint(skeletonPose, ragdoll, backUpper, armUpperLeft); AddJoint(skeletonPose, ragdoll, armUpperLeft, armLowerLeft); AddJoint(skeletonPose, ragdoll, armLowerLeft, handLeft); AddJoint(skeletonPose, ragdoll, backUpper, armUpperRight); AddJoint(skeletonPose, ragdoll, armUpperRight, armLowerRight); AddJoint(skeletonPose, ragdoll, armLowerRight, handRight); AddJoint(skeletonPose, ragdoll, pelvis, legUpperLeft); AddJoint(skeletonPose, ragdoll, legUpperLeft, legLowerLeft); AddJoint(skeletonPose, ragdoll, legLowerLeft, footLeft); AddJoint(skeletonPose, ragdoll, pelvis, legUpperRight); AddJoint(skeletonPose, ragdoll, legUpperRight, legLowerRight); AddJoint(skeletonPose, ragdoll, legLowerRight, footRight); #endregion #region ----- Add Limits ----- // Choosing limits is difficult. // We create hinge limits with AngularLimits in the back and in the knee. // For all other joints we use TwistSwingLimits with symmetric cones. AddAngularLimit(skeletonPose, ragdoll, pelvis, backLower, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f)); AddAngularLimit(skeletonPose, ragdoll, backLower, backUpper, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.4f)); AddAngularLimit(skeletonPose, ragdoll, backUpper, neck, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f)); AddTwistSwingLimit(ragdoll, neck, head, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.5f, -0.7f), new Vector3F(0.1f, 0.5f, 0.7f)); var parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse; var childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperLeft).Inverse; var bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, backUpper, armUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(-0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armUpperLeft, armLowerLeft, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armLowerLeft, handLeft, Matrix33F.Identity, Matrix33F.CreateRotationX(+ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f)); parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse; childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperRight).Inverse; bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, backUpper, armUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armUpperRight, armLowerRight, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armLowerRight, handRight, Matrix33F.Identity, Matrix33F.CreateRotationX(-ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f)); parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse; childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperLeft).Inverse; bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, pelvis, legUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f)); AddAngularLimit(skeletonPose, ragdoll, legUpperLeft, legLowerLeft, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f)); AddTwistSwingLimit(ragdoll, legLowerLeft, footLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f)); parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse; childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperRight).Inverse; bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, pelvis, legUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f)); AddAngularLimit(skeletonPose, ragdoll, legUpperRight, legLowerRight, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f)); AddTwistSwingLimit(ragdoll, legLowerRight, footRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f)); #endregion #region ----- Add Motors ----- ragdoll.Motors.AddRange(Enumerable.Repeat <RagdollMotor>(null, numberOfBones)); ragdoll.Motors[pelvis] = new RagdollMotor(pelvis, -1); ragdoll.Motors[backLower] = new RagdollMotor(backLower, pelvis); ragdoll.Motors[backUpper] = new RagdollMotor(backUpper, backLower); ragdoll.Motors[neck] = new RagdollMotor(neck, backUpper); ragdoll.Motors[head] = new RagdollMotor(head, neck); ragdoll.Motors[armUpperLeft] = new RagdollMotor(armUpperLeft, backUpper); ragdoll.Motors[armLowerLeft] = new RagdollMotor(armLowerLeft, armUpperLeft); ragdoll.Motors[handLeft] = new RagdollMotor(handLeft, armLowerLeft); ragdoll.Motors[armUpperRight] = new RagdollMotor(armUpperRight, backUpper); ragdoll.Motors[armLowerRight] = new RagdollMotor(armLowerRight, armUpperRight); ragdoll.Motors[handRight] = new RagdollMotor(handRight, armLowerRight); ragdoll.Motors[legUpperLeft] = new RagdollMotor(legUpperLeft, pelvis); ragdoll.Motors[legLowerLeft] = new RagdollMotor(legLowerLeft, legUpperLeft); ragdoll.Motors[footLeft] = new RagdollMotor(footLeft, legLowerLeft); ragdoll.Motors[legUpperRight] = new RagdollMotor(legUpperRight, pelvis); ragdoll.Motors[legLowerRight] = new RagdollMotor(legLowerRight, legUpperRight); ragdoll.Motors[footRight] = new RagdollMotor(footRight, legLowerRight); #endregion }
//-------------------------------------------------------------- #region Methods //-------------------------------------------------------------- protected override void OnLoad() { // Add rigid bodies to simulation. var simulation = _services.GetInstance <Simulation>(); // We use a random number generator with a custom seed. RandomHelper.Random = new Random(123); // ----- Add a ground plane. AddBody(simulation, "GroundPlane", Pose.Identity, new PlaneShape(Vector3F.UnitY, 0), MotionType.Static); // ----- Create a small flying sphere. AddBody(simulation, "Sphere", new Pose(new Vector3F(0, 1f, 0)), new SphereShape(0.2f), MotionType.Static); // ----- Create small walls at the level boundary. AddBody(simulation, "WallLeft", new Pose(new Vector3F(-30, 1, 0)), new BoxShape(0.3f, 2, 60), MotionType.Static); AddBody(simulation, "WallRight", new Pose(new Vector3F(30, 1, 0)), new BoxShape(0.3f, 2, 60), MotionType.Static); AddBody(simulation, "WallFront", new Pose(new Vector3F(0, 1, -30)), new BoxShape(60, 2, 0.3f), MotionType.Static); AddBody(simulation, "WallBack", new Pose(new Vector3F(0, 1, 30)), new BoxShape(60, 2, 0.3f), MotionType.Static); // ----- Create a few bigger objects. // We position the boxes so that we have a few corners we can run into. Character controllers // should be stable when the user runs into corners. AddBody(simulation, "House0", new Pose(new Vector3F(10, 1, -10)), new BoxShape(8, 2, 8f), MotionType.Static); AddBody(simulation, "House1", new Pose(new Vector3F(13, 1, -4)), new BoxShape(2, 2, 4), MotionType.Static); AddBody(simulation, "House2", new Pose(new Vector3F(10, 2, -15), Matrix33F.CreateRotationY(-0.3f)), new BoxShape(8, 4, 2), MotionType.Static); // ----- Create stairs with increasing step height. // Each step is a box. With this object we can test if our character can climb up // stairs. The character controller has a step height limit. Increasing step heights // let us test if the step height limit works. float startHeight = 0; const float stepDepth = 1f; for (int i = 0; i < 10; i++) { float stepHeight = 0.1f + i * 0.05f; Vector3F position = new Vector3F(0, startHeight + stepHeight / 2, -2 - i * stepDepth); AddBody(simulation, "Step" + i, new Pose(position), new BoxShape(2, stepHeight, stepDepth), MotionType.Static); startHeight += stepHeight; } // ----- V obstacle to test if we get stuck. AddBody(simulation, "V0", new Pose(new Vector3F(-5.5f, 0, 10), QuaternionF.CreateRotationZ(0.2f)), new BoxShape(1f, 2f, 2), MotionType.Static); AddBody(simulation, "V1", new Pose(new Vector3F(-4, 0, 10), QuaternionF.CreateRotationZ(-0.2f)), new BoxShape(1f, 2f, 2), MotionType.Static); // ----- Create a height field. // Terrain that is uneven is best modeled with a height field. Height fields are faster // than general triangle meshes. // The height direction is the y direction. // The height field lies in the x/z plane. var numberOfSamplesX = 20; var numberOfSamplesZ = 20; var samples = new float[numberOfSamplesX * numberOfSamplesZ]; // Create arbitrary height values. for (int z = 0; z < numberOfSamplesZ; z++) { for (int x = 0; x < numberOfSamplesX; x++) { if (x == 0 || z == 0 || x == 19 || z == 19) { // Set this boundary elements to a low height, so that the height field is connected // to the ground. samples[z * numberOfSamplesX + x] = -1; } else { // A sine/cosine function that creates some interesting waves. samples[z * numberOfSamplesX + x] = 1.0f + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1.0f); } } } var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ); AddBody(simulation, "HeightField", new Pose(new Vector3F(10, 0, 10)), heightField, MotionType.Static); // ----- Create rubble on the floor (small random objects on the floor). // Our character should be able to move over small bumps on the ground. for (int i = 0; i < 50; i++) { Vector3F position = new Vector3F(RandomHelper.Random.NextFloat(-5, 5), 0, RandomHelper.Random.NextFloat(10, 20)); QuaternionF orientation = RandomHelper.Random.NextQuaternionF(); Vector3F size = RandomHelper.Random.NextVector3F(0.05f, 0.8f); AddBody(simulation, "Stone" + i, new Pose(position, orientation), new BoxShape(size), MotionType.Static); } // ----- Create some slopes to see how our character performs on/under sloped surfaces. // Here we can test how the character controller behaves if the head touches an inclined // ceiling. AddBody(simulation, "SlopeGround", new Pose(new Vector3F(-2, 1.8f, -12), QuaternionF.CreateRotationX(0.4f)), new BoxShape(2, 0.5f, 10), MotionType.Static); AddBody(simulation, "SlopeRoof", new Pose(new Vector3F(-2, 5.6f, -12), QuaternionF.CreateRotationX(-0.4f)), new BoxShape(2, 0.5f, 10), MotionType.Static); // Create slopes with increasing tilt angles. // The character controller has a slope limit. Only flat slopes should be climbable. // Movement between slopes should be smooth. Vector3F slopePosition = new Vector3F(-17, -0.25f, 6); BoxShape slopeShape = new BoxShape(8, 0.5f, 5); for (int i = 1; i < 8; i++) { Matrix33F oldRotation = Matrix33F.CreateRotationX((i - 1) * MathHelper.ToRadians(10)); Matrix33F rotation = Matrix33F.CreateRotationX(i * MathHelper.ToRadians(10)); slopePosition += (oldRotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2 + (rotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2; AddBody(simulation, "Slope" + i, new Pose(slopePosition, rotation), slopeShape, MotionType.Static); } // Create slopes with decreasing tilt angles. slopePosition = new Vector3F(-8, -2, 5); slopeShape = new BoxShape(8f, 0.5f, 5); for (int i = 1; i < 8; i++) { Matrix33F oldRotation = Matrix33F.CreateRotationX(MathHelper.ToRadians(40) - (i - 1) * MathHelper.ToRadians(10)); Matrix33F rotation = Matrix33F.CreateRotationX(MathHelper.ToRadians(40) - i * MathHelper.ToRadians(10)); slopePosition += (oldRotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2 + (rotation * new Vector3F(0, 0, -slopeShape.WidthZ)) / 2; Vector3F position = slopePosition - rotation * new Vector3F(0, slopeShape.WidthY / 2, 0); AddBody(simulation, "Slope2" + i, new Pose(position, rotation), slopeShape, MotionType.Static); } // ----- Create a slope with a wall on one side. // This objects let's us test how the character controller behaves while falling and // sliding along a vertical wall. (Run up the slope and then jump down while moving into // the wall.) AddBody(simulation, "LongSlope", new Pose(new Vector3F(-24, 3, -10), Matrix33F.CreateRotationX(0.4f)), new BoxShape(4, 5f, 30), MotionType.Static); AddBody(simulation, "LongSlopeWall", new Pose(new Vector3F(-26, 5, -10)), new BoxShape(0.5f, 10f, 25), MotionType.Static); // ----- Create a trigger object that represents a ladder. var ladder = AddBody(simulation, "Ladder", new Pose(new Vector3F(-25.7f, 5, 0)), new BoxShape(0.5f, 10f, 1), MotionType.Static); ladder.CollisionObject.Type = CollisionObjectType.Trigger; // ----- Create a mesh object to test walking on triangle meshes. // Normally, the mesh would be loaded from a file. Here, we make a composite shape and // let DigitalRune Geometry compute a mesh for it. Then we throw away the composite // shape and use only the mesh. (We do this to test triangle meshes. Using the composite // shape instead of the triangle mesh would be a lot faster.) CompositeShape compositeShape = new CompositeShape(); compositeShape.Children.Add(new GeometricObject(heightField, Pose.Identity)); compositeShape.Children.Add(new GeometricObject(new CylinderShape(1, 2), new Pose(new Vector3F(10, 1, 10)))); compositeShape.Children.Add(new GeometricObject(new SphereShape(3), new Pose(new Vector3F(15, 0, 15)))); compositeShape.Children.Add(new GeometricObject(new BoxShape(4, 4, 3), new Pose(new Vector3F(15, 1.5f, 5)))); compositeShape.Children.Add(new GeometricObject(new BoxShape(4, 4, 3), new Pose(new Vector3F(15, 1.5f, 0)))); ITriangleMesh mesh = compositeShape.GetMesh(0.01f, 3); TriangleMeshShape meshShape = new TriangleMeshShape(mesh); // Collision detection speed for triangle meshes can be improved by using a spatial // partition. Here, we assign an AabbTree to the triangle mesh shape. The tree is // built automatically when needed and it stores triangle indices (therefore the generic // parameter of the AabbTree is int). meshShape.Partition = new AabbTree <int>() { // The tree is automatically built using a mixed top-down/bottom-up approach. Bottom-up // building is slower but produces better trees. If the tree building takes too long, // we can lower the BottomUpBuildThreshold (default is 128). BottomUpBuildThreshold = 0, }; // Contact welding creates smoother contact normals - but it costs a bit of performance. meshShape.EnableContactWelding = true; AddBody(simulation, "Mesh", new Pose(new Vector3F(-30, 0, 10)), meshShape, MotionType.Static); // ----- Create a seesaw. var seesawBase = AddBody(simulation, "SeesawBase", new Pose(new Vector3F(5, 0.5f, 0)), new BoxShape(0.2f, 1, 1), MotionType.Static); var seesaw = AddBody(simulation, "Seesaw", new Pose(new Vector3F(5, 1.05f, 0)), new BoxShape(5, 0.1f, 1), MotionType.Dynamic); // Attach the seesaw to the base using a hinge joint. simulation.Constraints.Add(new HingeJoint { BodyA = seesaw, BodyB = seesawBase, AnchorPoseALocal = new Pose(new Vector3F(0, 0, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), AnchorPoseBLocal = new Pose(new Vector3F(0, 0.5f, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), CollisionEnabled = false, }); // ----- A platform that is moving up/down. _elevator = AddBody(simulation, "Elevator", new Pose(new Vector3F(5, -1f, 5)), new BoxShape(3, 1f, 3), MotionType.Kinematic); _elevator.LinearVelocity = new Vector3F(2, 2, 0); // ----- A platform that is moving sideways. _pusher = AddBody(simulation, "Pusher", new Pose(new Vector3F(15, 0.5f, 0)), new BoxShape(3, 1f, 3), MotionType.Kinematic); _pusher.LinearVelocity = new Vector3F(0, 0, 2); // ----- Create conveyor belt with two static boxes on the sides. AddBody(simulation, "ConveyorSide0", new Pose(new Vector3F(19, 0.25f, 0)), new BoxShape(0.8f, 0.5f, 8f), MotionType.Static); AddBody(simulation, "ConveyorSide1", new Pose(new Vector3F(21, 0.25f, 0)), new BoxShape(0.8f, 0.5f, 8f), MotionType.Static); // The conveyor belt is a simple box with a special material. var conveyorBelt = AddBody(simulation, "ConveyorBelt", new Pose(new Vector3F(20, 0.25f, 0)), new BoxShape(1f, 0.51f, 8f), MotionType.Static); UniformMaterial materialWithSurfaceMotion = new UniformMaterial("ConveyorBelt", true) // Important: The second parameter enables the surface { // motion. It has to be set to true in the constructor! SurfaceMotion = new Vector3F(0, 0, 1), // The surface motion relative to the object. }; conveyorBelt.Material = materialWithSurfaceMotion; // ----- Distribute a few dynamic spheres and boxes across the landscape. SphereShape sphereShape = new SphereShape(0.5f); for (int i = 0; i < 10; i++) { Vector3F position = RandomHelper.Random.NextVector3F(-15, 15); position.Y = 20; AddBody(simulation, "Sphere" + i, new Pose(position), sphereShape, MotionType.Dynamic); } BoxShape boxShape = new BoxShape(1, 1, 1); for (int i = 0; i < 10; i++) { Vector3F position = RandomHelper.Random.NextVector3F(-15, 15); position.Y = 20; AddBody(simulation, "Box" + i, new Pose(position), boxShape, MotionType.Dynamic); } }
public RefractionSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics Simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new GroundObject(Services)); var lavaBallsObject = new LavaBallsObject(Services); GameObjectService.Objects.Add(lavaBallsObject); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); GameObjectService.Objects.Add(new FogObject(Services)); GameObjectService.Objects.Add(new StaticSkyObject(Services)); GameObjectService.Objects.Add(new CampfireObject(Services)); for (int i = 0; i < 10; i++) { GameObjectService.Objects.Add(new DynamicObject(Services, 1)); GameObjectService.Objects.Add(new DynamicObject(Services, 2)); GameObjectService.Objects.Add(new DynamicObject(Services, 3)); } // Add a few palm trees. Random random = new Random(12345); for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation))); } // Add a few dudes which use the refraction effect. for (int i = 0; i < 5; i++) { Vector3F position = new Vector3F(random.NextFloat(-4, 4), 0, random.NextFloat(2, -5)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); var dudeObject = new DudeObject(Services, "DudeRefracted/Dude") { Pose = new Pose(position, orientation) }; GameObjectService.Objects.Add(dudeObject); //dudeObject.AnimationController.Pause(); } // The DeferredGraphicsScreen has a SceneRenderer, which contains all // renderers necessary to render transparent objects (e.g. BillboardRenderer // for particles, MeshRenderer for meshes, etc.). // We remove the MeshRenderer and add our own RefractionMeshRenderer instead. var meshRenderer = _graphicsScreen.AlphaBlendSceneRenderer.Renderers.OfType <MeshRenderer>().First(); _graphicsScreen.AlphaBlendSceneRenderer.Renderers.Remove(meshRenderer); _graphicsScreen.AlphaBlendSceneRenderer.Renderers.Add(new RefractionMeshRenderer(GraphicsService)); }