예제 #1
0
        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);
        }
예제 #2
0
        // 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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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;
                }
            }
        }
예제 #5
0
        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();
        }