public KinectWrapper(Game game) : base(game) { // one sensor is currently supported _kinectSensor = KinectSensor.GetDefault(); // open the reader for the body frames _bodyFrameReader = _kinectSensor.BodyFrameSource.OpenReader(); // open the sensor _kinectSensor.Open(); _bodyFrameReader.FrameArrived += OnKinectBodyFrameArrived; Offset = new Vector3(0, 0.3f, 0); Scale = new Vector3(1, 1, 1); // Create a skeleton that defines the bone hierarchy and rest pose. var skeleton = new Skeleton( Bones.Select(b => b.ParentIndex).ToArray(), // Parent indices Bones.Select(b => b.Name).ToArray(), // Bone names Enumerable.Repeat(SrtTransform.Identity, Bones.Length).ToArray()); // Bind poses = all Identity transforms // Create a SkeletonPose for each player. SkeletonPoseA = SkeletonPose.Create(skeleton); SkeletonPoseB = SkeletonPose.Create(skeleton); }
// Note: // SkeletonPose.Invalidate() needs to be called when the internal BoneTransforms // are changed. Invalidate() only has an effect if the SkeletonPose has a // SkeletonBoneAccessor. Newly created SkeletonPose do not have a SkeletonBoneAccessor. // --> Calling Invalidate() should not have a performance impact. Except for the // Set() method. Set() is called in AnimationManager.Apply() where the animation // value is copied into the actual SkeletonPose, which might use a SkeletonBoneAccessor. // Set() is the only method where Invalidate() is mandatory. However, the // SkeletonPoseTraits might be used outside of the animation service. Invalidate() // should be called in all methods to be safe. /// <inheritdoc/> /// <exception cref="ArgumentNullException"> /// <paramref name="reference"/> is <see langword="null"/>. /// </exception> public void Create(ref SkeletonPose reference, out SkeletonPose value) { if (reference == null) { throw new ArgumentNullException("reference", "The reference value must not be null. This exception usually occurs when an IAnimatableProperty<SkeletonPose> is being animated, but the value of the property is null. A SkeletonPose must be set before the property can be animated."); } value = SkeletonPose.Create(reference.Skeleton); }
private void InitializeSkeletonPoses() { // Create a list of the bone/joint names of a Kinect skeleton. int numberOfJoints = Enum.GetNames(typeof(JointType)).Length; var boneNames = new string[numberOfJoints]; for (int i = 0; i < numberOfJoints; i++) { boneNames[i] = ((JointType)i).ToString(); } // Create list with one entry per bone. Each entry is the index of the parent bone. var boneParents = new[] { -1, (int)JointType.HipCenter, (int)JointType.Spine, (int)JointType.ShoulderCenter, (int)JointType.ShoulderCenter, (int)JointType.ShoulderLeft, (int)JointType.ElbowLeft, (int)JointType.WristLeft, (int)JointType.ShoulderCenter, (int)JointType.ShoulderRight, (int)JointType.ElbowRight, (int)JointType.WristRight, (int)JointType.HipCenter, (int)JointType.HipLeft, (int)JointType.KneeLeft, (int)JointType.AnkleLeft, (int)JointType.HipCenter, (int)JointType.HipRight, (int)JointType.KneeRight, (int)JointType.AnkleRight, }; // Create a list of the bind pose transformations of all bones. Since we do not // get such information from Kinect, we position all bones in the local origin. var boneBindPoses = new SrtTransform[numberOfJoints]; for (int i = 0; i < numberOfJoints; i++) { boneBindPoses[i] = SrtTransform.Identity; } // Create a skeleton that defines the bone hierarchy and rest pose. var skeleton = new DRSkeleton(boneParents, boneNames, boneBindPoses); // Create a SkeletonPose for each player. SkeletonPoseA = SkeletonPose.Create(skeleton); SkeletonPoseB = SkeletonPose.Create(skeleton); }
internal void OnAssetLoaded(object sender, EventArgs eventArgs) { // Create MeshNode.SkeletonPoses for all mesh.Skeletons. // (Skeletons can be shared and for each skeleton we create only one SkeletonPose.) Dictionary <Skeleton, SkeletonPose> skeletons = new Dictionary <Skeleton, SkeletonPose>(); foreach (var meshNode in this.GetSubtree().OfType <MeshNode>()) { var skeleton = meshNode.Mesh.Skeleton; if (skeleton != null) { // Get existing skeleton pose or create a new one. SkeletonPose skeletonPose; if (!skeletons.TryGetValue(skeleton, out skeletonPose)) { skeletonPose = SkeletonPose.Create(skeleton); skeletons.Add(skeleton, skeletonPose); } meshNode.SkeletonPose = skeletonPose; } } }
public ActiveRagdollSample(Microsoft.Xna.Framework.Game game) : base(game) { GraphicsScreen.DrawReticle = true; // Add game objects which allow to shoot balls and grab rigid bodies. _ballShooterObject = new BallShooterObject(Services) { Speed = 10 }; GameObjectService.Objects.Add(_ballShooterObject); _grabObject = new GrabObject(Services); GameObjectService.Objects.Add(_grabObject); var modelNode = ContentManager.Load <ModelNode>("Dude/Dude"); _meshNode = modelNode.GetSubtree().OfType <MeshNode>().First().Clone(); _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0)); SampleHelper.EnablePerPixelLighting(_meshNode); GraphicsScreen.Scene.Children.Add(_meshNode); // Create a copy of the dude's skeleton. _targetSkeletonPose = SkeletonPose.Create(_meshNode.Mesh.Skeleton); // Animate the _targetSkeletonPose. var animations = _meshNode.Mesh.Animations; var loopingAnimation = new AnimationClip <SkeletonPose>(animations.Values.First()) { LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_targetSkeletonPose); // Create a ragdoll for the Dude model. _ragdoll = new Ragdoll(); DudeRagdollCreator.Create(_targetSkeletonPose, _ragdoll, Simulation, 0.571f); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _meshNode.PoseWorld; _ragdoll.UpdateBodiesFromSkeleton(_targetSkeletonPose); // In this sample we use an active ragdoll. We need joints because constraint ragdoll // motors only affect the body rotations. _ragdoll.EnableJoints(); // We disable limits. If limits are enabled, the ragdoll could get unstable if // the animation tries to move a limb beyond an allowed limit. (This happens if // a pose in the animation violates one of our limits.) _ragdoll.DisableLimits(); // Set all motors to constraint motors. Constraint motors are like springs that // rotate the limbs to a target position. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Constraint; motor.ConstraintDamping = 10000; motor.ConstraintSpring = 100000; } } _ragdoll.EnableMotors(); // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); // Add a rigid body. var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f)) { Name = "Box", Pose = new Pose(new Vector3F(0, 3, 0)), }; Simulation.RigidBodies.Add(box); }
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 FacialAnimationSample(Microsoft.Xna.Framework.Game game) : base(game) { _graphicsScreen = new DeferredGraphicsScreen(Services) { DrawReticle = false }; GraphicsService.Screens.Insert(0, _graphicsScreen); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add a game object which adds some GUI controls for the deferred graphics // screen to the Options window. GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); // Use a fixed camera. var projection = new PerspectiveProjection(); projection.SetFieldOfView( ConstantsF.PiOver4, GraphicsService.GraphicsDevice.Viewport.AspectRatio, 0.1f, 10); var cameraNode = new CameraNode(new Camera(projection)); cameraNode.LookAt(new Vector3F(0.15f, 0.15f, 0.5f), new Vector3F(0.1f, 0.15f, 0), Vector3F.Up); _graphicsScreen.Scene.Children.Add(cameraNode); _graphicsScreen.ActiveCameraNode = cameraNode; // Lighting setup: var keyLight = new LightNode(new Spotlight { DiffuseIntensity = 0.6f, SpecularIntensity = 0.4f }); keyLight.LookAt(new Vector3F(-2, 2, 2), new Vector3F(), Vector3F.Up); _graphicsScreen.Scene.Children.Add(keyLight); var backLight = new LightNode(new Spotlight { DiffuseIntensity = 0.3f, SpecularIntensity = 0.3f }); backLight.LookAt(new Vector3F(1, 0.5f, -2), new Vector3F(), Vector3F.Up); _graphicsScreen.Scene.Children.Add(backLight); var fillLight = new LightNode(new AmbientLight { HemisphericAttenuation = 1, Intensity = 0.1f }); _graphicsScreen.Scene.Children.Add(fillLight); // The scene does not have a proper background. That's why the exposure is a // bit off. --> Reduce the max exposure. var hdrFilter = _graphicsScreen.PostProcessors.OfType <HdrFilter>().First(); hdrFilter.MaxExposure = 6; // Load the customized "Sintel" model (original: Durian Open Movie Project - http://www.sintel.org/). var model = ContentManager.Load <ModelNode>("Sintel/Sintel-Head").Clone(); model.PoseWorld = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(MathHelper.ToRadians(10)) * Matrix33F.CreateRotationX(-MathHelper.ToRadians(90))); _graphicsScreen.Scene.Children.Add(model); // The model consists of a root node and a mesh node. // ModelNode "Sintel-Head" // MeshNode "Sintel" _sintel = (MeshNode)model.Children[0]; // The model contains two skeletal animations: // - "MOUTH-open" is just a single frame. // - "Test" is a short animation (250 frames). // In the Options window, we will add a slider to move the jaw. // Slider.Value = 0 ... mouth closed (default) _mouthClosedPose = SkeletonPose.Create(_sintel.Mesh.Skeleton); // Slider.Value = 1 ... mouth open (copied from the "MOUTH-open" animation) SkeletonKeyFrameAnimation mouthOpen = _sintel.Mesh.Animations["MOUTH-open"]; _mouthOpenPose = SkeletonPose.Create(_sintel.Mesh.Skeleton); mouthOpen.GetValue(TimeSpan.Zero, ref _mouthOpenPose, ref _mouthOpenPose, ref _mouthOpenPose); // Turn the "Test" animation into an endless loop. _skeletalAnimation = new AnimationClip <SkeletonPose>(_sintel.Mesh.Animations["Test"]) { Duration = TimeSpan.MaxValue, LoopBehavior = LoopBehavior.Cycle }; // Mesh has several morph targets for facial animation, which are imported // automatically via the content pipeline. Unfortunately, the XNA content // pipeline cannot import morph target animations automatically. // In this demo, we will create a morph target animation in code. _morphingAnimation = CreateMorphingAnimation(); CreateGuiControls(); }