Ejemplo n.º 1
0
        /// <summary>
        /// Performs a local motion planning to estimate the next pose
        /// </summary>
        /// <param name="velocity"></param>
        /// <param name="time"></param>
        /// <param name="currentPosition"></param>
        /// <param name="currentRotation"></param>
        /// <param name="targetPosition"></param>
        /// <param name="targetRotation"></param>
        /// <returns></returns>
        private MTransform DoLocalMotionPlanning(double velocity, TimeSpan time, MVector3 currentPosition, MQuaternion currentRotation, MVector3 targetPosition, MQuaternion targetRotation)
        {
            //Create a resulting transform
            MTransform result = new MTransform();


            //Estimate the delta
            MVector3 deltaPosition = targetPosition.Subtract(currentPosition);

            //Estimate the meximum allowed delta
            double maxTranslationDelta = velocity * time.TotalSeconds;

            //Limit the maximum
            if (deltaPosition.Magnitude() >= maxTranslationDelta)
            {
                deltaPosition = deltaPosition.Normalize();
                deltaPosition = deltaPosition.Multiply(maxTranslationDelta);
            }


            float  angularVelocityReach = 100f;
            double angle = Math.Abs(MQuaternionExtensions.Angle(currentRotation, targetRotation));

            double maxAngle = angularVelocityReach * time.TotalSeconds;

            //Estimate the blendweihgt for the oreitnation blending
            double weight = Math.Min(1, maxAngle / angle);

            result.Position = currentPosition.Add(deltaPosition);
            result.Rotation = MQuaternionExtensions.Slerp(currentRotation, targetRotation, (float)weight);
            //result.Time = time;


            return(result);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Performs the actual motion planning
        /// </summary>
        /// <param name="velocity"></param>
        /// <param name="angularVelocity"></param>
        /// <param name="time"></param>
        /// <param name="currentPosition"></param>
        /// <param name="currentRotation"></param>
        /// <param name="targetPosition"></param>
        /// <param name="targetRotation"></param>
        /// <returns></returns>
        private MTransform DoLocalMotionPlanning(float velocity, float angularVelocity, TimeSpan time, MVector3 currentPosition, MQuaternion currentRotation, MVector3 targetPosition, MQuaternion targetRotation)
        {
            MTransform result = new MTransform();

            MVector3 delta = targetPosition.Subtract(currentPosition);
            double   angle = Math.Abs(MQuaternionExtensions.Angle(currentRotation, targetRotation));

            double maxTranslationDelta = velocity * time.TotalSeconds;

            if (delta.Magnitude() >= maxTranslationDelta)
            {
                delta = delta.Normalize();
                delta = delta.Multiply(maxTranslationDelta);
            }

            //To do consider self collision



            double maxAngle = angularVelocity * time.TotalSeconds;

            if (angle < maxAngle)
            {
                angle = maxAngle;
            }

            double weight = Math.Min(1, maxAngle / angle);

            result.Position = currentPosition.Add(delta);
            result.Rotation = MQuaternionExtensions.Slerp(currentRotation, targetRotation, (float)weight);
            //result.Time = time;


            return(result);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Computes the rotation to rotate from one vector to the other
        /// </summary>
        /// <param name="from">The start direction</param>
        /// <param name="to">The desired direction</param>
        /// <returns></returns>
        private static MQuaternion FromToRotation(MVector3 from, MVector3 to)
        {
            //Normalize both vectors
            from = from.Normalize();
            to   = to.Normalize();

            //Estimate the rotation axis
            MVector3 axis = MVector3Extensions.Cross(from, to).Normalize();

            //Compute the phi angle
            double phi = Math.Acos(MVector3Extensions.Dot(from, to)) / (from.Magnitude() * to.Magnitude());

            //Create a new quaternion representing the rotation
            MQuaternion result = new MQuaternion()
            {
                X = Math.Sin(phi / 2) * axis.X,
                Y = Math.Sin(phi / 2) * axis.Y,
                Z = Math.Sin(phi / 2) * axis.Z,
                W = Math.Cos(phi / 2)
            };

            //Perform is nan check and return identity quaternion
            if (double.IsNaN(result.W) || double.IsNaN(result.X) || double.IsNaN(result.Y) || double.IsNaN(result.Z))
            {
                result = new MQuaternion(0, 0, 0, 1);
            }

            //Return the estimated rotation
            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Performs local motion planning to reach the defined point
        /// </summary>
        /// <param name="velocity"></param>
        /// <param name="time"></param>
        /// <param name="currentPosition"></param>
        /// <param name="currentRotation"></param>
        /// <param name="targetPosition"></param>
        /// <param name="targetRotation"></param>
        /// <returns></returns>
        private MTransform DoLocalMotionPlanning(double velocity, double angularVelocity, TimeSpan time, MVector3 currentPosition, MQuaternion currentRotation, MVector3 targetPosition, MQuaternion targetRotation)
        {
            //Create a new transform representing the result
            MTransform result = new MTransform();

            //Estimate the vector to reach the goal
            MVector3 delta    = targetPosition.Subtract(currentPosition);
            float    distance = delta.Magnitude();

            //Determine the angular distance
            double angle = Math.Abs(MQuaternionExtensions.Angle(currentRotation, targetRotation));


            //Determine the max translation delta and max angle
            double maxTranslationDelta = velocity * time.TotalSeconds;
            double maxAngle            = angularVelocity * time.TotalSeconds;

            //Compute the translation weight
            float translationWeight = (float)Math.Min(1, maxTranslationDelta / delta.Magnitude());

            //Compute the rotation weight
            float rotationWeight = (float)Math.Min(1, maxAngle / angle);

            //Limit the translation
            if (delta.Magnitude() >= maxTranslationDelta)
            {
                delta = delta.Normalize();
                delta = delta.Multiply(maxTranslationDelta);
            }


            //Compute the new position
            result.Position = currentPosition.Add(delta);

            if (angularVelocity == 0)
            {
                result.Rotation = MQuaternionExtensions.Slerp(currentRotation, targetRotation, translationWeight);
            }

            else
            {
                result.Rotation = MQuaternionExtensions.Slerp(currentRotation, targetRotation, rotationWeight);
            }


            return(result);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Do step routine in which the actual simulation result is generated
        /// </summary>
        /// <param name="time"></param>
        /// <param name="simulationState"></param>
        /// <returns></returns>
        public override MSimulationResult DoStep(double time, MSimulationState simulationState)
        {
            //Create a new simulation result
            MSimulationResult result = new MSimulationResult()
            {
                Events             = new List <MSimulationEvent>(),
                Constraints        = simulationState.Constraints ?? new List <MConstraint>(),
                SceneManipulations = new List <MSceneManipulation>()
            };

            this.SkeletonAccess.SetChannelData(simulationState.Current.Copy());

            // Target position we want to transform to
            MVector3 targetPos = this.targetTransform.Position;

            // Fully body posture. Only Pelvis Center (first joint) has to be manipulated.
            List <double> posture = simulationState.Current.PostureData;

            // Current position and distance to target.
            MVector3 currentPos = this.SkeletonAccess.GetRootPosition(simulationState.Initial.AvatarID);
            MVector3 distance   = targetPos.Subtract(currentPos);

            // Current rotation and rotational diff to target
            MQuaternion currentRot = this.SkeletonAccess.GetRootRotation(simulationState.Initial.AvatarID);
            MQuaternion targetRot  = this.targetTransform.Rotation;



            MVector3 newPos;

            MVector3 deltaDistance = distance.Clone();


            if (this.velocity > 0)
            {
                deltaDistance = distance.Normalize().Multiply(this.velocity * time);
                Console.WriteLine("Delta v: " + deltaDistance.Magnitude() + " " + time + " " + this.velocity);
            }



            // If no velocity set or distance very close, directly morph to target position and rotation.
            if (this.velocity <= 0 || distance.Magnitude() < deltaDistance.Magnitude())
            {
                newPos = targetPos;

                // Set rotation
                //posture[3] = this.targetTransform.Rotation.W;
                //posture[4] = this.targetTransform.Rotation.X;
                //posture[5] = this.targetTransform.Rotation.Y;
                //posture[6] = this.targetTransform.Rotation.Z;

                // Add end event.
                Console.WriteLine("Finished with vel " + this.velocity + " at " + distance.Magnitude());
                result.Events.Add(new MSimulationEvent(this.instruction.Name, mmiConstants.MSimulationEvent_End, this.instruction.ID));
            }
            else // if velocity > 0 and distance sufficiently large, we should apply linear translation with the provided velocity.
            {
                newPos = currentPos.Add(deltaDistance);
                Console.WriteLine("Target Location: " + this.targetTransform.Position + " " + currentPos + " " + distance + " " + deltaDistance + " " + newPos);
            }

            Console.WriteLine("newposrot: " + newPos + " " + targetRot);
            this.SkeletonAccess.SetRootPosition(simulationState.Current.AvatarID, newPos);
            this.SkeletonAccess.SetRootRotation(simulationState.Current.AvatarID, targetRot);

            result.Posture = this.SkeletonAccess.GetCurrentPostureValues(simulationState.Current.AvatarID);

            Console.WriteLine("Frame : " + result.Posture.PostureData[0] + " " + result.Posture.PostureData[1] + " " + result.Posture.PostureData[2] + " " + result.Posture.PostureData[3] + " " + result.Posture.PostureData[4] + " " + result.Posture.PostureData[5] + " " + result.Posture.PostureData[6] + " ");

            //Return the result
            return(result);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Basic do step routine that is executed for each frame and generates the actual motion.
        /// </summary>
        /// <param name="time"></param>
        /// <param name="simulationState"></param>
        /// <returns></returns>
        private MSimulationResult DoStepBlending(double time, MSimulationState simulationState)
        {
            //Create a new simulation result
            MSimulationResult result = new MSimulationResult()
            {
                Events             = simulationState.Events ?? new List <MSimulationEvent>(),
                Constraints        = simulationState.Constraints,
                SceneManipulations = simulationState.SceneManipulations ?? new List <MSceneManipulation>(),
                Posture            = simulationState.Current
            };


            //Directly operate on the global constraints -> since no ik is computed
            List <MConstraint> globalConstraints = result.Constraints;

            //Assign the global constraints to the constraint manager
            this.constraintManager.SetConstraints(ref globalConstraints);

            //Use the initial state (approved posture of last frame)
            this.SkeletonAccess.SetChannelData(simulationState.Initial);

            //Get the current hand position and rotation
            MVector3    currentHandPosition = this.SkeletonAccess.GetGlobalJointPosition(this.AvatarDescription.AvatarID, this.handJoint);
            MQuaternion currentHandRotation = this.SkeletonAccess.GetGlobalJointRotation(this.AvatarDescription.AvatarID, this.handJoint);


            MJointConstraint jointConstraint = null;

            switch (this.handJoint)
            {
            case MJointType.LeftWrist:
                jointConstraint = this.constraintManager.GetEndeffectorConstraint(MJointType.LeftWrist);
                break;

            case MJointType.RightWrist:
                jointConstraint = this.constraintManager.GetEndeffectorConstraint(MJointType.RightWrist);
                break;
            }


            //Handle the joint constraint
            if (jointConstraint != null)
            {
                //Get the current hand positon based on the constraint
                currentHandPosition = jointConstraint.GeometryConstraint.GetGlobalPosition(this.SceneAccess);
                currentHandRotation = jointConstraint.GeometryConstraint.GetGlobalRotation(this.SceneAccess);
            }

            //Set the skeleton to the current state
            this.SkeletonAccess.SetChannelData(simulationState.Current);


            //Determine the target hand position (either underlying MMU or given via boundary constraints)
            MVector3    targetHandPosition = this.SkeletonAccess.GetGlobalJointPosition(this.AvatarDescription.AvatarID, this.handJoint);
            MQuaternion targetHandRotation = this.SkeletonAccess.GetGlobalJointRotation(this.AvatarDescription.AvatarID, this.handJoint);

            //Move the hand from the current position to the target position
            MVector3 deltaPosition = targetHandPosition.Subtract(currentHandPosition);

            float angle = (float)MQuaternionExtensions.Angle(currentHandRotation, targetHandRotation);

            //Compute the distance of the hand to the target hand position
            float distanceToGoal = deltaPosition.Magnitude();

            //Compute the max distance which can be covered within the current frame
            float maxDistance = (float)(time * this.velocity);

            //Compute the max allowed angle
            float maxAngle = (float)(time * this.angularVelocity);

            //Compute the weight for slerping (weight increases with shrinking distance to target)
            float translationWeight = Math.Min(1.0f, maxDistance / distanceToGoal);

            //Compute the rotation weight
            float rotationWeight = Math.Min(1.0f, maxAngle / angle);

            //Blend from the current rotation to the target
            result.Posture = Blending.PerformBlend((IntermediateSkeleton)this.SkeletonAccess, simulationState.Initial, simulationState.Current, Math.Min(translationWeight, rotationWeight), true);

            this.SkeletonAccess.SetChannelData(result.Posture);

            if (distanceToGoal < 0.01f)
            {
                result.Events.Add(new MSimulationEvent()
                {
                    Name      = "Release Finished",
                    Reference = this.instruction.ID,
                    Type      = mmiConstants.MSimulationEvent_End
                });

                //Remove all constraints for the respective hand
                this.constraintManager.RemoveEndeffectorConstraints(this.handJoint);
            }
            else
            {
                //Remove the endeffector constraint
                this.constraintManager.RemoveEndeffectorConstraints(this.handJoint);

                //Update the constraint
                this.constraintManager.SetEndeffectorConstraint(this.handJoint, this.SkeletonAccess.GetGlobalJointPosition(result.Posture.AvatarID, this.handJoint), this.SkeletonAccess.GetGlobalJointRotation(result.Posture.AvatarID, this.handJoint));
            }



            return(result);
        }
Ejemplo n.º 7
0
 public static double SqrMagnitude(this MVector3 vector)
 {
     return(vector.Magnitude() * vector.Magnitude());
 }
Ejemplo n.º 8
0
        public void ScaleSkeleton(MAvatarPosture globalTarget, Dictionary <MJointType, string> joint_map)
        {
            List <MJointType> spine = new List <MJointType>()
            {
                MJointType.S1L5Joint, MJointType.T12L1Joint, MJointType.T1T2Joint, MJointType.C4C5Joint, MJointType.HeadJoint
            };

            if (spine.Contains(this.GetMJoint().Type))
            {
                //float shoulder_height = getJointPosition(HumanBodyBones.LeftUpperArm, anim).y;
                double shoulder_height = getJointPosition(globalTarget, joint_map[MJointType.HeadJoint]).Y;
                double hip_height      = getJointPosition(globalTarget, joint_map[MJointType.PelvisCentre]).Y;
                double spine_length    = shoulder_height - hip_height;


                ((RJoint)this.parentJoint).boneLength = (this.GetOffsetPositions()).Multiply(spine_length).Magnitude();
                this.GetOffsetPositions().X           = 0;
                this.GetOffsetPositions().Y           = 1.0;
                this.GetOffsetPositions().Z           = 0;
            }
            if (this.joint.Type == MJointType.Root)
            {
                //MVector3 rootPos = getJointPosition(globalTarget, joint_map[MJointType.Root]);
                //this.SetOffsets(rootPos);
            }
            else if (this.joint.Type == MJointType.PelvisCentre)
            {
                MVector3 hips      = getJointPosition(globalTarget, joint_map[MJointType.PelvisCentre]).Clone();
                MVector3 shoulder  = getJointPosition(globalTarget, joint_map[MJointType.LeftShoulder]);
                MVector3 leftupleg = getJointPosition(globalTarget, joint_map[MJointType.LeftHip]);

                // find the average z axis position of shoulders and hips to find initial position of hip
                hips.Z = (shoulder.Z + leftupleg.Z) / 2;
                // raise hip to the hight of the target avatars hip height.
                hips.Y = leftupleg.Y;
                MVector3 root = new MVector3(hips.X, 0, hips.Z);
                ((RJoint)this.parentJoint).SetOffsets(root);
                hips.X = 0;
                hips.Z = 0;
                this.SetOffsets(hips);
            }
            else
            {
                double factor = 0.0d;
                if (this.parentJoint.children.Count == 3 && this.parentJoint.children[0] != this)
                {
                    // If there are two children (e.g. pelvis / upper spine), take the half distance between both children
                    factor = GetJointDistance(globalTarget, joint_map[this.parentJoint.children[1].GetMJoint().Type], joint_map[this.parentJoint.children[2].GetMJoint().Type]) / 2.0d;
                }
                else
                {
                    // If there is one child, take the parent bone length to scale target position
                    factor = ((RJoint)this.parentJoint).boneLength;
                }
                // scale offset to scale the skeleton to match bone lengths.
                this.SetOffsets(this.GetOffsetPositions().Multiply(factor));


                // handle special cases for shoulders and hands
                string jointID = this.GetMJoint().ID;

                if (jointID.Contains("Shoulder"))
                {
                    // in case of shoulders, they have to be raised in up direction.
                    double shoulder_height = getJointPosition(globalTarget, joint_map[this.GetMJoint().Type]).Y;
                    double current_Pos     = this.GetShoulderHeight();
                    shoulder_height             = shoulder_height - current_Pos;
                    this.GetOffsetPositions().Y = shoulder_height;
                }
            }
            if (this.children.Count > 0 && this.children[0].GetMJoint().ID.Contains("Tip"))
            {
                // Finger Tips
                MVector3 offsetVector = this.children[0].GetOffsetPositions();
                this.boneLength = offsetVector.Magnitude();
            }
            else
            {
                // if this is not the last joint in a sequence, scale depending on distance to child human bone
                if (joint_map.ContainsKey(this.children[0].GetMJoint().Type) && joint_map.ContainsKey(this.GetMJoint().Type))
                {
                    this.boneLength = GetJointDistance(globalTarget, joint_map[this.GetMJoint().Type], joint_map[this.children[0].GetMJoint().Type]);
                }
                else
                {
                    this.boneLength = 0.1;
                }
            }

            // recurse
            foreach (Joint child in this.children)
            {
                if (!child.GetMJoint().ID.Contains("Tip"))
                {
                    ((RJoint)(child)).ScaleSkeleton(globalTarget, joint_map);
                }
            }

            if (this.GetMJoint().ID.Contains("Wrist"))
            {
                MVector3   wristPos = this.GetGlobalPosition();//getJointPosition(globalTarget, joint_map[this.GetMJoint().Type]);
                MTransform Twrist   = new MTransform("tmp", this.GetGlobalPosition(), this.GetGlobalRotation());
                Joint      middle   = this.children[0];

                Joint index  = this.children[1];
                Joint ring   = this.children[2];
                Joint little = this.children[3];
                Joint thumb  = this.children[4];

                double middle_shift = 0.0;
                if (joint_map.ContainsKey(middle.GetMJoint().Type))
                {
                    MVector3 MiddlePos = ((RJoint)middle).GetFingerPosition(globalTarget, joint_map, 0);
                    middle_shift = MiddlePos.Z;
                    MiddlePos.Z  = 0;
                    ((RJoint)this.children[0]).SetOffsets(MiddlePos);
                }
                else
                {
                    ((RJoint)this.children[0]).SetOffsets(new MVector3(0, 0.1, 0));
                }

                if (joint_map.ContainsKey(index.GetMJoint().Type))
                {
                    MVector3 IndexPos = ((RJoint)index).GetFingerPosition(globalTarget, joint_map, middle_shift);
                    ((RJoint)this.children[1]).SetOffsets(IndexPos);
                }
                else
                {
                    ((RJoint)this.children[1]).SetOffsets(new MVector3(0, 0.1, 0.02));
                }

                if (joint_map.ContainsKey(ring.GetMJoint().Type))
                {
                    MVector3 RingPos = ((RJoint)ring).GetFingerPosition(globalTarget, joint_map, middle_shift);
                    ((RJoint)this.children[2]).SetOffsets(RingPos);
                }
                else
                {
                    ((RJoint)this.children[2]).SetOffsets(new MVector3(0, 0.1, -0.02));
                }
                if (joint_map.ContainsKey(little.GetMJoint().Type))
                {
                    MVector3 LittlePos = ((RJoint)little).GetFingerPosition(globalTarget, joint_map, middle_shift);
                    ((RJoint)this.children[3]).SetOffsets(LittlePos);
                }
                else
                {
                    ((RJoint)this.children[3]).SetOffsets(new MVector3(0, 0.1, -0.04));
                }

                if (joint_map.ContainsKey(thumb.GetMJoint().Type))
                {
                    MVector3 ThumbPos = ((RJoint)thumb).GetFingerPosition(globalTarget, joint_map, middle_shift);
                    ((RJoint)this.children[4]).SetOffsets(ThumbPos);
                }
                else
                {
                    ((RJoint)this.children[4]).SetOffsets(new MVector3(0, 0.02, 0.02));
                }
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Method performs a local motion planning and tries to reach the specified goal position and rotation using the given velocity,angular velocity and time.
        /// </summary>
        /// <param name="velocity"></param>
        /// <param name="angularVelocity"></param>
        /// <param name="time"></param>
        /// <param name="currentPosition"></param>
        /// <param name="currentRotation"></param>
        /// <param name="targetPosition"></param>
        /// <param name="targetRotation"></param>
        /// <returns></returns>
        private MTransform DoLocalMotionPlanning(double velocity, double angularVelocity, TimeSpan time, MVector3 currentPosition, MQuaternion currentRotation, MVector3 targetPosition, MQuaternion targetRotation, bool collisionAvoidance)
        {
            //Create a new transform representing the result
            MTransform result = new MTransform();

            //Estimate the delta
            MVector3 delta = targetPosition.Subtract(currentPosition);

            //Determine the current delta angle
            double angle = Math.Abs(MQuaternionExtensions.Angle(currentRotation, targetRotation));

            //Determine the max translation delta and max angle in the current frame
            double maxTranslationDelta = velocity * time.TotalSeconds;
            double maxAngle            = angularVelocity * time.TotalSeconds;

            //Estimate the blend weight for the rotation and position
            float rotationWeight = (float)Math.Min(1, maxAngle / angle);
            float positionWeight = (float)Math.Min(1, maxTranslationDelta / delta.Magnitude());

            //Limit the max translation
            if (delta.Magnitude() >= maxTranslationDelta)
            {
                delta = delta.Normalize();
                delta = delta.Multiply(maxTranslationDelta);
            }


            if (collisionAvoidance)
            {
                MVector3 collisionAvoidanceForce = this.ComputCollisionAvoidance(currentPosition, delta);

                //if (collisionAvoidanceForce.Magnitude() > 0)
                //    MMICSharp.Adapter.Logger.Log(MMICSharp.Adapter.Log_level.L_INFO, "Collision avoidance force: " + collisionAvoidanceForce.Magnitude());

                //Add the collision avoidance force on top
                delta = delta.Add(collisionAvoidanceForce);

                //Limit the max translation
                if (delta.Magnitude() >= maxTranslationDelta)
                {
                    delta = delta.Normalize();
                    delta = delta.Multiply(maxTranslationDelta);
                }
            }

            //Compute the new position
            result.Position = currentPosition.Add(delta);


            //Compute the new rotation by interpolating towards the target rotation
            if (angularVelocity > 0)
            {
                result.Rotation = MQuaternionExtensions.Slerp(currentRotation, targetRotation, rotationWeight);
            }

            //Use the rotation weight
            else
            {
                result.Rotation = MQuaternionExtensions.Slerp(currentRotation, targetRotation, positionWeight);
            }


            //Return the simulation result
            return(result);
        }
Ejemplo n.º 10
0
        public override MSimulationResult DoStep(double time, MSimulationState simulationState)
        {
            //Create a new simulation result
            MSimulationResult result = new MSimulationResult()
            {
                Events             = simulationState.Events ?? new List <MSimulationEvent>(),
                Constraints        = simulationState.Constraints ?? new List <MConstraint>(),
                SceneManipulations = simulationState.SceneManipulations ?? new List <MSceneManipulation>()
            };

            //Assign the constraints to a temp varilable
            List <MConstraint> constraints = result.Constraints;

            //Use the constraint manager to manage the constraints
            constraintManager.SetConstraints(ref constraints);


            //Get the hand position and rotation of the last frame (approved result)
            this.SkeletonAccess.SetChannelData(simulationState.Initial);
            MVector3    currentHandPosition = this.SkeletonAccess.GetGlobalJointPosition(this.AvatarDescription.AvatarID, this.handJoint);
            MQuaternion currentHandRotation = this.SkeletonAccess.GetGlobalJointRotation(this.AvatarDescription.AvatarID, this.handJoint);


            //Get the desired hand position (of the underlying motion e.g. idle)
            this.SkeletonAccess.SetChannelData(simulationState.Current);
            MVector3    targetHandPosition = this.SkeletonAccess.GetGlobalJointPosition(this.AvatarDescription.AvatarID, this.handJoint);
            MQuaternion targetHandRotation = this.SkeletonAccess.GetGlobalJointRotation(this.AvatarDescription.AvatarID, this.handJoint);


            //Add an offset on top of the position if desired
            if (this.addOffset)
            {
                targetHandPosition = ComputeNewPositionWithOffset(targetHandPosition, simulationState.Current);
            }

            //Move the hand from the current position to the target position
            MVector3 deltaPosition = targetHandPosition.Subtract(currentHandPosition);

            //Compute the distance of the hand to the target hand position
            float distanceToGoal = deltaPosition.Magnitude();


            //Create positioning finished event if not already created and distance below threshold
            if (distanceToGoal < this.positioningFinishedThreshold && !this.positioningFinished)
            {
                result.Events.Add(new MSimulationEvent("PositioningFinished", "PositioningFinished", this.instruction.ID));
                this.positioningFinished = true;
            }

            //Compute the current velocity based on the general max velocity and the velocity of the root motion
            float currentVelocity = this.velocity + this.ComputeRootVelocity(time, simulationState);

            //Compute the max distance which can be covered within the current frame
            float maxDistance = (float)(time * currentVelocity);

            //Compute the weight for slerping (weight increases with shrinking distance to target)
            float weight = Math.Max(0, 1 - distanceToGoal);

            //Create a new transform representing the next hand transform
            MTransform newHandTransform = new MTransform("", currentHandPosition.Clone(), currentHandRotation.Clone())
            {
                //Compute the new hand position (normalize delta position and multiply by max distance)
                Position = currentHandPosition.Add(deltaPosition.Normalize().Multiply(Math.Min(deltaPosition.Magnitude(), maxDistance))),

                //Just perform an interpolation to gather new hand rotation (weight is determined by the translation distance)
                Rotation = MQuaternionExtensions.Slerp(currentHandRotation, targetHandRotation, weight)
            };


            //Compute the corresponding positon/rotation of the object and
            //adjust the transformation of the object which should be moved
            result.SceneManipulations.Add(new MSceneManipulation()
            {
                Transforms = new List <MTransformManipulation>()
                {
                    new MTransformManipulation()
                    {
                        Target = this.objectTransform.ID,
                        //Compute the new global position of the object
                        Position = newHandTransform.TransformPoint(this.objectPositionOffset),
                        //Compute the new global rotation of the object
                        Rotation = newHandTransform.TransformRotation(this.objectRotationOffset)
                    }
                }
            });


            //Set the desired endeffector constraints
            constraintManager.SetEndeffectorConstraint(this.handJoint, newHandTransform.Position, newHandTransform.Rotation);

            //Generate a new posture using the ik solver and the specified constraints
            MIKServiceResult ikResult = this.ServiceAccess.IKService.CalculateIKPosture(simulationState.Current, constraintManager.GetJointConstraints(), new  Dictionary <string, string>());

            result.Posture = ikResult.Posture;

            //Return the result
            return(result);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Do step routine in which the actual simulation result is generated
        /// </summary>
        /// <param name="time"></param>
        /// <param name="simulationState"></param>
        /// <returns></returns>
        public override MSimulationResult DoStep(double time, MSimulationState simulationState)
        {
            //Create a new simulation result
            MSimulationResult result = new MSimulationResult()
            {
                Events             = simulationState.Events != null ? simulationState.Events : new List <MSimulationEvent>(),
                Constraints        = simulationState.Constraints,
                SceneManipulations = simulationState.SceneManipulations != null ? simulationState.SceneManipulations : new List <MSceneManipulation>()
            };


            //Create variables representing the next object position/rotation
            MTransform nextObjectTransform = subjectTransform.Clone();

            //Use the constraint manager to manage the constraints
            List <MConstraint> tmpConstraints = result.Constraints;

            //Set the constraints
            constraintManager.SetConstraints(ref tmpConstraints);


            //Compute the new hand position and rotation
            MVector3 deltaPosition  = this.targetObjectTransform.Position.Subtract(subjectTransform.Position);
            float    distanceToGoal = deltaPosition.Magnitude();

            //Get the current object position
            float maxDistance = (float)time * 1.0f;

            //Check the current distance to goal
            if (distanceToGoal < 0.01f)
            {
                result.Events.Add(new MSimulationEvent(this.instruction.Name, mmiConstants.MSimulationEvent_End, this.instruction.ID));
            }
            else
            {
                //Compute the new hand position (normalize delta position and multiply by max distance)
                nextObjectTransform.Position = this.subjectTransform.Position.Add(deltaPosition.Normalize().Multiply(Math.Min(distanceToGoal, maxDistance)));

                //Compute the weight for slerping (weight increases with shrinking distance to target)
                float weight = Math.Max(0, 1 - distanceToGoal);

                //Just perform an interpolation to gather new hand rotation (weight is determined by the translation distance)
                nextObjectTransform.Rotation = MQuaternionExtensions.Slerp(this.subjectTransform.Rotation, this.targetObjectTransform.Rotation, weight);
            }

            //Adjust the transformation of the object which should be moved
            result.SceneManipulations.Add(new MSceneManipulation()
            {
                Transforms = new List <MTransformManipulation>()
                {
                    new MTransformManipulation()
                    {
                        Target   = this.subjectTransform.ID,
                        Position = nextObjectTransform.Position,
                        Rotation = nextObjectTransform.Rotation
                    }
                }
            });

            //Get the current hand position in global space
            MVector3    globalHandPosition = nextObjectTransform.TransformPoint(this.handPositionOffset);
            MQuaternion globalHandRotation = nextObjectTransform.TransformRotation(this.handRotationOffset);

            //Set the desired endeffector constraints
            constraintManager.SetEndeffectorConstraint(this.handJoint, globalHandPosition, globalHandRotation);



            MIKServiceResult ikResult = this.ServiceAccess.IKService.CalculateIKPosture(simulationState.Current, constraintManager.GetJointConstraints(), new Dictionary <string, string>());

            //Generate a new posture using the ik solver and the specified constraints
            result.Posture = ikResult.Posture;

            //Return the result
            return(result);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Basic euclidean distance function for float arrays
        /// </summary>
        /// <param name="vector1"></param>
        /// <param name="vector2"></param>
        /// <returns></returns>
        private static float EuclideanDistance(MVector3 vector1, MVector3 vector2)
        {
            MVector3 diff = vector1.Subtract(vector2);

            return(diff.Magnitude());
        }