예제 #1
0
        public void Solve(ref TransformBuffer localPose, float3 target)
        {
            ReadPose(ref localPose);

            quaternion tipGlobalRotation = globalTransforms[tipIndex].q;

            // 1. Force mid joint rotation to half stretch pose (override animation), forcing rotation will ensure the fold axis will be the same across all animation poses,
            // ensuring IK stability over time. This will also make sure the joint isn't broken by being fold along the wrong axis and in the wrong direction
            SetLocalRotation(midIndex, halfStretchedMidRotation);

            float3 midToRoot = RootPos - MidPos;
            float3 midToTip  = TipPos - MidPos;

            // 2. Get current axis and angle rotation between 2 limbs
            quaternion upperToLowerRot = Missing.forRotation(midToRoot, midToTip);
            float      upperToLowerAngle;
            float3     upperToLowerAxis = Missing.axisAngle(upperToLowerRot, out upperToLowerAngle);

            // 3. Extend or compress arm in order to reach distance to target
            float      desiredAngle   = GetTriangleAngle(midToRoot, midToTip, target - RootPos);
            quaternion unfoldRotation = quaternion.AxisAngle(upperToLowerAxis, desiredAngle - upperToLowerAngle);

            SetGlobalRotation(midIndex, math.mul(unfoldRotation, globalTransforms[midIndex].q));

            // 4. Align tip of the arm with target
            quaternion alignRotation = Missing.forRotation(TipPos - RootPos, target - RootPos);

            SetGlobalRotation(rootIndex, math.mul(alignRotation, globalTransforms[rootIndex].q));

            // 5. Preserve tip global rotation
            SetGlobalRotation(tipIndex, tipGlobalRotation);

            WritePose(ref localPose);
        }
예제 #2
0
 void WritePose(ref TransformBuffer localPose)
 {
     for (int i = rootIndex; i < jointIndices.Length; ++i)
     {
         localPose[jointIndices[i]] = localTransforms[i];
     }
 }
        internal AffineTransform ComputeGlobalJointTransform(ref TransformBuffer localPose, int jointIndex)
        {
            AffineTransform globalTransform = localPose[jointIndex];

            while (joints[jointIndex].parentIndex >= 0)
            {
                jointIndex      = joints[jointIndex].parentIndex;
                globalTransform = localPose[jointIndex] * globalTransform;
            }

            return(globalTransform);
        }
예제 #4
0
        void ReadPose(ref TransformBuffer localPose)
        {
            localTransforms[0]  = localPose[jointIndices[0]];
            globalTransforms[0] = rig.ComputeGlobalJointTransform(ref localPose, jointIndices[0]);

            for (int i = 1; i < jointIndices.Length; ++i)
            {
                AffineTransform localJoint = localPose[jointIndices[i]];
                localTransforms[i]  = localJoint;
                globalTransforms[i] = globalTransforms[i - 1] * localJoint;
            }
        }
예제 #5
0
        public override void RetargetPose(ref TransformBuffer sourceTransformBuffer, ref TransformBuffer targetTransformBuffer)
        {
#if USE_HUMAN_POSE_HANDLER_RETARGETING
            int affineTransformSize = UnsafeUtility.SizeOf <AffineTransform>();

            AffineTransform leftFootSource  = AffineTransform.identity;
            AffineTransform rightFootSource = AffineTransform.identity;
            AffineTransform leftHandSource  = AffineTransform.identity;
            AffineTransform rightHandSource = AffineTransform.identity;

            // 1. Compute IK target positions from source
            if (enableIK)
            {
                leftFootSource  = sourceRig.ComputeGlobalJointTransform(ref sourceTransformBuffer, feetIK.leftLimbSourceJointIndex);
                rightFootSource = sourceRig.ComputeGlobalJointTransform(ref sourceTransformBuffer, feetIK.rightLimbSourceJointIndex);

                leftHandSource  = sourceRig.ComputeGlobalJointTransform(ref sourceTransformBuffer, handsIK.leftLimbSourceJointIndex);
                rightHandSource = sourceRig.ComputeGlobalJointTransform(ref sourceTransformBuffer, handsIK.rightLimbSourceJointIndex);
            }

            // 2. Convert source transform buffer (joint transforms) to human pose (universal muscles values)
            AffineTransform rootTransform = sourceTransformBuffer[0];
            sourceTransformBuffer[0] = AffineTransform.identity;

            for (int i = 0; i < sourceTransformBuffer.Length; ++i)
            {
                sourceAvatarPose[i] = sourceTransformBuffer[i];
            }
            sourceHumanPoseHandler.SetInternalAvatarPose(sourceAvatarPose.Reinterpret <float>(affineTransformSize));
            sourceHumanPoseHandler.GetInternalHumanPose(ref humanPose);

            // 3. Convert human poses (muscles) to target transform buffer, retargeting
            targetHumanPoseHandler.SetInternalHumanPose(ref humanPose);
            targetHumanPoseHandler.GetInternalAvatarPose(targetAvatarPose.Reinterpret <float>(affineTransformSize));
            for (int i = 0; i < targetTransformBuffer.Length; ++i)
            {
                targetTransformBuffer[i] = targetAvatarPose[i];
            }

            // 4. Scale root motion and slightly lower pelvis
            targetTransformBuffer[0] = rootTransform * sourceToTargetScale;
            targetTransformBuffer[targetRig.BodyJointIndex] = new AffineTransform(targetTransformBuffer[targetRig.BodyJointIndex].t - new float3(0.0f, pelvisOffset, 0.0f), targetTransformBuffer[targetRig.BodyJointIndex].q);

            // 5. Solve feet & hands IK
            if (enableIK)
            {
                feetIK.Solve(ref targetTransformBuffer, leftFootSource.t * sourceToTargetScale, rightFootSource.t * sourceToTargetScale);
                handsIK.Solve(ref targetTransformBuffer, leftHandSource.t * sourceToTargetScale, rightHandSource.t * sourceToTargetScale);
            }
#endif
        }
예제 #6
0
        /// <summary>
        /// Function to perform clean up on the shader state.
        /// </summary>
        internal void CleanUp()
        {
            ConstantBuffers[0] = null;

            if (DefaultVertexShader != null)
            {
                DefaultVertexShader.Dispose();
            }

            DefaultVertexShader = null;

            if (TransformBuffer == null)
            {
                return;
            }

            TransformBuffer.Dispose();
            TransformBuffer = null;
        }
예제 #7
0
 public void Solve(ref TransformBuffer targetTransformBuffer, float3 leftTargetPosition, float3 rightTargetPosition)
 {
     leftLimbChainIK.Solve(ref targetTransformBuffer, leftTargetPosition);
     rightLimbChainIK.Solve(ref targetTransformBuffer, rightTargetPosition);
 }