public SimulatedHandControllerPose(SimulatedHandControllerPose pose)
 {
     Id = pose.Id;
     LocalJointPoses = new MixedRealityPose[HandData.JointCount];
     SetZero();
     Array.Copy(pose.LocalJointPoses, LocalJointPoses, HandData.JointCount);
 }
        /// <summary>
        /// Initialize pose data for use in editor from files.
        /// </summary>
        /// <param name="poses">List of pose data assets with pose information.</param>
        public static void Initialize(IReadOnlyList <HandControllerPoseProfile> poses)
        {
            if (isInitialized)
            {
                return;
            }

            // To stabilize the simulated hand poses, we look
            // for the hand "open" pose, which we will use as a reference to offset
            // all other poses, so the "Palm" joint position stays the same for all simulated
            // poses. If no open pose is defined, we can't do anything and keep everything as it is.
            SimulatedHandControllerPose openPose = default;

            foreach (var poseData in poses)
            {
                if (poseData.Id.Equals("open"))
                {
                    openPose = new SimulatedHandControllerPose(poseData.Id);
                    openPose.FromJson(poseData.Data.text);
                    HandPoses.Add(openPose.Id, openPose);
                    //break;
                }
            }

            foreach (var poseData in poses)
            {
                if (poseData.Data != null)
                {
                    if (openPose != default)
                    {
                        // If we already found the open pose, we don't want it initialized again, since we took
                        // care of that above.
                        if (!poseData.Id.Equals("open"))
                        {
                            // We have open pose data, offset this pose using it's palm position.
                            var pose = new SimulatedHandControllerPose(poseData.Id);
                            pose.FromJson(poseData.Data.text);
                            OffsetJointsRelativeToOpenPosePalmPosition(openPose, pose);
                            HandPoses.Add(pose.Id, pose);
                        }
                    }
                    else
                    {
                        var pose = new SimulatedHandControllerPose(poseData.Id);
                        pose.FromJson(poseData.Data.text);
                        HandPoses.Add(pose.Id, pose);
                    }
                }

                if (poseData.IsDefault)
                {
                    DefaultHandPose = poseData;
                }
            }

            isInitialized = true;
        }
        /// <summary>
        /// Gets the pose for a given pose name, if it's registered.
        /// </summary>
        /// <param name="name">The name of the pose.</param>
        /// <param name="result">Hand pose reference.</param>
        /// <returns>True, if found.</returns>
        public static bool TryGetPoseByName(string name, out SimulatedHandControllerPose result)
        {
            if (HandPoses.TryGetValue(name, out var pose))
            {
                result = pose;
                return(true);
            }

            result = default;
            return(false);
        }
        private static void OffsetJointsRelativeToOpenPosePalmPosition(SimulatedHandControllerPose openPose, SimulatedHandControllerPose pose)
        {
            Vector3 openHandPalmPosition = openPose.LocalJointPoses[(int)TrackedHandJoint.Palm].Position;
            Vector3 posePalmPosition     = pose.LocalJointPoses[(int)TrackedHandJoint.Palm].Position;
            Vector3 offset = posePalmPosition - openHandPalmPosition;

            for (int i = 0; i < pose.LocalJointPoses.Length; i++)
            {
                pose.LocalJointPoses[i].Position -= offset;
            }
        }
        /// <summary>
        /// Interpolates between the poses a and b by the interpolant t.
        /// </summary>
        /// <param name="interpolatedPose"></param>
        /// <param name="a">Pose at t = 0.</param>
        /// <param name="b">Pose at t = 1.</param>
        /// <param name="t">The parameter t is clamped to the range [0,1].</param>
        public static void Lerp(ref SimulatedHandControllerPose interpolatedPose, SimulatedHandControllerPose a, SimulatedHandControllerPose b, float t)
        {
            for (int i = 0; i < interpolatedPose.LocalJointPoses.Length; i++)
            {
                var jointPoseA = a.LocalJointPoses[i];
                var jointPoseB = b.LocalJointPoses[i];

                var position = Vector3.Lerp(jointPoseA.Position, jointPoseB.Position, t);
                var rotation = Quaternion.Slerp(jointPoseA.Rotation, jointPoseB.Rotation, t);

                interpolatedPose.LocalJointPoses[i] = new MixedRealityPose(position, rotation);
            }

            interpolatedPose.Id = t >= 1 ? b.Id : a.Id;
        }
 /// <summary>Determines whether the specified object is equal to this instance.</summary>
 /// <param name="other">The specified object.</param>
 /// <returns>True, if the specified object is equal to this instance, otherwise false.</returns>
 public bool Equals(SimulatedHandControllerPose other)
 {
     return(Id == other.Id);
 }