public override void Update(GameTime gameTime) { _debugRenderer.Clear(); if (_avatarPose == null) { // Must wait till renderer is ready. Before that we do not get skeleton info. if (_avatarRenderer.State == AvatarRendererState.Ready) { // Create AvatarPose. _avatarPose = new AvatarPose(_avatarRenderer); // A 'bone transform' is the transformation of a bone relative to its bind pose. // Bone transforms define the pose of a skeleton. // Rotate arm of avatar. SkeletonPose skeletonPose = _avatarPose.SkeletonPose; int shoulderIndex = skeletonPose.Skeleton.GetIndex("ShoulderLeft"); skeletonPose.SetBoneTransform(shoulderIndex, new SrtTransform(QuaternionF.CreateRotationZ(-0.9f))); // The class SkeletonHelper provides some useful extension methods. // One is SetBoneRotationAbsolute() which sets the orientation of a bone relative // to model space. // Rotate elbow to make the lower arm point forward. int elbowIndex = skeletonPose.Skeleton.GetIndex("ElbowLeft"); SkeletonHelper.SetBoneRotationAbsolute(skeletonPose, elbowIndex, QuaternionF.CreateRotationY(ConstantsF.PiOver2)); // Draw avatar skeleton for debugging. _debugRenderer.DrawSkeleton(skeletonPose, _pose, Vector3F.One, 0.02f, Color.Orange, true); } } }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Start the first animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } } else { if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) { // Switch to next preset. _currentAvatarAnimationPreset++; if (!Enum.IsDefined(typeof(AvatarAnimationPreset), _currentAvatarAnimationPreset)) { _currentAvatarAnimationPreset = 0; } // Cross-fade to new animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One)) { // Switch to previous preset. _currentAvatarAnimationPreset--; if (!Enum.IsDefined(typeof(AvatarAnimationPreset), _currentAvatarAnimationPreset)) { _currentAvatarAnimationPreset = (AvatarAnimationPreset)EnumHelper.GetValues(typeof(AvatarAnimationPreset)).Length - 1; } // Cross-fade to new animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } } }
/// <overloads> /// <summary> /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.) /// </summary> /// </overloads> /// /// <summary> /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.) /// </summary> /// <param name="avatarPose">The avatar pose.</param> /// <param name="simulation">The simulation.</param> /// <returns>The avatar ragdoll.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="avatarPose"/> or <paramref name="simulation"/> is <see langword="null"/>. /// </exception> /// <remarks> /// This method is available only in the Xbox 360 build of the /// DigitalRune.Physics.Specialized.dll. /// </remarks> public static Ragdoll CreateAvatarRagdoll(AvatarPose avatarPose, Simulation simulation) { if (avatarPose == null) throw new ArgumentNullException("avatarPose"); if (simulation == null) throw new ArgumentNullException("simulation"); return CreateAvatarRagdoll(avatarPose.SkeletonPose.Skeleton, simulation); }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Start the first animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } } else { if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) { // Switch to next preset. _currentAvatarAnimationPreset++; if (!Enum.IsDefined(typeof(AvatarAnimationPreset), _currentAvatarAnimationPreset)) _currentAvatarAnimationPreset = 0; // Cross-fade to new animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One)) { // Switch to previous preset. _currentAvatarAnimationPreset--; if (!Enum.IsDefined(typeof(AvatarAnimationPreset), _currentAvatarAnimationPreset)) _currentAvatarAnimationPreset = (AvatarAnimationPreset)EnumHelper.GetValues(typeof(AvatarAnimationPreset)).Length - 1; // Cross-fade to new animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } } }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // In this sample we use a passive ragdoll where we need joints to hold the // limbs together and limits to control the angular movement. _ragdoll.EnableJoints(); _ragdoll.EnableLimits(); // Set all motors to constraint motors that only use damping. This adds a damping // effect to all ragdoll limbs. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Constraint; motor.ConstraintDamping = 5; motor.ConstraintSpring = 0; } } _ragdoll.EnableMotors(); // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); } } else { // Copy skeleton pose from ragdoll. _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose); } // Render rigid bodies. _debugRenderer.Clear(); foreach (var body in Simulation.RigidBodies) { if (!(body.Shape is EmptyShape)) // Do not draw dummy bodies which might be used by the ragdoll. { _debugRenderer.DrawObject(body, Color.Black, true, false); } } }
/// <overloads> /// <summary> /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.) /// </summary> /// </overloads> /// /// <summary> /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.) /// </summary> /// <param name="avatarPose">The avatar pose.</param> /// <param name="simulation">The simulation.</param> /// <returns>The avatar ragdoll.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="avatarPose"/> or <paramref name="simulation"/> is <see langword="null"/>. /// </exception> /// <remarks> /// This method is available only in the Xbox 360 build of the /// DigitalRune.Physics.Specialized.dll. /// </remarks> public static Ragdoll CreateAvatarRagdoll(AvatarPose avatarPose, Simulation simulation) { if (avatarPose == null) { throw new ArgumentNullException("avatarPose"); } if (simulation == null) { throw new ArgumentNullException("simulation"); } return(CreateAvatarRagdoll(avatarPose.SkeletonPose.Skeleton, simulation)); }
public override void Update(GameTime gameTime) { base.Update(gameTime); if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); AnimationService.StartAnimation(_walkAnimation, _avatarPose).AutoRecycle(); } } }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); AnimationService.StartAnimation(_waveAnimation, _avatarPose).AutoRecycle(); } } else if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) { // Restart animation using a cross-fade of 0.5 seconds. AnimationService.StartAnimation(_waveAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); } }
public override void Update(GameTime gameTime) { base.Update(gameTime); if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // In this sample we use a passive ragdoll where we need joints to hold the // limbs together and limits to control the angular movement. _ragdoll.EnableJoints(); _ragdoll.EnableLimits(); // Set all motors to constraint motors that only use damping. This adds a damping // effect to all ragdoll limbs. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Constraint; motor.ConstraintDamping = 5; motor.ConstraintSpring = 0; } } _ragdoll.EnableMotors(); // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); } } }
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; } }
public override void Update(GameTime gameTime) { base.Update(gameTime); if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); AnimationService.StartAnimation(_waveAnimation, _avatarPose).AutoRecycle(); } } else if (InputService.IsPressed(Buttons.A, false, PlayerIndex.One)) { // Restart animation using a cross-fade of 0.5 seconds. AnimationService.StartAnimation(_waveAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); } }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); _targetPose = SkeletonPose.Create(_avatarPose.SkeletonPose.Skeleton); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses // of the current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // To simplify collision checks, we need a simple way to determine whether // a rigid body belongs to the ragdoll. // --> Set RigidBody.UserData = _ragdoll. // (Alternatively we could also set specific names for the rigid bodies, // or we could assign the collision objects to a certain collision group.) foreach (var body in _ragdoll.Bodies) { if (body != null) { body.UserData = _ragdoll; } } // Add rigid bodies and constraints to the simulation. _ragdoll.AddToSimulation(Simulation); // Start by playing the key frame animation. SwitchMode(RagdollMode.Mode1); // The facial expression can be applied directly to the _avatarPose. _animationController0 = AnimationService.StartAnimation(_expressionAnimation, _avatarPose); // The skeletal animation is applied to the _targetPose. The _targetPose // is used to drive the ragdoll. (See end of method.) _animationController1 = AnimationService.StartAnimation(_skeletonAnimation, (IAnimatableProperty <SkeletonPose>)_targetPose); } return; } if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode1); } else if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode2); } else if (InputService.IsPressed(Buttons.X, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode3); } else if (InputService.IsPressed(Buttons.Y, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode4); } if (_mode == RagdollMode.Mode1 || _mode == RagdollMode.Mode2) { // The ragdoll plays a certain animation. Check whether the character was // hit by a ball. foreach (var contactConstraint in Simulation.ContactConstraints) { if (contactConstraint.BodyA.UserData == _ragdoll && contactConstraint.BodyB.Name.StartsWith("Ball") || contactConstraint.BodyB.UserData == _ragdoll && contactConstraint.BodyA.Name.StartsWith("Ball")) { // Switch to the "Passive Ragdoll" mode and let the character collapse. SwitchMode(RagdollMode.Mode3); // Hint: You can read contactConstraint.LinearConstraintImpulse.Length to // determine the strength of the impact. } } } switch (_mode) { case RagdollMode.Mode1: // In mode 1 we update the rigid bodies directly. _ragdoll.UpdateBodiesFromSkeleton(_targetPose); break; case RagdollMode.Mode2: // Compute how much time the simulation will advance in the next Update(). TimeSpan nextSimulationTimeStep; int numberOfSubTimeSteps; Simulation.GetNextTimeStep(gameTime.ElapsedGameTime, out nextSimulationTimeStep, out numberOfSubTimeSteps); // In mode 2 velocity motors update the rigid bodies. _ragdoll.DriveToPose(_targetPose, (float)nextSimulationTimeStep.TotalSeconds); break; case RagdollMode.Mode3: // In mode 3 we don't have to update the rigid bodies. break; case RagdollMode.Mode4: // In mode 4 constraint motors control the joints of the ragdoll. // (The second parameter is only required for velocity motors.) _ragdoll.DriveToPose(_targetPose, 0); break; } // Copy the skeleton pose. (_avatarPose stores the skeleton pose which is // being rendered.) _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose); _debugRenderer.Clear(); _debugRenderer.DrawText("\n"); _debugRenderer.DrawText(_statusMessage); // Render rigid bodies. foreach (var body in Simulation.RigidBodies) { if (!(body.Shape is EmptyShape)) // Do not draw dummy bodies which might be used by the ragdoll. { _debugRenderer.DrawObject(body, Color.Black, true, false); } } }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); _targetPose = SkeletonPose.Create(_avatarPose.SkeletonPose.Skeleton); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses // of the current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // To simplify collision checks, we need a simple way to determine whether // a rigid body belongs to the ragdoll. // --> Set RigidBody.UserData = _ragdoll. // (Alternatively we could also set specific names for the rigid bodies, // or we could assign the collision objects to a certain collision group.) foreach (var body in _ragdoll.Bodies) if (body != null) body.UserData = _ragdoll; // Add rigid bodies and constraints to the simulation. _ragdoll.AddToSimulation(Simulation); // Start by playing the key frame animation. SwitchMode(RagdollMode.Mode1); // The facial expression can be applied directly to the _avatarPose. _animationController0 = AnimationService.StartAnimation(_expressionAnimation, _avatarPose); // The skeletal animation is applied to the _targetPose. The _targetPose // is used to drive the ragdoll. (See end of method.) _animationController1 = AnimationService.StartAnimation(_skeletonAnimation, (IAnimatableProperty<SkeletonPose>)_targetPose); } return; } if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) SwitchMode(RagdollMode.Mode1); else if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One)) SwitchMode(RagdollMode.Mode2); else if (InputService.IsPressed(Buttons.X, false, LogicalPlayerIndex.One)) SwitchMode(RagdollMode.Mode3); else if (InputService.IsPressed(Buttons.Y, false, LogicalPlayerIndex.One)) SwitchMode(RagdollMode.Mode4); if (_mode == RagdollMode.Mode1 || _mode == RagdollMode.Mode2) { // The ragdoll plays a certain animation. Check whether the character was // hit by a ball. foreach (var contactConstraint in Simulation.ContactConstraints) { if (contactConstraint.BodyA.UserData == _ragdoll && contactConstraint.BodyB.Name.StartsWith("Ball") || contactConstraint.BodyB.UserData == _ragdoll && contactConstraint.BodyA.Name.StartsWith("Ball")) { // Switch to the "Passive Ragdoll" mode and let the character collapse. SwitchMode(RagdollMode.Mode3); // Hint: You can read contactConstraint.LinearConstraintImpulse.Length to // determine the strength of the impact. } } } switch (_mode) { case RagdollMode.Mode1: // In mode 1 we update the rigid bodies directly. _ragdoll.UpdateBodiesFromSkeleton(_targetPose); break; case RagdollMode.Mode2: // Compute how much time the simulation will advance in the next Update(). TimeSpan nextSimulationTimeStep; int numberOfSubTimeSteps; Simulation.GetNextTimeStep(gameTime.ElapsedGameTime, out nextSimulationTimeStep, out numberOfSubTimeSteps); // In mode 2 velocity motors update the rigid bodies. _ragdoll.DriveToPose(_targetPose, (float)nextSimulationTimeStep.TotalSeconds); break; case RagdollMode.Mode3: // In mode 3 we don't have to update the rigid bodies. break; case RagdollMode.Mode4: // In mode 4 constraint motors control the joints of the ragdoll. // (The second parameter is only required for velocity motors.) _ragdoll.DriveToPose(_targetPose, 0); break; } // Copy the skeleton pose. (_avatarPose stores the skeleton pose which is // being rendered.) _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose); _debugRenderer.Clear(); _debugRenderer.DrawText("\n"); _debugRenderer.DrawText(_statusMessage); // Render rigid bodies. foreach (var body in Simulation.RigidBodies) if (!(body.Shape is EmptyShape)) // Do not draw dummy bodies which might be used by the ragdoll. _debugRenderer.DrawObject(body, Color.Black, true, false); }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Start stand animation. _standAnimationController = AnimationService.StartAnimation(_standAnimation, _avatarPose); _standAnimationController.AutoRecycle(); } } else { // When the user presses buttons, we cross-fade to the custom animations. if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) { _actionAnimationController = AnimationService.StartAnimation( _jumpAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.3))); _actionAnimationController.AutoRecycle(); } if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One)) { _actionAnimationController = AnimationService.StartAnimation( _punchAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.3))); _actionAnimationController.AutoRecycle(); } if (InputService.IsPressed(Buttons.X, false, LogicalPlayerIndex.One)) { _actionAnimationController = AnimationService.StartAnimation( _kickAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.3))); _actionAnimationController.AutoRecycle(); } if (InputService.IsPressed(Buttons.Y, false, LogicalPlayerIndex.One)) { _actionAnimationController = AnimationService.StartAnimation( _faintAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.3))); _actionAnimationController.AutoRecycle(); } // The left trigger controls the speed of the walk cycle. float leftTrigger = Math.Abs(InputService.GetGamePadState(LogicalPlayerIndex.One).Triggers.Left); _walkAnimationController.Speed = leftTrigger * 2; if (_walkAnimationController.State != AnimationState.Playing) { // The walk cycle is not playing. // --> Start walk animation if left trigger is pressed. if (leftTrigger > 0) { _walkAnimationController = AnimationService.StartAnimation( _walkAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.3))); _walkAnimationController.AutoRecycle(); } } else { // The walk cycle is playing. // --> Cross-fade to stand animation if left trigger is not pressed. if (leftTrigger == 0) { _standAnimationController = AnimationService.StartAnimation( _standAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.3))); _standAnimationController.AutoRecycle(); } } // If none of the animations is playing, then restart the stand animation. if (_standAnimationController.State != AnimationState.Playing && _actionAnimationController.State != AnimationState.Playing && _walkAnimationController.State != AnimationState.Playing) { _standAnimationController = AnimationService.StartAnimation( _standAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.3))); _standAnimationController.AutoRecycle(); } } }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // In this sample we use a passive ragdoll where we need joints to hold the // limbs together and limits to control the angular movement. _ragdoll.EnableJoints(); _ragdoll.EnableLimits(); // Set all motors to constraint motors that only use damping. This adds a damping // effect to all ragdoll limbs. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Constraint; motor.ConstraintDamping = 5; motor.ConstraintSpring = 0; } } _ragdoll.EnableMotors(); // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); } } else { // Copy skeleton pose from ragdoll. _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose); } // Render rigid bodies. _debugRenderer.Clear(); foreach (var body in Simulation.RigidBodies) if (!(body.Shape is EmptyShape)) // Do not draw dummy bodies which might be used by the ragdoll. _debugRenderer.DrawObject(body, Color.Black, true, false); }
public override void Update(GameTime gameTime) { base.Update(gameTime); if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); _targetPose = SkeletonPose.Create(_avatarPose.SkeletonPose.Skeleton); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses // of the current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // To simplify collision checks, we need a simple way to determine whether // a rigid body belongs to the ragdoll. // --> Set RigidBody.UserData = _ragdoll. // (Alternatively we could also set specific names for the rigid bodies, // or we could assign the collision objects to a certain collision group.) foreach (var body in _ragdoll.Bodies) if (body != null) body.UserData = _ragdoll; // Add rigid bodies and constraints to the simulation. _ragdoll.AddToSimulation(Simulation); // Start by playing the key frame animation. SwitchMode(RagdollMode.Mode1); // The facial expression can be applied directly to the _avatarPose. _animationController0 = AnimationService.StartAnimation(_expressionAnimation, _avatarPose); // The skeletal animation is applied to the _targetPose. The _targetPose // is used to drive the ragdoll. (See end of method.) _animationController1 = AnimationService.StartAnimation(_skeletonAnimation, (IAnimatableProperty<SkeletonPose>)_targetPose); } return; } if (InputService.IsPressed(Buttons.A, false, PlayerIndex.One)) SwitchMode(RagdollMode.Mode1); else if (InputService.IsPressed(Buttons.B, false, PlayerIndex.One)) SwitchMode(RagdollMode.Mode2); else if (InputService.IsPressed(Buttons.X, false, PlayerIndex.One)) SwitchMode(RagdollMode.Mode3); else if (InputService.IsPressed(Buttons.Y, false, PlayerIndex.One)) SwitchMode(RagdollMode.Mode4); if (_mode == RagdollMode.Mode1 || _mode == RagdollMode.Mode2) { // The ragdoll plays a certain animation. Check whether the character was // hit by a ball. foreach (var contactConstraint in Simulation.ContactConstraints) { if (contactConstraint.BodyA.UserData == _ragdoll && contactConstraint.BodyB.Name.StartsWith("Ball") || contactConstraint.BodyB.UserData == _ragdoll && contactConstraint.BodyA.Name.StartsWith("Ball")) { // Switch to the "Passive Ragdoll" mode and let the character collapse. SwitchMode(RagdollMode.Mode3); // Hint: You can read contactConstraint.LinearConstraintImpulse.Length to // determine the strength of the impact. } } } switch (_mode) { case RagdollMode.Mode1: // In mode 1 we update the rigid bodies directly. _ragdoll.UpdateBodiesFromSkeleton(_targetPose); break; case RagdollMode.Mode2: // In mode 2 velocity motors update the rigid bodies. _ragdoll.DriveToPose(_targetPose, gameTime.ElapsedGameTime); break; case RagdollMode.Mode3: // In mode 3 we don't have to update the rigid bodies. break; case RagdollMode.Mode4: // In mode 4 constraint motors control the joints of the ragdoll. _ragdoll.DriveToPose(_targetPose, gameTime.ElapsedGameTime); break; } // Copy the skeleton pose. (_avatarPose stores the skeleton pose which is // being rendered.) _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose); }