diff options
Diffstat (limited to 'Runtime/mecanim/human')
-rw-r--r-- | Runtime/mecanim/human/hand.cpp | 351 | ||||
-rw-r--r-- | Runtime/mecanim/human/hand.h | 124 | ||||
-rw-r--r-- | Runtime/mecanim/human/handle.h | 40 | ||||
-rw-r--r-- | Runtime/mecanim/human/human.cpp | 2405 | ||||
-rw-r--r-- | Runtime/mecanim/human/human.h | 390 |
5 files changed, 3310 insertions, 0 deletions
diff --git a/Runtime/mecanim/human/hand.cpp b/Runtime/mecanim/human/hand.cpp new file mode 100644 index 0000000..dd5e062 --- /dev/null +++ b/Runtime/mecanim/human/hand.cpp @@ -0,0 +1,351 @@ +#include "UnityPrefix.h" +#include "Runtime/mecanim/skeleton/skeleton.h" +#include "Runtime/mecanim/human/hand.h" + +namespace mecanim +{ + +namespace hand +{ + const static int32_t Phalange2DoF[hand::kLastPhalange][3] = + { + { kProximalDownUp, kProximalInOut, -1 }, // kProximal + { kIntermediateCloseOpen, -1, -1 }, // kIntermediate + { kDistalCloseOpen, -1, -1 } // kDistal + }; + + const static int32_t DoF2Bone[s_DoFCount] = + { + kThumb * kLastPhalange + kProximal, + kThumb * kLastPhalange + kProximal, + kThumb * kLastPhalange + kIntermediate, + kThumb * kLastPhalange + kDistal, + + kIndex * kLastPhalange + kProximal, + kIndex * kLastPhalange + kProximal, + kIndex * kLastPhalange + kIntermediate, + kIndex * kLastPhalange + kDistal, + + kMiddle * kLastPhalange + kProximal, + kMiddle * kLastPhalange + kProximal, + kMiddle * kLastPhalange + kIntermediate, + kMiddle * kLastPhalange + kDistal, + + kRing * kLastPhalange + kProximal, + kRing * kLastPhalange + kProximal, + kRing * kLastPhalange + kIntermediate, + kRing * kLastPhalange + kDistal, + + kLittle * kLastPhalange + kProximal, + kLittle * kLastPhalange + kProximal, + kLittle * kLastPhalange + kIntermediate, + kLittle * kLastPhalange + kDistal + }; + + + + skeleton::SetupAxesInfo const& GetAxeInfo(uint32_t index) + { + const static skeleton::SetupAxesInfo setupAxesInfoArray[s_BoneCount] = + { + {{0,0.125,0.125f,1},{0,1,0,0},{0,-25,-20},{0,25,20},{-1,-1,1,-1},math::kZYRoll,0}, // kThumb.kProximal + {{0,-0.2f,0,1},{0,1,0,0},{0,0,-40},{0,0,35},{-1,1,1,-1},math::kZYRoll,0}, // kThumb.kIntermediate + {{0,-0.2f,0,1},{0,1,0,0},{0,0,-40},{0,0,35},{-1,1,1,-1},math::kZYRoll,0}, // kThumb.kDistal + {{0,0.08f,0.3f,1},{0,0,1,0},{0,-20,-50},{0,20,50},{-1,-1,-1,-1},math::kZYRoll,0}, // kIndex.kProximal + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0}, // kIndex.kIntermediate + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0}, // kIndex.kDistal + {{0,0.04f,0.3f,1},{0,0,1,0},{0,-7.5f,-50},{0,7.5f,50},{-1,-1,-1,-1},math::kZYRoll,0}, // kMiddle.kProximal + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0}, // kMiddle.kIntermediate + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0}, // kMiddle.kDistal + {{0,-0.04f,0.3f,1},{0,0,1,0},{0,-7.5f,-50},{0,7.5f,50},{-1,1,-1,-1},math::kZYRoll,0}, // kRing.kProximal + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0}, // kRing.kIntermediate + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0}, // kRing.kDistal + {{0,-0.08f,0.3f,1},{0,0,1,0},{0,-20,-50},{0,20,50},{-1,1,-1,-1},math::kZYRoll,0}, // kLittle.kProximal + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0}, // kLittle.kIntermediate + {{0,0,0.33f,1},{0,0,1,0},{0,0,-45},{0,0,45},{-1,1,-1,-1},math::kZYRoll,0} // kLittle.kDistal + }; + + return setupAxesInfoArray[index]; + } + + + const char* FingerName(uint32_t aFinger) + { + const static char* fingerName[kLastFinger] = { + "Thumb", + "Index", + "Middle", + "Ring", + "Little" + }; + + return fingerName[aFinger]; + } + + const char* PhalangeName(uint32_t aFinger) + { + const static char* phalangeName[kLastPhalange] = { + "Proximal", + "Intermediate", + "Distal" + }; + return phalangeName[aFinger]; + } + + const char* FingerDoFName(uint32_t aFinger) + { + const static char* fingerDoFName[kLastFingerDoF] = { + "1 Stretched", + "Spread", + "2 Stretched", + "3 Stretched" + }; + return fingerDoFName[aFinger]; + } + + Hand::Hand() + { + memset(m_HandBoneIndex, -1, sizeof(int32_t)*s_BoneCount); + } + + int32_t MuscleFromBone(int32_t aBoneIndex, int32_t aDoFIndex) + { + int32_t ret = -1; + int32_t findex = GetFingerIndex(aBoneIndex); + int32_t pindex = GetPhalangeIndex(aBoneIndex); + + if(Phalange2DoF[pindex][2-aDoFIndex] != -1) + { + ret = findex * kLastFingerDoF + Phalange2DoF[pindex][2-aDoFIndex]; + } + + return ret; + } + + int32_t BoneFromMuscle(int32_t aDoFIndex) + { + return DoF2Bone[aDoFIndex]; + } + + Hand* CreateHand(memory::Allocator& arAlloc) + { + Hand* hand = arAlloc.Construct<Hand>(); + memset(hand->m_HandBoneIndex,-1,sizeof(int32_t)*kLastFinger*kLastPhalange); + + return hand; + } + + void DestroyHand(Hand *apHand, memory::Allocator& arAlloc) + { + if(apHand) + { + arAlloc.Deallocate(apHand); + } + } + + HandPose::HandPose() + { + int32_t i; + + for(i = 0; i < s_DoFCount; i++) + { + m_DoFArray[i]= 0; + } + + m_Override = 0; + m_CloseOpen = 0; + m_InOut = 0; + m_Grab = 0; + m_GrabX = math::xformIdentity(); + } + + void HandPoseCopy(HandPose const *apHandPoseSrc,HandPose *apHandPoseDst) + { + int32_t i; + + for(i = 0; i < s_DoFCount; i++) + { + apHandPoseDst->m_DoFArray[i] = apHandPoseSrc->m_DoFArray[i]; + } + + apHandPoseDst->m_Override = apHandPoseDst->m_Override; + apHandPoseDst->m_CloseOpen = apHandPoseDst->m_CloseOpen; + apHandPoseDst->m_InOut = apHandPoseDst->m_InOut; + apHandPoseDst->m_Grab = apHandPoseDst->m_Grab; + apHandPoseDst->m_GrabX = apHandPoseDst->m_GrabX; + } + + void HandSetupAxes(Hand const *apHand, skeleton::SkeletonPose const *apSkeletonPose, skeleton::Skeleton *apSkeleton, bool aLeft) + { + int32_t f,p,b; + + for(f = 0; f < kLastFinger; f++) + { + for(p = 0; p < kLastPhalange; p++) + { + float len = 1.0f; + int32_t skAxisBoneId = -1; + + b = GetBoneIndex(f,p); + int32_t skBoneIndex = apHand->m_HandBoneIndex[b]; + + if(p < kLastPhalange-1 && apHand->m_HandBoneIndex[GetBoneIndex(f,p+1)] >= 0) + { + skAxisBoneId = apHand->m_HandBoneIndex[GetBoneIndex(f,p+1)]; + } + else if(p > 0 && apHand->m_HandBoneIndex[GetBoneIndex(f,p-1)] >= 0) + { + skAxisBoneId = apHand->m_HandBoneIndex[GetBoneIndex(f,p-1)]; + len = -0.75f; + } + + if(skBoneIndex >= 0) + { + skeleton::SetupAxes(apSkeleton,apSkeletonPose, GetAxeInfo(b), skBoneIndex,skAxisBoneId,aLeft,len); + } + } + } + } + + void HandCopyAxes(Hand const *apSrcHand, skeleton::Skeleton const *apSrcSkeleton, Hand const *apHand, skeleton::Skeleton *apSkeleton) + { + int32_t i; + + for(i = 0; i < s_BoneCount; i++) + { + skeleton::Node const *srcNode = apSrcHand->m_HandBoneIndex[i] >= 0 ? &apSrcSkeleton->m_Node[apSrcHand->m_HandBoneIndex[i]] : 0; + skeleton::Node const *node = apHand->m_HandBoneIndex[i] >= 0 ? &apSkeleton->m_Node[apHand->m_HandBoneIndex[i]] : 0; + + if(srcNode != 0 && node != 0 && srcNode->m_AxesId != -1 && node->m_AxesId != -1) + { + apSkeleton->m_AxesArray[node->m_AxesId] = apSrcSkeleton->m_AxesArray[srcNode->m_AxesId]; + } + } + } + + void HandPoseSolve(HandPose const* apHandPoseIn,HandPose* apHandPoseOut) + { + int32_t f; + + for(f = 0; f < kLastFinger; f++) + { + int32_t i = f*kLastFingerDoF; + apHandPoseOut->m_DoFArray[i+kProximalDownUp] = (1-apHandPoseIn->m_Override) * apHandPoseIn->m_DoFArray[i+kProximalDownUp] + apHandPoseIn->m_CloseOpen; + apHandPoseOut->m_DoFArray[i+kProximalInOut] = (1-apHandPoseIn->m_Override) * apHandPoseIn->m_DoFArray[i+kProximalInOut] + apHandPoseIn->m_InOut; + apHandPoseOut->m_DoFArray[i+kIntermediateCloseOpen] = (1-apHandPoseIn->m_Override) * apHandPoseIn->m_DoFArray[i+kIntermediateCloseOpen] + apHandPoseIn->m_CloseOpen; + apHandPoseOut->m_DoFArray[i+kDistalCloseOpen] = (1-apHandPoseIn->m_Override) * apHandPoseIn->m_DoFArray[i+kDistalCloseOpen] + apHandPoseIn->m_CloseOpen; + } + } + + void Hand2SkeletonPose(Hand const *apHand, skeleton::Skeleton const *apSkeleton, HandPose const *apHandPose, skeleton::SkeletonPose *apSkeletonPose) + { + int32_t f,p; + + for(f = 0; f < kLastFinger; f++) + { + for(p = 0; p < kLastPhalange; p++) + { + int32_t i = GetBoneIndex(f,p); + + if(apHand->m_HandBoneIndex[i] >= 0) + { + math::float4 xyz = math::cond( math::bool4(Phalange2DoF[p][2] != -1,Phalange2DoF[p][1] != -1,Phalange2DoF[p][0] != -1,false), + math::float4(apHandPose->m_DoFArray[GetDoFIndex(f,Phalange2DoF[p][2])],apHandPose->m_DoFArray[GetDoFIndex(f,Phalange2DoF[p][1])],apHandPose->m_DoFArray[GetDoFIndex(f,Phalange2DoF[p][0])],0), + math::float4::zero()); + + skeleton::SkeletonSetDoF(apSkeleton,apSkeletonPose,xyz,apHand->m_HandBoneIndex[i]); + } + } + } + } + + void Skeleton2HandPose(Hand const *apHand, skeleton::Skeleton const *apSkeleton,skeleton::SkeletonPose const *apSkeletonPose, HandPose *apHandPose, float aOffset) + { + int32_t f,p; + + for(f = 0; f < kLastFinger; f++) + { + for(p = 0; p < kLastPhalange; p++) + { + int32_t i = GetBoneIndex(f,p); + + if(apHand->m_HandBoneIndex[i] >= 0) + { + const math::float4 xyz = skeleton::SkeletonGetDoF(apSkeleton,apSkeletonPose,apHand->m_HandBoneIndex[i]); + + if(Phalange2DoF[p][2] != -1) apHandPose->m_DoFArray[GetDoFIndex(f,Phalange2DoF[p][2])] = xyz.x().tofloat() + aOffset; + if(Phalange2DoF[p][1] != -1) apHandPose->m_DoFArray[GetDoFIndex(f,Phalange2DoF[p][1])] = xyz.y().tofloat() + aOffset; + if(Phalange2DoF[p][0] != -1) apHandPose->m_DoFArray[GetDoFIndex(f,Phalange2DoF[p][0])] = xyz.z().tofloat() + aOffset; + } + } + } + } + + void FingerLengths(Hand const *apHand, skeleton::Skeleton const *apSkeleton, float *apLengthArray) + { + int32_t f,p; + + for(f = 0; f < kLastFinger; f++) + { + apLengthArray[f] = 0.0f; + + for(p = 0; p < kLastPhalange; p++) + { + int32_t i = GetBoneIndex(f,p); + + if(apHand->m_HandBoneIndex[i] >= 0) + { + apLengthArray[f] += apSkeleton->m_AxesArray[apHand->m_HandBoneIndex[i]].m_Length; + } + } + } + } + + void FingerBaseFromPose(Hand const *apHand,skeleton::SkeletonPose const *apSkeletonPose,math::float4 *apPositionArray) + { + int32_t f; + + for(f = 0; f < kLastFinger; f++) + { + int32_t i = GetBoneIndex(f,kProximal); + + if(apHand->m_HandBoneIndex[i] >= 0) + { + apPositionArray[f] = apSkeletonPose->m_X[apHand->m_HandBoneIndex[i]].t; + } + } + } + + void FingerTipsFromPose(Hand const *apHand,skeleton::Skeleton const *apSkeleton, skeleton::SkeletonPose const *apSkeletonPose,math::float4 *apPositionArray) + { + int32_t f; + + for(f = 0; f < kLastFinger; f++) + { + int32_t i = GetBoneIndex(f,kDistal); + + if(apHand->m_HandBoneIndex[i] >= 0) + { + apPositionArray[f] = skeleton::SkeletonNodeEndPoint(apSkeleton,apHand->m_HandBoneIndex[i],apSkeletonPose); + } + } + } + + void FingersIKSolve(Hand const *apHand, skeleton::Skeleton const *apSkeleton,math::float4 const *apPositionArray, float *apWeightArray, skeleton::SkeletonPose *apSkeletonPose, skeleton::SkeletonPose *apSkeletonPoseWorkspace) + { + int32_t f; + + for(f = 0; f < kLastFinger; f++) + { + int32_t topIndex = apHand->m_HandBoneIndex[hand::GetBoneIndex(f,hand::kProximal)]; + int32_t midIndex = apHand->m_HandBoneIndex[hand::GetBoneIndex(f,hand::kIntermediate)]; + int32_t endIndex = apHand->m_HandBoneIndex[hand::GetBoneIndex(f,hand::kDistal)]; + + if(topIndex >= 0 && midIndex >= 0 && endIndex >= 0) + { + skeleton::Skeleton3BoneIK(apSkeleton,topIndex,midIndex,endIndex,apPositionArray[f],apWeightArray[f],apSkeletonPose,apSkeletonPoseWorkspace); + } + } + } +} +} diff --git a/Runtime/mecanim/human/hand.h b/Runtime/mecanim/human/hand.h new file mode 100644 index 0000000..1050340 --- /dev/null +++ b/Runtime/mecanim/human/hand.h @@ -0,0 +1,124 @@ +#pragma once + +#include "Runtime/mecanim/defs.h" +#include "Runtime/mecanim/memory.h" +#include "Runtime/mecanim/types.h" +#include "Runtime/Math/Simd/xform.h" + + +#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h" +#include "Runtime/Animation/MecanimArraySerialization.h" + + +namespace mecanim +{ + +namespace skeleton { struct Skeleton; struct SkeletonPose; struct SetupAxesInfo; } + +namespace hand +{ + enum Fingers + { + kThumb = 0 , + kIndex, + kMiddle, + kRing, + kLittle, + kLastFinger + }; + + enum Phalanges + { + kProximal = 0, + kIntermediate, + kDistal, + kLastPhalange + }; + + enum FingerDoF + { + kProximalDownUp = 0, + kProximalInOut, + kIntermediateCloseOpen, + kDistalCloseOpen, + kLastFingerDoF + }; + + const int32_t s_BoneCount = kLastFinger*kLastPhalange; + const int32_t s_DoFCount = kLastFinger*kLastFingerDoF; + + inline int32_t GetBoneIndex(int32_t fingerIndex, int32_t phalangeIndex) { return fingerIndex * kLastPhalange + phalangeIndex; }; + inline int32_t GetFingerIndex(int32_t boneIndex) { return boneIndex / kLastPhalange; }; + inline int32_t GetPhalangeIndex(int32_t boneIndex) { return boneIndex % kLastPhalange; }; + inline int32_t GetDoFIndex(int32_t fingerIndex, int32_t phalangeDoFIndex) { return fingerIndex * kLastFingerDoF + phalangeDoFIndex; }; + + const char* FingerName(uint32_t finger); + const char* FingerDoFName(uint32_t finger); + const char* PhalangeName(uint32_t finger); + + struct Hand + { + DEFINE_GET_TYPESTRING(Hand) + + Hand(); + int32_t m_HandBoneIndex[s_BoneCount]; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + STATIC_ARRAY_TRANSFER(int32_t, m_HandBoneIndex, s_BoneCount); + } + }; + + struct HandPose + { + DEFINE_GET_TYPESTRING(HandPose) + + HandPose(); + + math::xform m_GrabX; + float m_DoFArray[s_DoFCount]; + float m_Override; + float m_CloseOpen; + float m_InOut; + float m_Grab; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER(m_GrabX); + STATIC_ARRAY_TRANSFER(float, m_DoFArray, s_DoFCount); + + TRANSFER(m_Override); + TRANSFER(m_CloseOpen); + TRANSFER(m_InOut); + TRANSFER(m_Grab); + } + }; + + int32_t MuscleFromBone(int32_t aBoneIndex, int32_t aDoFIndex); + int32_t BoneFromMuscle(int32_t aDoFIndex); + + Hand* CreateHand(memory::Allocator& alloc); + void DestroyHand(Hand *hand, memory::Allocator& alloc); + + void HandSetupAxes(Hand const *hand, skeleton::SkeletonPose const *skeletonPose, skeleton::Skeleton *skeleton, bool aLeft); + void HandCopyAxes(Hand const *srcHand, skeleton::Skeleton const *srcSkeleton, Hand const *hand, skeleton::Skeleton *skeleton); + void HandPoseCopy(HandPose const *handPoseSrc, HandPose *handPoseDst); + + // Retargeting function set + void HandPoseSolve(HandPose const* handPose,HandPose* handPoseOut); + void Hand2SkeletonPose(Hand const *hand, skeleton::Skeleton const *skeleton, HandPose const *handPose, skeleton::SkeletonPose *skeletonPose); + void Skeleton2HandPose(Hand const *hand, skeleton::Skeleton const *skeleton,skeleton::SkeletonPose const *skeletonPose, HandPose *handPose, float offset = 0.0f); + // IK + void FingerLengths(Hand const *hand, float *lengthArray); + void FingerBaseFromPose(Hand const *hand,skeleton::SkeletonPose const *skeletonPose,math::float4 *positionArray); + void FingerTipsFromPose(Hand const *hand,skeleton::Skeleton const *skeleton, skeleton::SkeletonPose const *skeletonPose,math::float4 *positionArray); + + void FingersIKSolve(Hand const *hand, skeleton::Skeleton const *skeleton,math::float4 const *positionArray, float *apWeightArray, skeleton::SkeletonPose *skeletonPose, skeleton::SkeletonPose *skeletonPoseWorkspace); + + mecanim::skeleton::SetupAxesInfo const& GetAxeInfo(uint32_t index); + +}// namespace hand + +} diff --git a/Runtime/mecanim/human/handle.h b/Runtime/mecanim/human/handle.h new file mode 100644 index 0000000..af1df50 --- /dev/null +++ b/Runtime/mecanim/human/handle.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Runtime/mecanim/defs.h" +#include "Runtime/mecanim/memory.h" +#include "Runtime/mecanim/types.h" +#include "Runtime/Math/Simd/xform.h" + +#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h" + +namespace mecanim +{ + +namespace human +{ + struct Handle + { + DEFINE_GET_TYPESTRING(Handle) + + Handle(): + m_X(math::xformIdentity()), + m_ParentHumanIndex(numeric_limits<uint32_t>::max_value), + m_ID(numeric_limits<uint32_t>::max_value) + { + } + + math::xform m_X; // Local tranform + uint32_t m_ParentHumanIndex; // Related parent's human bone index + uint32_t m_ID; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER(m_X); + TRANSFER(m_ParentHumanIndex); + TRANSFER(m_ID); + } + }; +} + +} diff --git a/Runtime/mecanim/human/human.cpp b/Runtime/mecanim/human/human.cpp new file mode 100644 index 0000000..4e2f8bf --- /dev/null +++ b/Runtime/mecanim/human/human.cpp @@ -0,0 +1,2405 @@ +#include "UnityPrefix.h" +#include "Runtime/mecanim/skeleton/skeleton.h" +#include "Runtime/mecanim/human/human.h" + +namespace mecanim +{ + +// anonymous namespace to hide data in local file scope +namespace +{ + using namespace human; + + static const int32_t Bone2DoF[kLastBone][3] = + { + { -1, -1, -1 }, // kHips + { kLeftLegDoFStart+kUpperLegFrontBack, kLeftLegDoFStart+kUpperLegInOut, kLeftLegDoFStart+kUpperLegRollInOut }, // kLeftUpperLeg + { kRightLegDoFStart+kUpperLegFrontBack, kRightLegDoFStart+kUpperLegInOut, kRightLegDoFStart+kUpperLegRollInOut }, // kRightUpperLeg + { kLeftLegDoFStart+kLegCloseOpen, -1, kLeftLegDoFStart+kLegRollInOut }, // kLeftLeg + { kRightLegDoFStart+kLegCloseOpen, -1, kRightLegDoFStart+kLegRollInOut }, // kRightLeg + { kLeftLegDoFStart+kFootCloseOpen, kLeftLegDoFStart+kFootInOut, -1 }, // kLeftFoot + { kRightLegDoFStart+kFootCloseOpen, kRightLegDoFStart+kFootInOut, -1 }, // kRightFoot + { kBodyDoFStart+kSpineFrontBack, kBodyDoFStart+kSpineLeftRight, kBodyDoFStart+kSpineRollLeftRight }, // kSpine + { kBodyDoFStart+kChestFrontBack, kBodyDoFStart+kChestLeftRight, kBodyDoFStart+kChestRollLeftRight }, // kChest + { kHeadDoFStart+kNeckFrontBack, kHeadDoFStart+kNeckLeftRight, kHeadDoFStart+kNeckRollLeftRight }, // kNeck + { kHeadDoFStart+kHeadFrontBack, kHeadDoFStart+kHeadLeftRight, kHeadDoFStart+kHeadRollLeftRight }, // kHead + { kLeftArmDoFStart+kShoulderDownUp, kLeftArmDoFStart+kShoulderFrontBack, -1 }, // kLeftShoulder + { kRightArmDoFStart+kShoulderDownUp, kRightArmDoFStart+kShoulderFrontBack, -1 }, // kRightShoulder + { kLeftArmDoFStart+kArmDownUp, kLeftArmDoFStart+kArmFrontBack, kLeftArmDoFStart+kArmRollInOut }, // kLeftArm + { kRightArmDoFStart+kArmDownUp, kRightArmDoFStart+kArmFrontBack, kRightArmDoFStart+kArmRollInOut }, // kRightArm + { kLeftArmDoFStart+kForeArmCloseOpen, -1, kLeftArmDoFStart+kForeArmRollInOut }, // kLeftForeArm + { kRightArmDoFStart+kForeArmCloseOpen, -1, kRightArmDoFStart+kForeArmRollInOut }, // kRightForeArm + { kLeftArmDoFStart+kHandDownUp,kLeftArmDoFStart+kHandInOut, -1 }, // kLeftHand + { kRightArmDoFStart+kHandDownUp,kRightArmDoFStart+kHandInOut, -1 }, // kRightHand + { kLeftLegDoFStart+kToesUpDown, -1, -1}, // kLeftToes + { kRightLegDoFStart+kToesUpDown, -1, -1 }, // kRightToes + { kHeadDoFStart+kLeftEyeDownUp, kHeadDoFStart+kLeftEyeLeftRight,-1 }, // LeftEye + { kHeadDoFStart+kRightEyeDownUp, kHeadDoFStart+kRightEyeLeftRight,-1 }, // RightEye + { kHeadDoFStart+kJawDownUp, kHeadDoFStart+kJawLeftRight,-1 } // Jaw + }; + + static const float HumanBoneDefaultMass[kLastBone] = + { + 12.0f, // kHips + 10.0f, // kLeftUpperLeg + 10.0f, // kRightUpperLeg + 4.0f, // kLeftLowerLeg + 4.0f, // kRightLowerLeg + 0.8f, // kLeftFoot + 0.8f, // kRightFoot + 2.5f, // kSpine + 24.0f, // kChest + 1.0f, // kNeck + 4.0f, // kHead + 0.5f, // kLeftShoulder + 0.5f, // kRightShoulder + 2.0f, // kLeftUpperArm + 2.0f, // kRightUpperArm + 1.5f, // kLeftLowerArm + 1.5f, // kRightLowerArm + 0.5f, // kLeftHand + 0.5f, // kRightHand + 0.2f, // kLeftToes + 0.2f, // kRightToes + 0.0f, // LeftEye + 0.0f, // RightEye + 0.0f // Jaw + }; + + static const int32_t BoneMirror[kLastBone] = + { + kHips, // kHips + kRightUpperLeg, // kLeftUpperLeg + -kLeftUpperLeg, // kRightUpperLeg + kRightLowerLeg, // kLeftLowerLeg + -kLeftLowerLeg, // kRightLowerLeg + kRightFoot, // kLeftFoot + -kLeftFoot, // kRightFoot + kSpine, // kSpine + kChest, // kChest + kNeck, // kNeck + kHead, // kHead + kRightShoulder, // kLeftShoulder + -kLeftShoulder, // kRightShoulder + kRightUpperArm, // kLeftUpperArm + -kLeftUpperArm, // kRightUpperArm + kRightLowerArm, // kLeftLowerArm + -kLeftLowerArm, // kRightLowerArm + kRightHand, // kLeftHand + -kLeftHand, // kRightHand + kRightToes, // kLeftToes + -kLeftToes, // kRightToes + kRightEye, // kLeftEye + -kLeftEye, // kRightEye + kJaw, // kJaw + }; + + static const float BodyDoFMirror[kLastBodyDoF] = + { + +1.0f, // kSpineFrontBack = 0, + -1.0f, // kSpineLeftRight, + -1.0f, // kSpineRollLeftRight, + +1.0f, // kChestFrontBack, + -1.0f, // kChestLeftRight, + -1.0f // kChestRollLeftRight, + }; + + static const float HeadDoFMirror[kLastHeadDoF] = + { + +1.0f, // kNeckFrontBack = 0, + -1.0f, // kNeckLeftRight, + -1.0f, // kNeckRollLeftRight, + +1.0f, // kHeadFrontBack, + -1.0f, // kHeadLeftRight, + -1.0f, // kHeadRollLeftRight, + +1.0f, // kLeftEyeDownUp, + -1.0f, // kLeftEyeLeftRight, + +1.0f, // kRightEyeDownUp, + -1.0f, // kRightEyeLeftRight, + +1.0f, // kJawDownUp, + -1.0f // kJawLeftRight, + }; + + static const int32_t BoneChildren[kLastBone][4] = + { + { 3,kLeftUpperLeg, kRightUpperLeg, kSpine },// kHips + { 1,kLeftLowerLeg }, // kLeftUpperLeg + { 1,kRightLowerLeg }, // kRightUpperLeg + { 1,kLeftFoot }, // kLeftLowerLeg + { 1,kRightFoot }, // kRightLowerLeg + { 1,kLeftToes }, // kLeftFoot + { 1,kRightToes }, // kRightFoot + { 1,kChest }, // kSpine + { 3,kNeck, kLeftShoulder, kRightShoulder }, // kChest + { 1,kHead }, // kNeck + { 3,kLeftEye,kRightEye,kJaw }, // kHead + { 1,kLeftUpperArm }, // kLeftShoulder + { 1,kRightUpperArm }, // kRightShoulder + { 1,kLeftLowerArm }, // kLeftUpperArm + { 1,kRightLowerArm }, // kRightUpperArm + { 1,kLeftHand }, // kLeftLowerArm + { 1,kRightHand }, // kRightLowerArm + { 0 }, // kLeftHand + { 0 }, // kRightHand + { 0 }, // kLeftToes + { 0 }, // kRightToes + { 0 }, // kLeftEye + { 0 }, // kRightEye + { 0 } // kJaw + }; + + static const int32_t DoF2Bone[human::kLastDoF] = { + kSpine, + kSpine, + kSpine, + kChest, + kChest, + kChest, + kNeck, + kNeck, + kNeck, + kHead, + kHead, + kHead, + kLeftEye, + kLeftEye, + kRightEye, + kRightEye, + kJaw, + kJaw, + kLeftUpperLeg, + kLeftUpperLeg, + kLeftUpperLeg, + kLeftLowerLeg, + kLeftLowerLeg, + kLeftFoot, + kLeftFoot, + kLeftToes, + kRightUpperLeg, + kRightUpperLeg, + kRightUpperLeg, + kRightLowerLeg, + kRightLowerLeg, + kRightFoot, + kRightFoot, + kRightToes, + kLeftShoulder, + kLeftShoulder, + kLeftUpperArm, + kLeftUpperArm, + kLeftUpperArm, + kLeftLowerArm, + kLeftLowerArm, + kLeftHand, + kLeftHand, + kRightShoulder, + kRightShoulder, + kRightUpperArm, + kRightUpperArm, + kRightUpperArm, + kRightLowerArm, + kRightLowerArm, + kRightHand, + kRightHand + }; + + static const int32_t DoF2BoneDoFIndex[human::kLastDoF] = { + 2, // kSpine, + 1, // kSpine, + 0, // kSpine, + 2, // kChest, + 1, // kChest, + 0, // kChest, + 2, // kNeck, + 1, // kNeck, + 0, // kNeck, + 2, // kHead, + 1, // kHead, + 0, // kHead, + 2, // kLeftEye, + 1, // kLeftEye, + 2, // kRightEye, + 1, // kRightEye, + 2, // kJaw, + 1, // kJaw, + 2, // kLeftUpperLeg, + 1, // kLeftUpperLeg, + 0, // kLeftUpperLeg, + 2, // kLeftLowerLeg, + 0, // kLeftLowerLeg, + 2, // kLeftFoot, + 1, // kLeftFoot, + 2, // kLeftToes, + 2, // kRightUpperLeg, + 1, // kRightUpperLeg, + 0, // kRightUpperLeg, + 2, // kRightLowerLeg, + 0, // kRightLowerLeg, + 2, // kRightFoot, + 1, // kRightFoot, + 2, // kRightToes, + 2, // kLeftShoulder, + 1, // kLeftShoulder, + 2, // kLeftUpperArm, + 1, // kLeftUpperArm, + 0, // kLeftUpperArm, + 2, // kLeftLowerArm, + 0, // kLeftLowerArm, + 2, // kLeftHand, + 1, // kLeftHand, + 2, // kRightShoulder, + 1, // kRightShoulder, + 2, // kRightUpperArm, + 1, // kRightUpperArm, + 0, // kRightUpperArm, + 2, // kRightLowerArm, + 0, // kRightLowerArm, + 2, // kRightHand, + 1, // kRightHand + }; + + const static float ATTRIBUTE_ALIGN(ALIGN4F) goalOrientationOffsetArray[kLastGoal][4] = {{0.5f,-0.5f,0.5f,0.5f},{0.5f,-0.5f,0.5f,0.5f},{0.707107f,0,0.707107f,0},{0,0.707107f,0,0.707107f}}; +} + +namespace human +{ + bool RequiredBone(uint32_t aBoneIndex) + { + static bool requiredBone[kLastBone] = { + true, //kHips + true, //kLeftUpperLeg + true, //kRightUpperLeg + true, //kLeftLowerLeg + true, //kRightLowerLeg + true, //kLeftFoot + true, //kRightFoot + true, //kSpine + false, //kChest + false, //kNeck + true, //kHead + false, //kLeftShoulder + false, //kRightShoulder + true, //kLeftUpperArm + true, //kRightUpperArm + true, //kLeftLowerArm + true, //kRightLowerArm + true, //kLeftHand + true, //kRightHand + false, //kLeftToes + false, //kRightToes + false, //kLeftEye, + false, //kRightEye, + false //kJaw, + }; + + return requiredBone[aBoneIndex]; + } + + const char* BoneName(uint32_t aBoneIndex) + { + static const char* boneName[kLastBone] = { + "Hips", + "LeftUpperLeg", + "RightUpperLeg", + "LeftLowerLeg", + "RightLowerLeg", + "LeftFoot", + "RightFoot", + "Spine", + "Chest", + "Neck", + "Head", + "LeftShoulder", + "RightShoulder", + "LeftUpperArm", + "RightUpperArm", + "LeftLowerArm", + "RightLowerArm", + "LeftHand", + "RightHand", + "LeftToes", + "RightToes", + "LeftEye", + "RightEye", + "Jaw" + }; + + return boneName[aBoneIndex]; + } + + const char* MuscleName(uint32_t aBoneIndex) + { + static const char* muscleName[human::kLastDoF] = { + + "Spine Front-Back", + "Spine Left-Right", + "Spine Twist Left-Right", + "Chest Front-Back", + "Chest Left-Right", + "Chest Twist Left-Right", + + "Neck Nod Down-Up", + "Neck Tilt Left-Right", + "Neck Turn Left-Right", + "Head Nod Down-Up", + "Head Tilt Left-Right", + "Head Turn Left-Right", + + "Left Eye Down-Up", + "Left Eye In-Out", + "Right Eye Down-Up", + "Right Eye In-Out", + + "Jaw Close", + "Jaw Left-Right", + + "Left Upper Leg Front-Back", + "Left Upper Leg In-Out", + "Left Upper Leg Twist In-Out", + "Left Lower Leg Stretch", + "Left Lower Leg Twist In-Out", + "Left Foot Up-Down", + "Left Foot Twist In-Out", + "Left Toes Up-Down", + + "Right Upper Leg Front-Back", + "Right Upper Leg In-Out", + "Right Upper Leg Twist In-Out", + "Right Lower Leg Stretch", + "Right Lower Leg Twist In-Out", + "Right Foot Up-Down", + "Right Foot Twist In-Out", + "Right Toes Up-Down", + + "Left Shoulder Down-Up", + "Left Shoulder Front-Back", + "Left Arm Down-Up", + "Left Arm Front-Back", + "Left Arm Twist In-Out", + "Left Forearm Stretch", + "Left Forearm Twist In-Out", + "Left Hand Down-Up", + "Left Hand In-Out", + + "Right Shoulder Down-Up", + "Right Shoulder Front-Back", + "Right Arm Down-Up", + "Right Arm Front-Back", + "Right Arm Twist In-Out", + "Right Forearm Stretch", + "Right Forearm Twist In-Out", + "Right Hand Down-Up", + "Right Hand In-Out" + }; + + return muscleName[aBoneIndex]; + } + + bool MaskHasLegs(const HumanPoseMask& mask) + { + for(int dofIter = 0; dofIter < mecanim::human::kLastLegDoF; dofIter++) + { + if(!mask.test(mecanim::human::kMaskDoFStartIndex+mecanim::human::kLeftLegDoFStart+dofIter)) + return false; + if(!mask.test(mecanim::human::kMaskDoFStartIndex+mecanim::human::kRightLegDoFStart+dofIter)) + return false; + } + + return true; + } + + int32_t MuscleFromBone(int32_t aBoneIndex, int32_t aDoFIndex) + { + return Bone2DoF[aBoneIndex][2-aDoFIndex]; + } + + int32_t BoneFromMuscle(int32_t aDoFIndex) + { + return DoF2Bone[aDoFIndex]; + } + + HumanPoseMask FullBodyMask() + { + return HumanPoseMask(~HumanPoseMask::type(0)); + } + + skeleton::SetupAxesInfo const& GetAxeInfo(uint32_t index) + { + const static skeleton::SetupAxesInfo setupAxesInfoArray[kLastBone] = + { + {{0,0,0,1},{-1,0,0,0},{-40,-40,-40},{40,40,40},{1,1,1,1},math::kZYRoll,0}, // kHips, + {{-0.268f,0,0,1},{1,0,0,0},{-60,-60,-90},{60,60,50},{1,1,1,1},math::kZYRoll,0}, // kLeftUpperLeg, + {{-0.268f,0,0,1},{1,0,0,0},{-60,-60,-90},{60,60,50},{-1,-1,1,1},math::kZYRoll,0}, // kRightUpperLeg, + {{0.839f,0,0,1},{1,0,0,0},{-90,0,-80},{90,0,80},{1,1,-1,1},math::kZYRoll,0}, // kLeftLeg, + {{0.839f,0,0,1},{1,0,0,0},{-90,0,-80},{90,0,80},{-1,1,-1,1},math::kZYRoll,0}, // kRightLeg, + {{0,0,0,1},{1,0,0,0},{0,-30,-50},{0,30,50},{1,1,1,1},math::kZYRoll,-2}, // kLeftFoot, + {{0,0,0,1},{1,0,0,0},{0,-30,-50},{0,30,50},{1,-1,1,1},math::kZYRoll,-2}, // kRightFoot, + {{0,0,0,1},{-1,0,0,0},{-40,-40,-40},{40,40,40},{1,1,1,1},math::kZYRoll,0}, // kSpine, + {{0,0,0,1},{-1,0,0,0},{-40,-40,-40},{40,40,40},{1,1,1,1},math::kZYRoll,0}, // kChest, + {{0,0,0,1},{-1,0,0,0},{-40,-40,-40},{40,40,40},{1,1,1,1},math::kZYRoll,0}, // kNeck, + {{0,0,0,1},{-1,0,0,0},{-40,-40,-40},{40,40,40},{1,1,1,1},math::kZYRoll,2}, // kHead, + {{0,0,0,1},{0,0,1,0},{0,-15,-15},{0,15,30},{1,1,-1,1},math::kZYRoll,0}, // kLeftShoulder, + {{0,0,0,1},{0,0,1,0},{0,-15,-15},{0,15,30},{1,1,1,1},math::kZYRoll,0}, // kRightShoulder, + {{0,0.268f,0.364f,1},{0,0,1,0},{-90,-100,-60},{90,100,100},{1,1,-1,1},math::kZYRoll,0}, // kLeftArm, + {{0,-0.268f,-0.364f,1},{0,0,1,0},{-90,-100,-60},{90,100,100},{-1,1,1,1},math::kZYRoll,0}, // kRightArm, + {{0,0.839f,0,1},{0,1,0,0},{-90,0,-80},{90,0,80},{1,1,-1,1},math::kZYRoll,0}, // kLeftForeArm, + {{0,-0.839f,0,1},{0,1,0,0},{-90,0,-80},{90,0,80},{-1,1,1,1},math::kZYRoll,0}, // kRightForeArm, + {{0,0,0,1},{0,0,1,0},{0,-40,-80},{0,40,80},{1,1,-1,1},math::kZYRoll,0}, // kLeftHand, + {{0,0,0,1},{0,0,1,0},{0,-40,-80},{0,40,80},{1,1,1,1},math::kZYRoll,0}, // kRightHand, + {{0,0,0,1},{1,0,0,0},{0,0,-50},{0,0,50},{1,1,1,1},math::kZYRoll,3}, // kLeftToes, + {{0,0,0,1},{1,0,0,0},{0,0,-50},{0,0,50},{1,1,1,1},math::kZYRoll,3}, // kRightToes, + {{0,0,0,1},{1,0,0,0},{0,-20,-10},{0,20,15},{1,1,-1,1},math::kZYRoll,3}, // kLeftEye, + {{0,0,0,1},{1,0,0,0},{0,-20,-10},{0,20,15},{1,-1,-1,1},math::kZYRoll,3}, // kRightEye, + {{0.09f,0,0,1},{1,0,0,0},{0,-10,-10},{0,10,10},{1,1,-1,1},math::kZYRoll,3} // kJaw, + }; + + return setupAxesInfoArray[index]; + + } + + + Human::Human() : m_HandlesCount(0), + m_HasLeftHand(false), + m_HasRightHand(false), + m_ColliderCount(0), + m_Scale(1), + m_RootX(math::xformIdentity()), + m_ArmTwist(0.5f), + m_ForeArmTwist(0.5f), + m_UpperLegTwist(0.5f), + m_LegTwist(0.5f), + m_ArmStretch(0.05f), + m_LegStretch(0.05f), + m_FeetSpacing(0.0f) + { + int32_t i; + + float mass = 0; + + for(i = 0; i < kLastBone; i++) + { + m_HumanBoneIndex[i] = -1; + m_HumanBoneMass[i] = HumanBoneDefaultMass[i]; + mass += m_HumanBoneMass[i]; + m_ColliderIndex[i] = -1; + } + + for(i = 0; i < kLastBone; i++) + { + m_HumanBoneMass[i] /= mass; + } + } + + Human* CreateHuman(skeleton::Skeleton *apSkeleton, skeleton::SkeletonPose *apSkeletonPose, uint32_t aHandlesCount, uint32_t aColliderCount, memory::Allocator& arAlloc) + { + Human* human = arAlloc.Construct<Human>(); + + human->m_Skeleton = apSkeleton; + human->m_SkeletonPose = apSkeletonPose; + human->m_Handles = arAlloc.ConstructArray<Handle>(aHandlesCount); + human->m_HandlesCount = aHandlesCount; + human->m_ColliderArray = arAlloc.ConstructArray<math::Collider>(aColliderCount); + human->m_ColliderCount = aColliderCount; + + memset(human->m_HumanBoneIndex, -1, sizeof(int32_t)*kLastBone); + memset(human->m_ColliderIndex, -1, sizeof(int32_t)*kLastBone); + + human->m_HasLeftHand = false; + human->m_HasRightHand = false; + + human->m_Scale = 1; + + return human; + } + + void DestroyHuman(Human *apHuman, memory::Allocator& arAlloc) + { + if(apHuman) + { + arAlloc.Deallocate(apHuman->m_Handles); + arAlloc.Deallocate(apHuman->m_ColliderArray); + + arAlloc.Deallocate(apHuman); + } + } + + HumanPose::HumanPose() + { + int32_t i; + + for(i = 0; i < kLastDoF; i++) + { + m_DoFArray[i] = 0; + } + + m_LookAtPosition = math::float4::zero(); + m_LookAtWeight = math::float4::zero(); + } + + void HumanAdjustMass(Human *apHuman) + { + if(apHuman->m_HumanBoneIndex[kNeck] < 0) + { + apHuman->m_HumanBoneMass[kChest] += apHuman->m_HumanBoneMass[kNeck]; + apHuman->m_HumanBoneMass[kNeck] = 0; + } + + if(apHuman->m_HumanBoneIndex[kLeftShoulder] < 0) + { + apHuman->m_HumanBoneMass[kChest] += apHuman->m_HumanBoneMass[kLeftShoulder]; + apHuman->m_HumanBoneMass[kLeftShoulder] = 0; + } + + if(apHuman->m_HumanBoneIndex[kRightShoulder] < 0) + { + apHuman->m_HumanBoneMass[kChest] += apHuman->m_HumanBoneMass[kRightShoulder]; + apHuman->m_HumanBoneMass[kRightShoulder] = 0; + } + + if(apHuman->m_HumanBoneIndex[kChest] < 0) + { + apHuman->m_HumanBoneMass[kSpine] += apHuman->m_HumanBoneMass[kChest]; + apHuman->m_HumanBoneMass[kChest] = 0; + } + + if(apHuman->m_HumanBoneIndex[kLeftToes] < 0) + { + apHuman->m_HumanBoneMass[kLeftFoot] += apHuman->m_HumanBoneMass[kLeftToes]; + apHuman->m_HumanBoneMass[kLeftToes] = 0; + } + + if(apHuman->m_HumanBoneIndex[kRightToes] < 0) + { + apHuman->m_HumanBoneMass[kRightFoot] += apHuman->m_HumanBoneMass[kRightToes]; + apHuman->m_HumanBoneMass[kRightToes] = 0; + } + } + + void HumanSetupAxes(Human *apHuman, skeleton::SkeletonPose const *apSkeletonPoseGlobal) + { + apHuman->m_RootX = math::xformIdentity(); + apHuman->m_RootX = HumanComputeRootXform(apHuman,apSkeletonPoseGlobal); + apHuman->m_Scale = apHuman->m_RootX.t.y().tofloat(); + + skeleton::SkeletonPoseComputeLocal(apHuman->m_Skeleton.Get(), apSkeletonPoseGlobal, apHuman->m_SkeletonPose.Get()); + + int32_t i; + + for(i = 0; i < kLastBone; i++) + { + int32_t skBoneIndex = apHuman->m_HumanBoneIndex[i]; + + int32_t skAxisBoneId = -1; + float len = 1.0f; + + switch(i) + { + case kLeftEye: + case kRightEye: + case kJaw: + len = 0.1f; + break; + + case kHead: + if(apHuman->m_HumanBoneIndex[kNeck] >= 0) + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kNeck]; + len = -1.0f; + } + else if(apHuman->m_HumanBoneIndex[kChest] >= 0) + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kChest]; + len = -0.5f; + } + else + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kSpine]; + len = -0.25f; + } + break; + + case kLeftFoot: + len = -apSkeletonPoseGlobal->m_X[skBoneIndex].t.y().tofloat(); + break; + + case kRightFoot: + len = -apSkeletonPoseGlobal->m_X[skBoneIndex].t.y().tofloat(); + break; + + case kLeftHand: + skAxisBoneId = apHuman->m_HumanBoneIndex[kLeftLowerArm]; + len = -0.5f; + break; + + case kRightHand: + skAxisBoneId = apHuman->m_HumanBoneIndex[kRightLowerArm]; + len = -0.5f; + break; + + case kLeftToes: + skAxisBoneId = apHuman->m_HumanBoneIndex[kLeftFoot]; + len = 0.5f; + break; + + case kRightToes: + skAxisBoneId = apHuman->m_HumanBoneIndex[kRightFoot]; + len = 0.5f; + break; + + case kHips: + skAxisBoneId = apHuman->m_HumanBoneIndex[kSpine]; + break; + + case kLeftUpperLeg: + skAxisBoneId = apHuman->m_HumanBoneIndex[kLeftLowerLeg]; + break; + + case kRightUpperLeg: + skAxisBoneId = apHuman->m_HumanBoneIndex[kRightLowerLeg]; + break; + + case kLeftLowerLeg: + skAxisBoneId = apHuman->m_HumanBoneIndex[kLeftFoot]; + break; + + case kRightLowerLeg: + skAxisBoneId = apHuman->m_HumanBoneIndex[kRightFoot]; + break; + + case kSpine: + if(apHuman->m_HumanBoneIndex[kChest] >= 0) + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kChest]; + } + else if(apHuman->m_HumanBoneIndex[kNeck] >= 0) + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kNeck]; + } + else + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kHead]; + } + break; + + case kChest: + if(apHuman->m_HumanBoneIndex[kNeck] >= 0) + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kNeck]; + } + else + { + skAxisBoneId = apHuman->m_HumanBoneIndex[kHead]; + } + break; + + case kNeck: + skAxisBoneId = apHuman->m_HumanBoneIndex[kHead]; + break; + + case kLeftShoulder: + skAxisBoneId = apHuman->m_HumanBoneIndex[kLeftUpperArm]; + break; + + case kRightShoulder: + skAxisBoneId = apHuman->m_HumanBoneIndex[kRightUpperArm]; + break; + + case kLeftUpperArm: + skAxisBoneId = apHuman->m_HumanBoneIndex[kLeftLowerArm]; + break; + + case kRightUpperArm: + skAxisBoneId = apHuman->m_HumanBoneIndex[kRightLowerArm]; + break; + + case kLeftLowerArm: + skAxisBoneId = apHuman->m_HumanBoneIndex[kLeftHand]; + break; + + case kRightLowerArm: + skAxisBoneId = apHuman->m_HumanBoneIndex[kRightHand]; + break; + }; + + if(skBoneIndex >= 0) + { + skeleton::SetupAxes(apHuman->m_Skeleton.Get(), apSkeletonPoseGlobal, GetAxeInfo(i), skBoneIndex,skAxisBoneId,true,len); + } + } + } + + void HumanSetupCollider(Human *apHuman, skeleton::SkeletonPose const *apSkeletonPoseGlobal) + { + //float refLen = apSkeletonPoseGlobal->m_X[apHuman->m_HumanBoneIndex[kHead]].t.y(); + + float hipsWidth = math::length(apSkeletonPoseGlobal->m_X[apHuman->m_HumanBoneIndex[kLeftUpperLeg]].t - apSkeletonPoseGlobal->m_X[apHuman->m_HumanBoneIndex[kRightUpperLeg]].t).tofloat(); + float shouldersWidth = math::length(apSkeletonPoseGlobal->m_X[apHuman->m_HumanBoneIndex[kLeftUpperArm]].t - apSkeletonPoseGlobal->m_X[apHuman->m_HumanBoneIndex[kRightUpperArm]].t).tofloat(); + + int32_t colliderIndex = 0; + int32_t boneIndex; + + for(boneIndex = 0; boneIndex < kLastBone; boneIndex++) + { + int32_t skIndex = apHuman->m_HumanBoneIndex[boneIndex]; + + if(skIndex >= 0) + { + apHuman->m_ColliderIndex[boneIndex] = colliderIndex; + + math::Axes axes = GetAxes(apHuman,boneIndex); + apHuman->m_ColliderArray[colliderIndex].m_X.s.x() = axes.m_Length; + apHuman->m_ColliderArray[colliderIndex].m_X.t.x() = math::float1(0.5f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + + if(boneIndex == kHips) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kCube; + //apHuman->m_ColliderArray[colliderIndex].m_X.s.x() *= math::float1(3.0f); + apHuman->m_ColliderArray[colliderIndex].m_X.t.x() = math::float1::zero(); + + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(1.5f * hipsWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(1.0f * hipsWidth); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kIgnored; + } + else if(boneIndex == kSpine) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kSphere; + + //apHuman->m_ColliderArray[colliderIndex].m_X.s.x() *= math::float1(1.5f); + apHuman->m_ColliderArray[colliderIndex].m_X.t.x() = math::float1(0.5f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(1.2f * hipsWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.8f * hipsWidth); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -7.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 7.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 7.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 7.0f; + } + else if(boneIndex == kChest) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kCube; + + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(1.0f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.6f * shouldersWidth); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -11.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 11.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 11.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 11.0f; + } + else if(boneIndex == kNeck) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kSphere; + + //apHuman->m_ColliderArray[colliderIndex].m_X.s.x() *= math::float1(1.5f); + apHuman->m_ColliderArray[colliderIndex].m_X.t.y() = math::float1(0.1f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.33f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.33f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -10.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 10.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 20.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 5.0f; + } + else if(boneIndex == kHead) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kSphere; + + apHuman->m_ColliderArray[colliderIndex].m_X.s.x() = math::float1(0.6f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.t.y() = math::float1(0.2f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.4f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.45f * shouldersWidth); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -5.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 8.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 20.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 10.0f; + } + else if(boneIndex == kLeftShoulder || boneIndex == kRightShoulder) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kNone; + + //apHuman->m_ColliderArray[colliderIndex].m_X.s.x() *= math::float1(1.2f); + apHuman->m_ColliderArray[colliderIndex].m_X.t.x() = math::float1(0.5f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.1f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.2f * shouldersWidth); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kIgnored; + } + else if(boneIndex == kLeftHand || boneIndex == kRightHand) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kCube; + + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.5f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.2f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -30.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 30.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 40.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 25.0f; + } + else if(boneIndex == kLeftFoot || boneIndex == kRightFoot) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kCube; + + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.4f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.85f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.t.y() = math::float1(-0.25f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.y(); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -45.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 20.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 30.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 50.0f; + } + else if(boneIndex == kLeftToes || boneIndex == kRightToes) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kNone; + + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.4f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.2f * shouldersWidth); + apHuman->m_ColliderArray[colliderIndex].m_X.t.y() = math::float1(-0.5f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.y(); + + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kIgnored; + } + else if( boneIndex == kLeftUpperArm || + boneIndex == kLeftLowerArm || + boneIndex == kRightUpperArm || + boneIndex == kRightLowerArm) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kCapsule; + + //apHuman->m_ColliderArray[colliderIndex].m_X.s.x() *= math::float1(1.2f); + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.25f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.25f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + + if(boneIndex == kLeftUpperArm || boneIndex == kRightUpperArm) + { + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -100.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 100.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 20.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 45.0f; + } + else if (boneIndex == kLeftLowerArm || boneIndex == kRightLowerArm) + { + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLocked; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + if (boneIndex == kLeftLowerArm) + { + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -130.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 0.0f; + } + else if (boneIndex == kRightLowerArm) + { + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = 0.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 130.0f; + } + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 5.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 20.0f; + } + } + else if( boneIndex == kLeftLowerLeg || + boneIndex == kLeftUpperLeg || + boneIndex == kRightLowerLeg || + boneIndex == kRightUpperLeg) + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kCapsule; + + //apHuman->m_ColliderArray[colliderIndex].m_X.s.x() *= math::float1(1.2f); + apHuman->m_ColliderArray[colliderIndex].m_X.s.z() = math::float1(0.175f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + apHuman->m_ColliderArray[colliderIndex].m_X.s.y() = math::float1(0.175f) * apHuman->m_ColliderArray[colliderIndex].m_X.s.x(); + + if (boneIndex == kLeftLowerLeg || boneIndex == kRightLowerLeg) + { + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLocked; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = 0.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 130.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 0.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 10.0f; + } + else if(boneIndex == kLeftUpperLeg || boneIndex == kRightUpperLeg) + { + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kLimited; + apHuman->m_ColliderArray[colliderIndex].m_MinLimitX = -70.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitX = 10.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitY = 45.0f; + apHuman->m_ColliderArray[colliderIndex].m_MaxLimitZ = 60.0f; + } + } + else + { + apHuman->m_ColliderArray[colliderIndex].m_Type = math::kNone; + apHuman->m_ColliderArray[colliderIndex].m_XMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_YMotionType = math::kIgnored; + apHuman->m_ColliderArray[colliderIndex].m_ZMotionType = math::kIgnored; + } + + colliderIndex++; + } + } + } + + void HumanCopyAxes(Human const *apSrcHuman, Human *apHuman) + { + int32_t i; + + for(i = 0; i < kLastBone; i++) + { + skeleton::Node const * srcNode = apSrcHuman->m_HumanBoneIndex[i] >= 0 ? &apSrcHuman->m_Skeleton->m_Node[apSrcHuman->m_HumanBoneIndex[i]] : 0; + skeleton::Node const * node = apHuman->m_HumanBoneIndex[i] >= 0 ? &apHuman->m_Skeleton->m_Node[apHuman->m_HumanBoneIndex[i]] : 0; + + if(srcNode != 0 && node != 0 && srcNode->m_AxesId != -1 && node->m_AxesId != -1) + { + apHuman->m_Skeleton->m_AxesArray[node->m_AxesId] = apSrcHuman->m_Skeleton->m_AxesArray[srcNode->m_AxesId]; + } + } + } + + math::Axes GetAxes(Human const *apHuman, int32_t aBoneIndex) + { + math::Axes ret; + + int32_t skIndex = apHuman->m_HumanBoneIndex[aBoneIndex]; + + if(skIndex >= 0) + { + int32_t axesIndex = apHuman->m_Skeleton->m_Node[skIndex].m_AxesId; + + if(axesIndex >= 0) + { + ret = apHuman->m_Skeleton->m_AxesArray[axesIndex]; + } + } + + return ret; + } + + void GetMuscleRange(Human const *apHuman, int32_t aDoFIndex, float &aMin, float &aMax) + { + math::Axes axes = GetAxes(apHuman,DoF2Bone[aDoFIndex]); + + switch(DoF2BoneDoFIndex[aDoFIndex]) + { + case 0: aMin = axes.m_Limit.m_Min.x().tofloat(); aMax = axes.m_Limit.m_Max.x().tofloat(); break; + case 1: aMin = axes.m_Limit.m_Min.y().tofloat(); aMax = axes.m_Limit.m_Max.y().tofloat(); break; + case 2: aMin = axes.m_Limit.m_Min.z().tofloat(); aMax = axes.m_Limit.m_Max.z().tofloat(); break; + } + } + + math::float4 AddAxis(Human const *apHuman, int32_t aIndex, math::float4 const &arQ) + { + math::Axes cAxes = apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[aIndex].m_AxesId]; + return math::normalize(math::quatMul(arQ,cAxes.m_PostQ)); + } + + math::float4 RemoveAxis(Human const *apHuman, int32_t aIndex, const math::float4 &arQ) + { + math::Axes cAxes = apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[aIndex].m_AxesId]; + return math::normalize(math::quatMul(arQ,math::quatConj(cAxes.m_PostQ))); + } + + math::xform NormalizedHandleX(Human const *apHuman, int32_t aHandleIndex) + { + int32_t pIndex = apHuman->m_HumanBoneIndex[apHuman->m_Handles[aHandleIndex].m_ParentHumanIndex]; + + math::xform px = apHuman->m_SkeletonPose->m_X[pIndex]; + math::xform hx = math::xformMul(px,apHuman->m_Handles[aHandleIndex].m_X); + + px.q = AddAxis(apHuman,pIndex,px.q); + px.s = math::float4::one(); + + return math::xformInvMul(px,hx); + } + + void HumanPoseAdjustForMissingBones(Human const *apHuman, HumanPose *apHumanPose) + { + if(apHuman->m_HumanBoneIndex[kNeck] < 0) + { + apHumanPose->m_DoFArray[kHeadDoFStart+kHeadFrontBack] += apHumanPose->m_DoFArray[kHeadDoFStart+kNeckFrontBack]; + apHumanPose->m_DoFArray[kHeadDoFStart+kNeckFrontBack] = 0; + + apHumanPose->m_DoFArray[kHeadDoFStart+kHeadLeftRight] += apHumanPose->m_DoFArray[kHeadDoFStart+kNeckLeftRight]; + apHumanPose->m_DoFArray[kHeadDoFStart+kNeckLeftRight] = 0; + + apHumanPose->m_DoFArray[kHeadDoFStart+kHeadRollLeftRight] += apHumanPose->m_DoFArray[kHeadDoFStart+kNeckRollLeftRight]; + apHumanPose->m_DoFArray[kHeadDoFStart+kNeckRollLeftRight] = 0; + } + + if(apHuman->m_HumanBoneIndex[kChest] < 0) + { + apHumanPose->m_DoFArray[kBodyDoFStart+kSpineFrontBack] += apHumanPose->m_DoFArray[kBodyDoFStart+kChestFrontBack]; + apHumanPose->m_DoFArray[kBodyDoFStart+kChestFrontBack] = 0; + + apHumanPose->m_DoFArray[kBodyDoFStart+kSpineLeftRight] += apHumanPose->m_DoFArray[kBodyDoFStart+kChestLeftRight]; + apHumanPose->m_DoFArray[kBodyDoFStart+kChestLeftRight] = 0; + + apHumanPose->m_DoFArray[kBodyDoFStart+kSpineRollLeftRight] += apHumanPose->m_DoFArray[kBodyDoFStart+kChestRollLeftRight]; + apHumanPose->m_DoFArray[kBodyDoFStart+kChestRollLeftRight] = 0; + } + + if(apHuman->m_HumanBoneIndex[kLeftShoulder] < 0) + { + apHumanPose->m_DoFArray[kLeftArmDoFStart+kArmDownUp] += (30.0f/200.0f) * apHumanPose->m_DoFArray[kLeftArmDoFStart+kShoulderDownUp]; + apHumanPose->m_DoFArray[kLeftArmDoFStart+kShoulderDownUp] = 0; + + apHumanPose->m_DoFArray[kLeftArmDoFStart+kArmFrontBack] += (45.0f/160.0f) * apHumanPose->m_DoFArray[kLeftArmDoFStart+kShoulderFrontBack]; + apHumanPose->m_DoFArray[kLeftArmDoFStart+kShoulderFrontBack] = 0; + } + + if(apHuman->m_HumanBoneIndex[kRightShoulder] < 0) + { + apHumanPose->m_DoFArray[kRightArmDoFStart+kArmDownUp] += (30.0f/200.0f) * apHumanPose->m_DoFArray[kRightArmDoFStart+kShoulderDownUp]; + apHumanPose->m_DoFArray[kRightArmDoFStart+kShoulderDownUp] = 0; + + apHumanPose->m_DoFArray[kRightArmDoFStart+kArmFrontBack] += (45.0f/160.0f) * apHumanPose->m_DoFArray[kRightArmDoFStart+kShoulderFrontBack]; + apHumanPose->m_DoFArray[kRightArmDoFStart+kShoulderFrontBack] = 0; + } + } + + void Human2SkeletonPose(Human const *apHuman, HumanPose const *apHumanPose, skeleton::SkeletonPose *apSkeletonPose, int32_t i) + { + if(apHuman->m_HumanBoneIndex[i] != -1) + { + math::float4 xyz = math::cond( math::bool4(Bone2DoF[i][2] != -1,Bone2DoF[i][1] != -1,Bone2DoF[i][0] != -1,false), + math::float4(apHumanPose->m_DoFArray[Bone2DoF[i][2]],apHumanPose->m_DoFArray[Bone2DoF[i][1]],apHumanPose->m_DoFArray[Bone2DoF[i][0]],0), + math::float4::zero()); + + skeleton::SkeletonSetDoF(apHuman->m_Skeleton.Get(),apSkeletonPose,xyz,apHuman->m_HumanBoneIndex[i]); + } + } + + void Human2SkeletonPose(Human const *apHuman, HumanPose const *apHumanPose, skeleton::SkeletonPose *apSkeletonPose) + { + int32_t i; + for(i = 1; i < kLastBone; i++) + { + Human2SkeletonPose(apHuman,apHumanPose,apSkeletonPose,i); + } + + if(apHuman->m_HasLeftHand) + { + hand::Hand2SkeletonPose(apHuman->m_LeftHand.Get(),apHuman->m_Skeleton.Get(),&apHumanPose->m_LeftHandPose,apSkeletonPose); + } + + if(apHuman->m_HasRightHand) + { + hand::Hand2SkeletonPose(apHuman->m_RightHand.Get(),apHuman->m_Skeleton.Get(),&apHumanPose->m_RightHandPose,apSkeletonPose); + } + } + + void Skeleton2HumanPose(Human const *apHuman, skeleton::SkeletonPose const *apSkeletonPose, HumanPose *apHumanPose, int32_t i) + { + if(apHuman->m_HumanBoneIndex[i] != -1) + { + const math::float4 xyz = skeleton::SkeletonGetDoF(apHuman->m_Skeleton.Get(),apSkeletonPose,apHuman->m_HumanBoneIndex[i]); + + if(Bone2DoF[i][2] != -1) apHumanPose->m_DoFArray[Bone2DoF[i][2]] = xyz.x().tofloat(); + if(Bone2DoF[i][1] != -1) apHumanPose->m_DoFArray[Bone2DoF[i][1]] = xyz.y().tofloat(); + if(Bone2DoF[i][0] != -1) apHumanPose->m_DoFArray[Bone2DoF[i][0]] = xyz.z().tofloat(); + } + } + + void Skeleton2HumanPose(Human const *apHuman, skeleton::SkeletonPose const *apSkeletonPose, HumanPose *apHumanPose) + { + int32_t i; + + for(i = 1; i < kLastBone; i++) + { + Skeleton2HumanPose(apHuman,apSkeletonPose,apHumanPose,i); + } + + if(apHuman->m_HasLeftHand) + { + hand::Skeleton2HandPose(apHuman->m_LeftHand.Get(),apHuman->m_Skeleton.Get(),apSkeletonPose,&apHumanPose->m_LeftHandPose); + } + + if(apHuman->m_HasRightHand) + { + hand::Skeleton2HandPose(apHuman->m_RightHand.Get(),apHuman->m_Skeleton.Get(),apSkeletonPose,&apHumanPose->m_RightHandPose); + } + } + + math::float4 HumanComputeBoneMassCenter(Human const *apHuman, skeleton::SkeletonPose const *apSkeletonPose,int32_t aBoneIndex) + { + math::float4 ret( math::float4::zero() ); + + switch(aBoneIndex) + { + case kHips: + ret = math::float1(1.0f/3.0f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftUpperLeg]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightUpperLeg]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kSpine]].t); + break; + + case kSpine: + if(apHuman->m_HumanBoneIndex[kChest] >= 0) + { + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kSpine]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kChest]].t); + } + else + { + ret = math::float1(0.1f) * apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kSpine]].t + math::float1(0.9f * 0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftUpperArm]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightUpperArm]].t); + } + break; + + case kChest: + if(apHuman->m_HumanBoneIndex[kNeck] >= 0 && apHuman->m_HumanBoneIndex[kLeftShoulder] >= 0 && apHuman->m_HumanBoneIndex[kRightShoulder] >= 0) + { + ret = math::float1(0.25f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kChest]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kNeck]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftShoulder]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightShoulder]].t); + } + else + { + ret = math::float1(1.0f/3.0f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kChest]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftUpperArm]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightUpperArm]].t); + } + break; + + case kNeck: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kNeck]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kHead]].t); + break; + + case kLeftUpperLeg: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftUpperLeg]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftLowerLeg]].t); + break; + + case kLeftLowerLeg: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftLowerLeg]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftFoot]].t); + break; + + case kLeftShoulder: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftShoulder]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftUpperArm]].t); + break; + + case kLeftUpperArm: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftUpperArm]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftLowerArm]].t); + break; + + case kLeftLowerArm: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftUpperArm]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kLeftHand]].t); + break; + + case kRightUpperLeg: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightUpperLeg]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightLowerLeg]].t); + break; + + case kRightLowerLeg: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightLowerLeg]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightFoot]].t); + break; + + case kRightShoulder: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightShoulder]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightUpperArm]].t); + break; + + case kRightUpperArm: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightUpperArm]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightLowerArm]].t); + break; + + case kRightLowerArm: + ret = math::float1(0.5f) * (apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightLowerArm]].t + apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[kRightHand]].t); + break; + + default: + ret = apSkeletonPose->m_X[apHuman->m_HumanBoneIndex[aBoneIndex]].t; + break; + }; + + return ret; + } + + math::float4 HumanComputeMassCenter(Human const *apHuman, skeleton::SkeletonPose const *apSkeletonPoseGlobal) + { + math::float4 ret(math::float4::zero()); + + int32_t i; + + float mass = 0; + + for(i = 0; i < kLastBone; i++) + { + int32_t index = apHuman->m_HumanBoneIndex[i]; + + if(index >=0) + { + float boneMass = apHuman->m_HumanBoneMass[i]; + ret += HumanComputeBoneMassCenter(apHuman,apSkeletonPoseGlobal,i) * math::float1(boneMass); + mass += boneMass; + } + } + + return ret / math::float1(mass); + } + + float HumanComputeMomentumOfInertia(Human const *apHuman, skeleton::SkeletonPose const *apSkeletonPoseGlobal) + { + float ret = 0; + + math::float4 mc = HumanComputeMassCenter(apHuman,apSkeletonPoseGlobal); + + int32_t i; + + for(i = 0; i < kLastBone; i++) + { + int32_t index = apHuman->m_HumanBoneIndex[i]; + + if(index >= 0) + { + float r = math::length(HumanComputeBoneMassCenter(apHuman,apSkeletonPoseGlobal,index) - mc).tofloat(); + ret += apHuman->m_HumanBoneMass[i] * r * r; + } + } + + return ret; + + } + + math::float4 HumanComputeOrientation(Human const* apHuman,skeleton::SkeletonPose const* apPoseGlobal) + { + int32_t llIndex = apHuman->m_HumanBoneIndex[kLeftUpperLeg]; + int32_t rlIndex = apHuman->m_HumanBoneIndex[kRightUpperLeg]; + + int32_t laIndex = apHuman->m_HumanBoneIndex[kLeftUpperArm]; + int32_t raIndex = apHuman->m_HumanBoneIndex[kRightUpperArm]; + + math::float4 legMC = math::float1(0.5f) * (apPoseGlobal->m_X[llIndex].t + apPoseGlobal->m_X[rlIndex].t); + math::float4 armMC = math::float1(0.5f) * (apPoseGlobal->m_X[laIndex].t + apPoseGlobal->m_X[raIndex].t); + + math::float4 upV = math::normalize(armMC-legMC); + + math::float4 legV = apPoseGlobal->m_X[rlIndex].t - apPoseGlobal->m_X[llIndex].t; + math::float4 armV = apPoseGlobal->m_X[raIndex].t - apPoseGlobal->m_X[laIndex].t; + + math::float4 rightV = math::normalize(legV+armV); + math::float4 frontV = math::cross(rightV, upV); + + rightV = math::cross(upV,frontV); + + return math::normalize(math::quatMul(math::quatMatrixToQuat(rightV,upV,frontV),math::quatConj(apHuman->m_RootX.q))); + } + + math::xform HumanComputeRootXform(Human const* apHuman,skeleton::SkeletonPose const* apPoseGlobal) + { + return math::xform(HumanComputeMassCenter(apHuman,apPoseGlobal),HumanComputeOrientation(apHuman,apPoseGlobal),math::float4(1.0f)); + } + + float HumanGetFootHeight(Human const* apHuman, bool aLeft) + { + return apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[apHuman->m_HumanBoneIndex[aLeft ? kLeftFoot : kRightFoot]].m_AxesId].m_Length; + } + + math::float4 HumanGetFootBottom(Human const* apHuman, bool aLeft) + { + return math::float4(HumanGetFootHeight(apHuman,aLeft),0,0,0); + } + + math::xform HumanGetColliderXform(Human const* apHuman, math::xform const& x, int32_t aBoneIndex) + { + math::xform ret; + + int32_t skIndex = apHuman->m_HumanBoneIndex[aBoneIndex]; + + if(skIndex >= 0) + { + int32_t axesIndex = apHuman->m_Skeleton->m_Node[skIndex].m_AxesId; + int32_t colliderIndex = apHuman->m_ColliderIndex[aBoneIndex]; + + if(axesIndex >= 0 && colliderIndex >= 0) + { + ret = x; + + ret.q = math::normalize(math::quatMul(ret.q,apHuman->m_Skeleton->m_AxesArray[axesIndex].m_PostQ)); + + ret = math::xformMul(ret,apHuman->m_ColliderArray[colliderIndex].m_X); + + //ret.q = math::normalize(math::quatMul(ret.q,math::float4(0,1,0,1))); // to math physX axis setup + } + } + + return ret; + } + + math::xform HumanSubColliderXform(Human const* apHuman, math::xform const& x, int32_t aBoneIndex) + { + math::xform ret; + + int32_t skIndex = apHuman->m_HumanBoneIndex[aBoneIndex]; + + if(skIndex >= 0) + { + int32_t axesIndex = apHuman->m_Skeleton->m_Node[skIndex].m_AxesId; + int32_t colliderIndex = apHuman->m_ColliderIndex[aBoneIndex]; + + if(axesIndex >= 0 && colliderIndex >= 0) + { + ret = x; + + ret = math::xformMulInv(ret,apHuman->m_ColliderArray[colliderIndex].m_X); + + ret.q = math::normalize(math::quatMul(ret.q, math::quatConj(apHuman->m_Skeleton->m_AxesArray[axesIndex].m_PostQ))); + } + } + + return ret; + } + + math::float4 HumanGetGoalOrientationOffset(Goal goalIndex) + { + return math::load(goalOrientationOffsetArray[goalIndex]); + } + + void HumanPoseClear(HumanPose& arPose) + { + uint32_t i; + + arPose.m_RootX = math::xformIdentity(); + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X = math::xformIdentity(); + } + + for(i = 0; i < kLastDoF; i++) + { + arPose.m_DoFArray[i] = 0; + } + + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] = 0; + arPose.m_RightHandPose.m_DoFArray[i] = 0; + } + } + + void HumanPoseCopy(HumanPose &arPose,HumanPose const &arPoseA, bool aDoFOnly) + { + uint32_t i; + + if(!aDoFOnly) + { + arPose.m_RootX = arPoseA.m_RootX; + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X = arPoseA.m_GoalArray[i].m_X; + } + } + + for(i = 0; i < kLastDoF; i++) + { + arPose.m_DoFArray[i] = arPoseA.m_DoFArray[i]; + } + + hand::HandPoseCopy(&arPoseA.m_LeftHandPose,&arPose.m_LeftHandPose); + hand::HandPoseCopy(&arPoseA.m_RightHandPose,&arPose.m_RightHandPose); + } + + void HumanPoseCopy(HumanPose &arPose,HumanPose const &arPoseA, HumanPoseMask const &arHumanPoseMask) + { + if( arHumanPoseMask == FullBodyMask()) + { + HumanPoseCopy(arPose,arPoseA); + } + else + { + int32_t i; + for(i = 0; i < kLastDoF; i++) + { + if(arHumanPoseMask.test(kMaskDoFStartIndex+i)) + { + arPose.m_DoFArray[i] = arPoseA.m_DoFArray[i]; + } + else + { + arPose.m_DoFArray[i] = 0; + } + } + + if(arHumanPoseMask.test(kMaskLeftHand)) + { + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] = arPoseA.m_LeftHandPose.m_DoFArray[i]; + } + } + else + { + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] = 0; + } + } + + if(arHumanPoseMask.test(kMaskRightHand)) + { + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_RightHandPose.m_DoFArray[i] = arPoseA.m_RightHandPose.m_DoFArray[i]; + } + } + else + { + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_RightHandPose.m_DoFArray[i] = 0; + } + } + + for(i = 0; i < kLastGoal; i++) + { + if(arHumanPoseMask.test(kMaskGoalStartIndex+i)) + { + arPose.m_GoalArray[i].m_X = arPoseA.m_GoalArray[i].m_X; + } + else + { + arPose.m_GoalArray[i].m_X = math::xformIdentity(); + } + } + + if(arHumanPoseMask.test(0)) + { + arPose.m_RootX = arPoseA.m_RootX; + } + else + { + arPose.m_RootX = math::xformIdentity(); + } + + } + } + + void HumanPoseAdd(HumanPose &arPose,HumanPose const &arPoseA,HumanPose const &arPoseB) + { + uint32_t i; + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X = math::xformMul(arPoseA.m_GoalArray[i].m_X,arPoseB.m_GoalArray[i].m_X); + } + + for(i = 0; i < kLastDoF; i++) + { + arPose.m_DoFArray[i] = arPoseA.m_DoFArray[i] + arPoseB.m_DoFArray[i]; + } + + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] = arPoseA.m_LeftHandPose.m_DoFArray[i] + arPoseB.m_LeftHandPose.m_DoFArray[i]; + arPose.m_RightHandPose.m_DoFArray[i] = arPoseA.m_RightHandPose.m_DoFArray[i] + arPoseB.m_RightHandPose.m_DoFArray[i]; + } + + arPose.m_RootX = math::xformMul(arPoseA.m_RootX,arPoseB.m_RootX); + } + + void HumanPoseSub(HumanPose &arPose,HumanPose const &arPoseA,HumanPose const &arPoseB) + { + uint32_t i; + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X = math::xformInvMulNS(arPoseB.m_GoalArray[i].m_X,arPoseA.m_GoalArray[i].m_X); + } + + for(i = 0; i < kLastDoF; i++) + { + arPose.m_DoFArray[i] = arPoseA.m_DoFArray[i] - arPoseB.m_DoFArray[i]; + } + + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] = arPoseA.m_LeftHandPose.m_DoFArray[i] - arPoseB.m_LeftHandPose.m_DoFArray[i]; + arPose.m_RightHandPose.m_DoFArray[i] = arPoseA.m_RightHandPose.m_DoFArray[i] - arPoseB.m_RightHandPose.m_DoFArray[i]; + } + + arPose.m_RootX = math::xformInvMulNS(arPoseB.m_RootX,arPoseA.m_RootX); + } + + void HumanPoseWeight(HumanPose &arPose,HumanPose const &arPoseA, float aWeight) + { + uint32_t i; + + math::float1 w(aWeight); + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X = math::xformWeight(arPoseA.m_GoalArray[i].m_X,w); + } + + for(i = 0; i < kLastDoF; i++) + { + arPose.m_DoFArray[i] = arPoseA.m_DoFArray[i] * aWeight; + } + + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] = arPoseA.m_LeftHandPose.m_DoFArray[i] * aWeight; + arPose.m_RightHandPose.m_DoFArray[i] = arPoseA.m_RightHandPose.m_DoFArray[i] * aWeight; + } + + arPose.m_RootX = math::xformWeight(arPoseA.m_RootX,w); + } + + void HumanPoseMirror(HumanPose &arPose,HumanPose const &arPoseA) + { + uint32_t i; + + for(i = 0; i < kLastBodyDoF; i++) + { + arPose.m_DoFArray[kBodyDoFStart + i] *= BodyDoFMirror[i]; + } + + for(i = 0; i < kLastHeadDoF; i++) + { + arPose.m_DoFArray[kHeadDoFStart + i] *= HeadDoFMirror[i]; + // bobtodo + } + + for(i = 0; i < kLastArmDoF; i++) + { + float dof = arPose.m_DoFArray[kLeftArmDoFStart + i]; + arPose.m_DoFArray[kLeftArmDoFStart + i] = arPose.m_DoFArray[kRightArmDoFStart + i]; + arPose.m_DoFArray[kRightArmDoFStart + i] = dof; + } + + for(i = 0; i < kLastLegDoF; i++) + { + float dof = arPose.m_DoFArray[kLeftLegDoFStart + i]; + arPose.m_DoFArray[kLeftLegDoFStart + i] = arPose.m_DoFArray[kRightLegDoFStart + i]; + arPose.m_DoFArray[kRightLegDoFStart + i] = dof; + } + + math::xform x = arPose.m_GoalArray[kLeftFootGoal].m_X; + arPose.m_GoalArray[kLeftFootGoal].m_X = arPose.m_GoalArray[kRightFootGoal].m_X; + arPose.m_GoalArray[kRightFootGoal].m_X = x; + + x = arPose.m_GoalArray[kLeftHandGoal].m_X; + arPose.m_GoalArray[kLeftHandGoal].m_X = arPose.m_GoalArray[kRightHandGoal].m_X; + arPose.m_GoalArray[kRightHandGoal].m_X = x; + + constant_float4(offsetQY,0,1,0,0); + constant_float4(offsetQZ,0,0,1,0); + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X = math::mirror(arPose.m_GoalArray[i].m_X); + } + + arPose.m_GoalArray[kLeftFootGoal].m_X.q = math::normalize(math::quatMul(arPose.m_GoalArray[kLeftFootGoal].m_X.q,offsetQY)); + arPose.m_GoalArray[kRightFootGoal].m_X.q = math::normalize(math::quatMul(arPose.m_GoalArray[kRightFootGoal].m_X.q,offsetQY)); + arPose.m_GoalArray[kLeftHandGoal].m_X.q = math::normalize(math::quatMul(arPose.m_GoalArray[kLeftHandGoal].m_X.q,offsetQZ)); + arPose.m_GoalArray[kRightHandGoal].m_X.q = math::normalize(math::quatMul(arPose.m_GoalArray[kRightHandGoal].m_X.q,offsetQZ)); + + arPose.m_RootX = math::mirror(arPose.m_RootX); + + for(i = 0; i < hand::s_DoFCount; i++) + { + float leftdof = arPose.m_LeftHandPose.m_DoFArray[i]; + arPose.m_LeftHandPose.m_DoFArray[i] = arPose.m_RightHandPose.m_DoFArray[i]; + arPose.m_RightHandPose.m_DoFArray[i] = leftdof; + } + } + + void HumanPoseBlend(HumanPose &arPose,HumanPose **apPoseArray, float *apWeightArray, uint32_t aCount) + { + uint32_t poseIter,i; + + for(i = 0; i < kLastDoF; i++) + { + arPose.m_DoFArray[i] = 0; + } + + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] = 0; + arPose.m_RightHandPose.m_DoFArray[i] = 0; + } + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X.t = math::float4::zero(); + arPose.m_GoalArray[i].m_X.q = math::float4::zero(); + arPose.m_GoalArray[i].m_X.s = math::float4::one(); + } + + arPose.m_RootX.t = math::float4::zero(); + arPose.m_RootX.q = math::float4::zero(); + arPose.m_RootX.s = math::float4::one(); + + float sumW = 0; + + for(poseIter = 0; poseIter < aCount; poseIter++) + { + float w = apWeightArray[poseIter]; + math::float1 w1(w); + + sumW += w; + + for(i = 0; i < kLastDoF; i++) + { + arPose.m_DoFArray[i] += apPoseArray[poseIter]->m_DoFArray[i]*w; + } + + for(i = 0; i < hand::s_DoFCount; i++) + { + arPose.m_LeftHandPose.m_DoFArray[i] += apPoseArray[poseIter]->m_LeftHandPose.m_DoFArray[i] * w; + arPose.m_RightHandPose.m_DoFArray[i] += apPoseArray[poseIter]->m_RightHandPose.m_DoFArray[i] * w; + } + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X.t += apPoseArray[poseIter]->m_GoalArray[i].m_X.t*w1; + arPose.m_GoalArray[i].m_X.q += math::cond(math::dot(arPose.m_GoalArray[i].m_X.q,apPoseArray[poseIter]->m_GoalArray[i].m_X.q) < math::float1::zero(),apPoseArray[poseIter]->m_GoalArray[i].m_X.q * -w1,apPoseArray[poseIter]->m_GoalArray[i].m_X.q * w1); + arPose.m_GoalArray[i].m_X.s *= scaleWeight(apPoseArray[poseIter]->m_GoalArray[i].m_X.s,w1); + } + + arPose.m_RootX.t += apPoseArray[poseIter]->m_RootX.t*w1; + arPose.m_RootX.q += math::cond(math::dot(arPose.m_RootX.q,apPoseArray[poseIter]->m_RootX.q) < math::float1::zero(),apPoseArray[poseIter]->m_RootX.q * -w1,apPoseArray[poseIter]->m_RootX.q * w1); + arPose.m_RootX.s *= scaleWeight(apPoseArray[poseIter]->m_RootX.s,w1); + } + + math::float4 q(0,0,0,math::saturate(1.0f-sumW)); + + for(i = 0; i < kLastGoal; i++) + { + arPose.m_GoalArray[i].m_X.q = math::normalize(arPose.m_GoalArray[i].m_X.q+q); + } + + arPose.m_RootX.q = math::normalize(arPose.m_RootX.q+q); + + } + + void HumanPoseAddOverrideLayer(HumanPose &arPoseBase,HumanPose const &arPose, float aWeight, HumanPoseMask const &arHumanPoseMask) + { + if(aWeight > 0.0f) + { + float weightInv = 1.0f - aWeight; + math::float1 w(aWeight); + + int32_t i; + for(i = 0; i < kLastDoF; i++) + { + if(arHumanPoseMask.test(kMaskDoFStartIndex+i)) + { + if(aWeight < 1.0f) + { + arPoseBase.m_DoFArray[i] = weightInv * arPoseBase.m_DoFArray[i] + aWeight * arPose.m_DoFArray[i]; + } + else + { + arPoseBase.m_DoFArray[i] = arPose.m_DoFArray[i]; + } + } + } + + if(arHumanPoseMask.test(kMaskLeftHand)) + { + for(i = 0; i < hand::s_DoFCount; i++) + { + if(aWeight < 1.0f) + { + arPoseBase.m_LeftHandPose.m_DoFArray[i] = weightInv * arPoseBase.m_LeftHandPose.m_DoFArray[i] + aWeight * arPose.m_LeftHandPose.m_DoFArray[i]; + } + else + { + arPoseBase.m_LeftHandPose.m_DoFArray[i] = arPose.m_LeftHandPose.m_DoFArray[i]; + } + } + } + + if(arHumanPoseMask.test(kMaskRightHand)) + { + for(i = 0; i < hand::s_DoFCount; i++) + { + if(aWeight < 1.0f) + { + arPoseBase.m_RightHandPose.m_DoFArray[i] = weightInv * arPoseBase.m_RightHandPose.m_DoFArray[i] + aWeight * arPose.m_RightHandPose.m_DoFArray[i]; + } + else + { + arPoseBase.m_RightHandPose.m_DoFArray[i] = arPose.m_RightHandPose.m_DoFArray[i]; + } + } + } + + for(i = 0; i < kLastGoal; i++) + { + if(arHumanPoseMask.test(kMaskGoalStartIndex+i)) + { + if(aWeight < 1.0f) + { + arPoseBase.m_GoalArray[i].m_X = math::xformBlend(arPoseBase.m_GoalArray[i].m_X,arPose.m_GoalArray[i].m_X,w); + } + else + { + arPoseBase.m_GoalArray[i].m_X = arPose.m_GoalArray[i].m_X; + } + } + } + + if(arHumanPoseMask.test(0)) + { + if(aWeight < 1.0f) + { + arPoseBase.m_RootX = math::xformBlend(arPoseBase.m_RootX,arPose.m_RootX,w); + } + else + { + arPoseBase.m_RootX = arPose.m_RootX; + } + } + } + } + + void HumanPoseAddAdditiveLayer(HumanPose &arPoseBase,HumanPose const &arPose, float aWeight, HumanPoseMask const &arHumanPoseMask) + { + if(aWeight > 0.0f) + { + math::float1 w(aWeight); + + int32_t i; + for(i = 0; i < kLastDoF; i++) + { + if(arHumanPoseMask.test(kMaskDoFStartIndex+i)) + { + arPoseBase.m_DoFArray[i] += aWeight * arPose.m_DoFArray[i]; + } + } + + if(arHumanPoseMask.test(kMaskLeftHand)) + { + for(i = 0; i < hand::s_DoFCount; i++) + { + arPoseBase.m_LeftHandPose.m_DoFArray[i] += aWeight * arPose.m_LeftHandPose.m_DoFArray[i]; + } + } + + if(arHumanPoseMask.test(kMaskRightHand)) + { + for(i = 0; i < hand::s_DoFCount; i++) + { + arPoseBase.m_RightHandPose.m_DoFArray[i] += aWeight * arPose.m_RightHandPose.m_DoFArray[i]; + } + } + + for(i = 0; i < kLastGoal; i++) + { + if(arHumanPoseMask.test(kMaskGoalStartIndex+i)) + { + arPoseBase.m_GoalArray[i].m_X = math::xformMul(arPoseBase.m_GoalArray[i].m_X, math::xformWeight(arPose.m_GoalArray[i].m_X, w)); + } + } + + if(arHumanPoseMask.test(0)) + { + arPoseBase.m_RootX = math::xformMul(arPoseBase.m_RootX, math::xformWeight(arPose.m_RootX,w)); + } + } + } + + void HumanFixMidDoF(Human const *apHuman, skeleton::SkeletonPose *apSkeletonPose, skeleton::SkeletonPose *apSkeletonPoseWs, int32_t aPIndex, int32_t aCIndex) + { + int32_t pNodeIndex = apHuman->m_HumanBoneIndex[aPIndex]; + int32_t cNodeIndex = apHuman->m_HumanBoneIndex[aCIndex]; + int32_t aNodeIndex = apHuman->m_Skeleton->m_Node[pNodeIndex].m_ParentId; + + math::Axes pAxes = apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[pNodeIndex].m_AxesId]; + math::Axes cAxes = apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[cNodeIndex].m_AxesId]; + + apSkeletonPoseWs->m_X[aNodeIndex].q = math::quatIdentity(); + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,pNodeIndex); + + math::float4 pq = apSkeletonPose->m_X[pNodeIndex].q; + math::float4 cqg = apSkeletonPoseWs->m_X[cNodeIndex].q; + + math::float4 cql = AxesProject(cAxes,apSkeletonPose->m_X[cNodeIndex].q); + + math::float4 xyz = math::quat2ZYRoll(cql); + xyz.y() = math::float1::zero(); + cql = math::ZYRoll2Quat(xyz); + + cql = math::AxesUnproject(cAxes,cql); + + apSkeletonPose->m_X[cNodeIndex].q = cql; + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,cNodeIndex); + + math::float4 qdiff = math::quatMul(cqg,math::quatConj(apSkeletonPoseWs->m_X[cNodeIndex].q)); + + apSkeletonPose->m_X[pNodeIndex].q = math::normalize(math::quatMul(qdiff,apSkeletonPose->m_X[pNodeIndex].q)); + + skeleton::SkeletonAlign(apHuman->m_Skeleton.Get(),pq,apSkeletonPose->m_X[pNodeIndex].q,pNodeIndex); + + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,pNodeIndex); + + apSkeletonPoseWs->m_X[cNodeIndex].q = cqg; + + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWs,apSkeletonPose,cNodeIndex,cNodeIndex); + } + + void HumanFixEndDoF(Human const *apHuman, skeleton::SkeletonPose *apSkeletonPose, skeleton::SkeletonPose *apSkeletonPoseWs, int32_t aPIndex, int32_t aCIndex) + { + int32_t pNodeIndex = apHuman->m_HumanBoneIndex[aPIndex]; + int32_t cNodeIndex = apHuman->m_HumanBoneIndex[aCIndex]; + int32_t aNodeIndex = apHuman->m_Skeleton->m_Node[pNodeIndex].m_ParentId; + + math::Axes pAxes = apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[pNodeIndex].m_AxesId]; + math::Axes cAxes = apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[cNodeIndex].m_AxesId]; + + apSkeletonPoseWs->m_X[aNodeIndex].q = math::quatIdentity(); + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,pNodeIndex); + + math::float4 pq = apSkeletonPose->m_X[pNodeIndex].q; + math::float4 cqg = apSkeletonPoseWs->m_X[cNodeIndex].q; + + math::float4 pq0 = FromAxes(pAxes,math::float4::zero()); + math::float4 cql0 = FromAxes(cAxes,math::float4::zero()); + + apSkeletonPose->m_X[pNodeIndex].q = pq0; + apSkeletonPose->m_X[cNodeIndex].q = cql0; + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,pNodeIndex); + + math::float4 qdiff = math::quatMul(cqg,math::quatConj(apSkeletonPoseWs->m_X[cNodeIndex].q)); + + apSkeletonPose->m_X[pNodeIndex].q = math::normalize(math::quatMul(qdiff,pq0)); + + skeleton::SkeletonAlign(apHuman->m_Skeleton.Get(),pq,apSkeletonPose->m_X[pNodeIndex].q,pNodeIndex); + + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,pNodeIndex); + + apSkeletonPoseWs->m_X[cNodeIndex].q = cqg; + + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWs,apSkeletonPose,cNodeIndex,cNodeIndex); + } + + void HumanFixTwist(Human const *apHuman, skeleton::SkeletonPose *apSkeletonPose, skeleton::SkeletonPose *apSkeletonPoseWs, int32_t aPIndex, int32_t aCIndex, const math::float1& aTwist) + { + int32_t pNodeIndex = apHuman->m_HumanBoneIndex[aPIndex]; + int32_t cNodeIndex = apHuman->m_HumanBoneIndex[aCIndex]; + int32_t aNodeIndex = apHuman->m_Skeleton->m_Node[pNodeIndex].m_ParentId; + + math::Axes pAxes = apHuman->m_Skeleton->m_AxesArray[apHuman->m_Skeleton->m_Node[pNodeIndex].m_AxesId]; + + apSkeletonPoseWs->m_X[aNodeIndex].q = math::quatIdentity(); + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,pNodeIndex); + + math::float4 pq = apSkeletonPose->m_X[pNodeIndex].q; + math::float4 cqg = apSkeletonPoseWs->m_X[cNodeIndex].q; + + math::float4 pxyz = math::ToAxes(pAxes,apSkeletonPose->m_X[pNodeIndex].q); + pxyz.x() *= aTwist; + + apSkeletonPose->m_X[pNodeIndex].q = math::FromAxes(pAxes,pxyz); + + skeleton::SkeletonAlign(apHuman->m_Skeleton.Get(),pq,apSkeletonPose->m_X[pNodeIndex].q,pNodeIndex); + + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWs,cNodeIndex,pNodeIndex); + + apSkeletonPoseWs->m_X[cNodeIndex].q = cqg; + + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWs,apSkeletonPose,cNodeIndex,cNodeIndex); + } + + void ReachGoalRotation(Human const *apHuman,math::float4 const &arEndQ, int32_t aGoalIndex, skeleton::SkeletonPose *apSkeletonPose, skeleton::SkeletonPose *apSkeletonPoseGbl, skeleton::SkeletonPose *apSkeletonPoseWorkspace) + { + int32_t index = apHuman->m_HumanBoneIndex[s_HumanGoalInfo[aGoalIndex].m_Index]; + int32_t parentIndex = apHuman->m_Skeleton->m_Node[index].m_ParentId; + apSkeletonPose->m_X[index].q = math::normalize(math::quatMul(math::quatConj(apSkeletonPoseGbl->m_X[parentIndex].q),arEndQ)); + + HumanFixEndDoF(apHuman,apSkeletonPose,apSkeletonPoseWorkspace,s_HumanGoalInfo[aGoalIndex].m_MidIndex,s_HumanGoalInfo[aGoalIndex].m_EndIndex); + } + + void HumanFixEndPointsSkeletonPose(Human const *apHuman, skeleton::SkeletonPose const*apSkeletonPoseRef, HumanPose *apHumanPose, skeleton::SkeletonPose *apSkeletonPoseGbl, skeleton::SkeletonPose *apSkeletonPoseLcl, skeleton::SkeletonPose *apSkeletonPoseWs,int32_t cIndex, int32_t pIndex) + { + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseLcl,apSkeletonPoseGbl,apHuman->m_HumanBoneIndex[cIndex],apHuman->m_HumanBoneIndex[pIndex]); + apSkeletonPoseGbl->m_X[apHuman->m_HumanBoneIndex[cIndex]].q = apSkeletonPoseRef->m_X[apHuman->m_HumanBoneIndex[cIndex]].q; + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseGbl,apSkeletonPoseLcl,apHuman->m_HumanBoneIndex[cIndex],apHuman->m_HumanBoneIndex[pIndex]); + + HumanFixEndDoF(apHuman,apSkeletonPoseLcl,apSkeletonPoseWs,pIndex,cIndex); + } + + void HumanAlignSkeletonPose(Human const *apHuman, skeleton::SkeletonPose const*apSkeletonPoseRef, HumanPose *apHumanPose, skeleton::SkeletonPose *apSkeletonPoseGbl, skeleton::SkeletonPose *apSkeletonPoseLcl,int32_t cIndex, int32_t pIndex) + { + Skeleton2HumanPose(apHuman,apSkeletonPoseLcl,apHumanPose,cIndex); + Human2SkeletonPose(apHuman,apHumanPose,apSkeletonPoseLcl,cIndex); + + skeleton::SkeletonPoseComputeGlobalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseLcl,apSkeletonPoseGbl,apHuman->m_HumanBoneIndex[cIndex],apHuman->m_HumanBoneIndex[pIndex]); + skeleton::SkeletonAlign(apHuman->m_Skeleton.Get(),apSkeletonPoseRef,apSkeletonPoseGbl,apHuman->m_HumanBoneIndex[cIndex]); + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseGbl,apSkeletonPoseLcl,apHuman->m_HumanBoneIndex[cIndex],apHuman->m_HumanBoneIndex[pIndex]); + } + + void RetargetFrom( Human const *apHuman, + skeleton::SkeletonPose const *apSkeletonPose, + HumanPose *apHumanPose, + skeleton::SkeletonPose *apSkeletonPoseRef, + skeleton::SkeletonPose *apSkeletonPoseGbl, + skeleton::SkeletonPose *apSkeletonPoseLcl, + skeleton::SkeletonPose *apSkeletonPoseWs, + mecanim::int32_t maxFixIter) + + { + const int32_t hipsIndex = apHuman->m_HumanBoneIndex[human::kHips]; + const math::float1 scale(apHuman->m_Scale); + + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseRef); + skeleton::SkeletonPoseCopy(apSkeletonPoseRef,apSkeletonPoseGbl); + + // force dummy bones to their default rotation + int32_t nodeIter; + for(nodeIter = 1; nodeIter < apHuman->m_Skeleton->m_Count; nodeIter++) + { + if(apHuman->m_Skeleton->m_Node[nodeIter].m_AxesId == -1) + { + apSkeletonPoseGbl->m_X[nodeIter].q = math::quatMul(apSkeletonPoseGbl->m_X[apHuman->m_Skeleton->m_Node[nodeIter].m_ParentId].q,apHuman->m_SkeletonPose->m_X[nodeIter].q); + } + } + + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseGbl,apSkeletonPoseLcl); + + int32_t fixIter; + + // align shoulders + for(fixIter = 0; fixIter < maxFixIter; fixIter++) + { + if(apHuman->m_HumanBoneIndex[kLeftShoulder] != -1) + { + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kLeftShoulder, kLeftShoulder); + } + + if(apHuman->m_HumanBoneIndex[kRightShoulder] != -1) + { + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kRightShoulder, kRightShoulder); + } + } + + // align upper limbs + for(fixIter = 0; fixIter < maxFixIter; fixIter++) + { + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kLeftUpperArm, apHuman->m_HumanBoneIndex[kLeftShoulder] != -1 ? kLeftShoulder : kLeftUpperArm); + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kRightUpperArm, apHuman->m_HumanBoneIndex[kRightShoulder] != -1 ? kRightShoulder : kRightUpperArm); + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kLeftUpperLeg, kLeftUpperLeg); + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kRightUpperLeg, kRightUpperLeg); + } + + // align & fix lower limbs + for(fixIter = 0; fixIter < maxFixIter; fixIter++) + { + HumanFixMidDoF(apHuman,apSkeletonPoseLcl,apSkeletonPoseWs,kLeftUpperArm,kLeftLowerArm); + HumanFixMidDoF(apHuman,apSkeletonPoseLcl,apSkeletonPoseWs,kRightUpperArm,kRightLowerArm); + HumanFixMidDoF(apHuman,apSkeletonPoseLcl,apSkeletonPoseWs,kLeftUpperLeg,kLeftLowerLeg); + HumanFixMidDoF(apHuman,apSkeletonPoseLcl,apSkeletonPoseWs,kRightUpperLeg,kRightLowerLeg); + + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kLeftLowerArm, kLeftUpperArm); + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kRightLowerArm, kRightUpperArm); + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kLeftLowerLeg, kLeftUpperLeg); + HumanAlignSkeletonPose(apHuman,apSkeletonPoseRef,apHumanPose,apSkeletonPoseGbl,apSkeletonPoseLcl,kRightLowerLeg, kRightUpperLeg); + } + + HumanFixEndPointsSkeletonPose(apHuman,apSkeletonPoseRef, apHumanPose, apSkeletonPoseGbl, apSkeletonPoseLcl, apSkeletonPoseWs, kLeftHand, kLeftLowerArm); + HumanFixEndPointsSkeletonPose(apHuman,apSkeletonPoseRef, apHumanPose, apSkeletonPoseGbl, apSkeletonPoseLcl, apSkeletonPoseWs, kRightHand, kRightLowerArm); + HumanFixEndPointsSkeletonPose(apHuman,apSkeletonPoseRef, apHumanPose, apSkeletonPoseGbl, apSkeletonPoseLcl, apSkeletonPoseWs, kLeftFoot, kLeftLowerLeg); + HumanFixEndPointsSkeletonPose(apHuman,apSkeletonPoseRef, apHumanPose, apSkeletonPoseGbl, apSkeletonPoseLcl, apSkeletonPoseWs, kRightFoot, kRightLowerLeg); + + Skeleton2HumanPose(apHuman,apSkeletonPoseLcl,apHumanPose); + skeleton::SkeletonPoseCopy(apHuman->m_SkeletonPose.Get(), apSkeletonPoseLcl); + Human2SkeletonPose(apHuman, apHumanPose, apSkeletonPoseLcl); + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(), apSkeletonPoseLcl,apSkeletonPoseGbl); + + apHumanPose->m_RootX = HumanComputeRootXform(apHuman,apSkeletonPoseGbl); + apHumanPose->m_RootX = math::xformInvMul(apSkeletonPoseGbl->m_X[hipsIndex],apHumanPose->m_RootX); + apHumanPose->m_RootX = math::xformMul(apSkeletonPoseRef->m_X[hipsIndex],apHumanPose->m_RootX); + apHumanPose->m_RootX.s = math::float4::one(); + + int32_t goalIter; + for(goalIter = 0; goalIter < kLastGoal; goalIter++) + { + int32_t index = apHuman->m_HumanBoneIndex[s_HumanGoalInfo[goalIter].m_Index]; + apHumanPose->m_GoalArray[goalIter].m_X.t = apSkeletonPoseRef->m_X[index].t; + apHumanPose->m_GoalArray[goalIter].m_X.q = AddAxis(apHuman,index,apSkeletonPoseRef->m_X[index].q); + apHumanPose->m_GoalArray[goalIter].m_X.s = math::float4::one(); + + if(goalIter < 2) apHumanPose->m_GoalArray[goalIter].m_X.t = math::xformMulVec(apHumanPose->m_GoalArray[goalIter].m_X,human::HumanGetFootBottom(apHuman,goalIter==0)); + apHumanPose->m_GoalArray[goalIter].m_X = math::xformInvMulNS(apHumanPose->m_RootX,apHumanPose->m_GoalArray[goalIter].m_X); + apHumanPose->m_GoalArray[goalIter].m_X.t /= scale; + } + + apHumanPose->m_RootX.t /= scale; + } + + void RetargetTo( Human const *apHuman, + HumanPose const *apHumanPoseBase, + HumanPose const *apHumanPose, + const math::xform &arX, + HumanPose *apHumanPoseOut, + skeleton::SkeletonPose *apSkeletonPose, + skeleton::SkeletonPose *apSkeletonPoseWs) + { + const int32_t rootIndex = 0; + const int32_t hipsIndex = apHuman->m_HumanBoneIndex[human::kHips]; + const math::float1 scale(apHuman->m_Scale); + + human::HumanPoseCopy(*apHumanPoseOut,*apHumanPoseBase); + + apHumanPoseOut->m_RootX.t *= scale; + apHumanPoseOut->m_RootX = math::xformMul(arX,apHumanPoseOut->m_RootX); + + int32_t goalIter; + for(goalIter = 0; goalIter < kLastGoal; goalIter++) + { + apHumanPoseOut->m_GoalArray[goalIter].m_X = apHumanPose ? apHumanPose->m_GoalArray[goalIter].m_X : apHumanPoseBase->m_GoalArray[goalIter].m_X; + apHumanPoseOut->m_GoalArray[goalIter].m_X.t *= scale; + apHumanPoseOut->m_GoalArray[goalIter].m_X = math::xformMul(arX,apHumanPoseOut->m_GoalArray[goalIter].m_X); + + if(goalIter < 2) apHumanPoseOut->m_GoalArray[goalIter].m_X.t = math::xformMulVec(apHumanPoseOut->m_GoalArray[goalIter].m_X,-human::HumanGetFootBottom(apHuman,goalIter==0)); + } + + ////////////////////////////////////////////////// + // + // transfer muscle space for base pose + // + skeleton::SkeletonPoseCopy(apHuman->m_SkeletonPose.Get(), apSkeletonPose); + HumanPoseAdjustForMissingBones(apHuman,apHumanPoseOut); + Human2SkeletonPose(apHuman, apHumanPoseOut, apSkeletonPose); + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(), apSkeletonPose,apSkeletonPoseWs); + + /////////////////////////////////////////////////////// + // + // adjust hips local + // + math::xform rootX = HumanComputeRootXform(apHuman,apSkeletonPoseWs); + apSkeletonPose->m_X[hipsIndex] = math::xformInvMulNS(rootX,apSkeletonPoseWs->m_X[hipsIndex]); + apSkeletonPose->m_X[hipsIndex].s = apSkeletonPoseWs->m_X[hipsIndex].s; + + //////////////////////////////////////////////////////// + // + // transfer muscle space + // + if(apHumanPose) + { + human::HumanPoseCopy(*apHumanPoseOut,*apHumanPose,true); + HumanPoseAdjustForMissingBones(apHuman,apHumanPoseOut); + Human2SkeletonPose(apHuman, apHumanPoseOut, apSkeletonPose); + } + + ////////////////////////////////////////////////// + // + // root + // + apSkeletonPose->m_X[rootIndex] = apHumanPoseOut->m_RootX; + } + + math::float4 GetLookAtDeltaQ(math::float4 const &pivot,math::float4 const &eyesT, math::float4 const &eyesQ, math::float4 const &eyesDir, math::float4 const &target, math::float1 const &weight) + { + math::float1 len = math::length(target - eyesT); + math::float4 dstV = target - pivot; + math::float4 srcV = eyesT - math::quatMulVec(eyesQ,eyesDir*math::float1(len)) - pivot; + + return math::quatWeight(math::normalize(math::quatArcRotate(srcV,dstV)),weight); + } + + void FullBodySolve(Human const *apHuman, HumanPose const *apHumanPose, skeleton::SkeletonPose *apSkeletonPose, skeleton::SkeletonPose *apSkeletonPoseWorkspaceA, skeleton::SkeletonPose *apSkeletonPoseWorkspaceB) + { + const int32_t hipsIndex = apHuman->m_HumanBoneIndex[kHips]; + const int32_t chestIndex = apHuman->m_HumanBoneIndex[kChest]; + const int32_t spineIndex = apHuman->m_HumanBoneIndex[kSpine]; + const int32_t neckIndex = apHuman->m_HumanBoneIndex[kNeck]; + const int32_t headIndex = apHuman->m_HumanBoneIndex[kHead]; + const int32_t leftEyeIndex = apHuman->m_HumanBoneIndex[kLeftEye]; + const int32_t rightEyeIndex = apHuman->m_HumanBoneIndex[kRightEye]; + + math::float1 lcw = math::saturate(math::float1(apHumanPose->m_LookAtWeight.x())); + math::float1 lbw = math::saturate(math::float1(apHumanPose->m_LookAtWeight.y())); + math::float1 lhw = math::saturate(math::float1(apHumanPose->m_LookAtWeight.z())); + math::float1 lew = math::saturate(math::float1(apHumanPose->m_LookAtWeight.w())); + + math::float4 headGoalT = apHumanPose->m_LookAtPosition; + + if(lcw > math::float1::zero()) + { + math::float4 eyesPos = apSkeletonPoseWorkspaceA->m_X[headIndex].t; + math::float4 eyesRot = AddAxis(apHuman,headIndex,apSkeletonPoseWorkspaceA->m_X[headIndex].q); + if(leftEyeIndex != -1 && rightEyeIndex != -1) eyesPos = math::xformMulVec(apSkeletonPoseWorkspaceA->m_X[headIndex],(apHuman->m_SkeletonPose->m_X[leftEyeIndex].t + apHuman->m_SkeletonPose->m_X[rightEyeIndex].t) * math::float1(0.5f)); + + math::float4 dstV = headGoalT - eyesPos; + math::float4 v = math::float4::zero(); + v.y() = -math::length(dstV); + math::float4 srcV = math::quatMulVec(eyesRot,v); + + math::float4 deltaQ = math::quatClamp(math::normalize(math::quatArcRotate(srcV,dstV)),math::radians(180.f*(1.f - lcw.tofloat()))); + + headGoalT = eyesPos + math::quatMulVec(deltaQ,srcV); + } + + if(lbw > math::float1::zero()) + { + math::float1 lsw = chestIndex != -1 ? math::float1(0.5) * lbw : lbw; + + math::float4 eyesPos = apSkeletonPoseWorkspaceA->m_X[headIndex].t; + math::float4 eyesRot = AddAxis(apHuman,headIndex,apSkeletonPoseWorkspaceA->m_X[headIndex].q); + + math::float4 deltaQ = GetLookAtDeltaQ(apSkeletonPoseWorkspaceA->m_X[spineIndex].t,eyesPos,eyesRot,math::float4(0,1,0,0),headGoalT,lsw); + + apSkeletonPoseWorkspaceA->m_X[spineIndex].q = math::normalize(math::quatMul(deltaQ,apSkeletonPoseWorkspaceA->m_X[spineIndex].q)); + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspaceA,apSkeletonPose,spineIndex,spineIndex); + + if(chestIndex != -1) + { + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,headIndex,spineIndex); + + math::float4 eyesPos = apSkeletonPoseWorkspaceA->m_X[headIndex].t; + math::float4 eyesRot = AddAxis(apHuman,headIndex,apSkeletonPoseWorkspaceA->m_X[headIndex].q); + + math::float4 deltaQ = GetLookAtDeltaQ(apSkeletonPoseWorkspaceA->m_X[chestIndex].t,eyesPos,eyesRot,math::float4(0,1,0,0),headGoalT,lbw); + + apSkeletonPoseWorkspaceA->m_X[chestIndex].q = math::normalize(math::quatMul(deltaQ,apSkeletonPoseWorkspaceA->m_X[chestIndex].q)); + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspaceA,apSkeletonPose,chestIndex,chestIndex); + } + } + + if(lhw > math::float1::zero()) + { + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,headIndex,spineIndex); + + if(neckIndex != -1) + { + math::float4 eyesPos = apSkeletonPoseWorkspaceA->m_X[headIndex].t; + math::float4 eyesRot = AddAxis(apHuman,headIndex,apSkeletonPoseWorkspaceA->m_X[headIndex].q); + + if(leftEyeIndex != -1 && rightEyeIndex != -1) eyesPos = math::xformMulVec(apSkeletonPoseWorkspaceA->m_X[headIndex],(apHuman->m_SkeletonPose->m_X[leftEyeIndex].t + apHuman->m_SkeletonPose->m_X[rightEyeIndex].t) * math::float1(0.5f)); + + math::float4 deltaQ = GetLookAtDeltaQ(apSkeletonPoseWorkspaceA->m_X[neckIndex].t,eyesPos,eyesRot,math::float4(0,1,0,0),headGoalT,lhw * math::float1(0.5)); + + apSkeletonPoseWorkspaceA->m_X[neckIndex].q = math::normalize(math::quatMul(deltaQ,apSkeletonPoseWorkspaceA->m_X[neckIndex].q)); + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspaceA,apSkeletonPose,neckIndex,neckIndex); + } + + int32_t iter; + for(iter = 0; iter < 3; iter++) + { + math::float4 eyesPos = apSkeletonPoseWorkspaceA->m_X[headIndex].t; + math::float4 eyesRot = AddAxis(apHuman,headIndex,apSkeletonPoseWorkspaceA->m_X[headIndex].q); + + if(leftEyeIndex != -1 && rightEyeIndex != -1) eyesPos = math::xformMulVec(apSkeletonPoseWorkspaceA->m_X[headIndex],(apHuman->m_SkeletonPose->m_X[leftEyeIndex].t + apHuman->m_SkeletonPose->m_X[rightEyeIndex].t) * math::float1(0.5f)); + + math::float4 deltaQ = GetLookAtDeltaQ(apSkeletonPoseWorkspaceA->m_X[headIndex].t,eyesPos,eyesRot,math::float4(0,1,0,0),headGoalT,lhw*lhw); + + apSkeletonPoseWorkspaceA->m_X[headIndex].q = math::normalize(math::quatMul(deltaQ,apSkeletonPoseWorkspaceA->m_X[headIndex].q)); + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspaceA,apSkeletonPose,headIndex,headIndex); + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,headIndex,headIndex); + } + } + + if(lew > math::float1::zero()) + { + if(leftEyeIndex != -1) + { + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,leftEyeIndex,spineIndex); + + math::float4 eyesPos = apSkeletonPoseWorkspaceA->m_X[leftEyeIndex].t; + math::float4 eyesRot = AddAxis(apHuman,leftEyeIndex,apSkeletonPoseWorkspaceA->m_X[leftEyeIndex].q); + + math::float4 deltaQ = GetLookAtDeltaQ(apSkeletonPoseWorkspaceA->m_X[leftEyeIndex].t,eyesPos,eyesRot,math::float4(-1,0,0,0),headGoalT,lew); + + apSkeletonPoseWorkspaceA->m_X[leftEyeIndex].q = math::normalize(math::quatMul(deltaQ,apSkeletonPoseWorkspaceA->m_X[leftEyeIndex].q)); + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspaceA,apSkeletonPose,leftEyeIndex,leftEyeIndex); + } + + if(rightEyeIndex != -1) + { + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,rightEyeIndex,spineIndex); + + math::float4 eyesPos = apSkeletonPoseWorkspaceA->m_X[rightEyeIndex].t; + math::float4 eyesRot = AddAxis(apHuman,rightEyeIndex,apSkeletonPoseWorkspaceA->m_X[rightEyeIndex].q); + + math::float4 deltaQ = GetLookAtDeltaQ(apSkeletonPoseWorkspaceA->m_X[rightEyeIndex].t,eyesPos,eyesRot,math::float4(-1,0,0,0),headGoalT,lew); + + apSkeletonPoseWorkspaceA->m_X[rightEyeIndex].q = math::normalize(math::quatMul(deltaQ,apSkeletonPoseWorkspaceA->m_X[rightEyeIndex].q)); + skeleton::SkeletonPoseComputeLocalQ(apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspaceA,apSkeletonPose,rightEyeIndex,rightEyeIndex); + } + } + + int32_t goalIter; + for(goalIter = kLeftFootGoal; goalIter <= kRightHandGoal; goalIter++) + { + int32_t topIndex = apHuman->m_HumanBoneIndex[s_HumanGoalInfo[goalIter].m_TopIndex]; + int32_t midIndex = apHuman->m_HumanBoneIndex[s_HumanGoalInfo[goalIter].m_MidIndex]; + int32_t endIndex = apHuman->m_HumanBoneIndex[s_HumanGoalInfo[goalIter].m_EndIndex]; + + if(apHumanPose->m_GoalArray[goalIter].m_WeightT > 0.f) + { + float weightT = math::saturate(apHumanPose->m_GoalArray[goalIter].m_WeightT); + + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,endIndex,hipsIndex); + + // adjust len + math::float4 t = math::lerp(apSkeletonPoseWorkspaceA->m_X[endIndex].t,apHumanPose->m_GoalArray[goalIter].m_X.t, math::float1(weightT)); + skeleton::Skeleton2BoneAdjustLength(apHuman->m_Skeleton.Get(),topIndex,midIndex,endIndex,t, math::float1( (goalIter < kLeftHandGoal ? apHuman->m_LegStretch : apHuman->m_ArmStretch) * weightT),apSkeletonPose,apSkeletonPoseWorkspaceA); + + // 2 bone ik + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,endIndex,topIndex); + skeleton::Skeleton2BoneIK(apHuman->m_Skeleton.Get(),topIndex,midIndex,endIndex,apHumanPose->m_GoalArray[goalIter].m_X.t,weightT,apSkeletonPose,apSkeletonPoseWorkspaceA); + } + } + + // end rotation + for(goalIter = kLeftFootGoal; goalIter <= kRightHandGoal; goalIter++) + { + int32_t endIndex = apHuman->m_HumanBoneIndex[s_HumanGoalInfo[goalIter].m_EndIndex]; + + if(apHumanPose->m_GoalArray[goalIter].m_WeightR > 0) + { + float weightR = math::saturate(apHumanPose->m_GoalArray[goalIter].m_WeightR); + + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspaceA,endIndex,hipsIndex); + + int32_t index = apHuman->m_HumanBoneIndex[s_HumanGoalInfo[goalIter].m_Index]; + + math::float4 q = AddAxis(apHuman,index,apSkeletonPoseWorkspaceA->m_X[index].q); + + q = math::quatLerp(q,apHumanPose->m_GoalArray[goalIter].m_X.q,math::float1(weightR)); + + q = RemoveAxis(apHuman,index,q); + + ReachGoalRotation(apHuman,q,goalIter,apSkeletonPose,apSkeletonPoseWorkspaceA,apSkeletonPoseWorkspaceB); + } + } + + /* no finger ik for 4.0 + if(apHuman->m_HasLeftHand) + { + if(apHumanPose->m_LeftHandPose.m_Grab > 0) + { + hand::HandPose pose; + hand::HandPoseSolve(&apHumanPose->m_LeftHandPose,&pose); + hand::Hand2SkeletonPose(apHuman->m_LeftHand,apHuman->m_Skeleton.Get(),&pose,apSkeletonPose); + + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspace); + + hand::Hand *hand = apHuman->m_LeftHand; + + float wArray[hand::kLastFinger]; + math::float4 posArray[hand::kLastFinger]; + + hand::FingerTipsFromPose(hand,apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspace,posArray); + + for(int i = 0; i < hand::kLastFinger; i++) + { + posArray[i] = SphereCollide(apHumanPose->m_LeftHandPose.m_GrabX,posArray[i]); + wArray[i] = apHumanPose->m_LeftHandPose.m_Grab; + } + + hand::FingersIKSolve(hand,apHuman->m_Skeleton.Get(),posArray,wArray,apSkeletonPose,apSkeletonPoseWorkspace); + } + } + + if(apHuman->m_HasRightHand) + { + if(apHumanPose->m_RightHandPose.m_Grab > 0) + { + hand::HandPose pose; + hand::HandPoseSolve(&apHumanPose->m_RightHandPose,&pose); + hand::Hand2SkeletonPose(apHuman->m_RightHand,apHuman->m_Skeleton.Get(),&pose,apSkeletonPose); + + skeleton::SkeletonPoseComputeGlobal(apHuman->m_Skeleton.Get(),apSkeletonPose,apSkeletonPoseWorkspace); + + hand::Hand *hand = apHuman->m_RightHand; + + float wArray[hand::kLastFinger]; + math::float4 posArray[hand::kLastFinger]; + + hand::FingerTipsFromPose(hand,apHuman->m_Skeleton.Get(),apSkeletonPoseWorkspace,posArray); + + for(int i = 0; i < hand::kLastFinger; i++) + { + posArray[i] = SphereCollide(apHumanPose->m_RightHandPose.m_GrabX,posArray[i]); + wArray[i] = apHumanPose->m_RightHandPose.m_Grab; + } + + hand::FingersIKSolve(hand,apHuman->m_Skeleton.Get(),posArray,wArray,apSkeletonPose,apSkeletonPoseWorkspace); + } + } + */ + } + + void TwistSolve(Human const *apHuman, skeleton::SkeletonPose *apSkeletonPose, skeleton::SkeletonPose *skeletonPoseWorkspace) + { + const math::float1 foreArmTwist(apHuman->m_ForeArmTwist); + const math::float1 armTwist(apHuman->m_ArmTwist); + const math::float1 legTwist(apHuman->m_LegTwist); + const math::float1 upperLegTwist(apHuman->m_UpperLegTwist); + + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kLeftLowerArm,kLeftHand,foreArmTwist); + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kLeftUpperArm,kLeftLowerArm,armTwist); + + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kRightLowerArm,kRightHand,foreArmTwist); + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kRightUpperArm,kRightLowerArm,armTwist); + + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kLeftLowerLeg,kLeftFoot,legTwist); + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kLeftUpperLeg,kLeftLowerLeg,upperLegTwist); + + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kRightLowerLeg,kRightFoot,legTwist); + HumanFixTwist(apHuman,apSkeletonPose,skeletonPoseWorkspace,kRightUpperLeg,kRightLowerLeg,upperLegTwist); + } + + float ComputeHierarchicMass(int32_t aBoneIndex,float *apMassArray) + { + apMassArray[aBoneIndex] = HumanBoneDefaultMass[aBoneIndex]; + + for(int childIter = 0; childIter < BoneChildren[aBoneIndex][0]; childIter++) + { + apMassArray[aBoneIndex] += ComputeHierarchicMass(BoneChildren[aBoneIndex][1+childIter],apMassArray); + } + + return apMassArray[aBoneIndex]; + } + + float DeltaPoseQuality(HumanPose &arDeltaPose, float aTol) + { + float massArray[kLastBone]; + ComputeHierarchicMass(0,massArray); + + float q = 0; + float sumW = 0; + + for(int dofIter = 0; dofIter < kLastDoF; dofIter++) + { + int32_t boneIndex = DoF2Bone[dofIter]; + + float v = math::saturate((aTol - math::abs(arDeltaPose.m_DoFArray[dofIter]))/aTol); + + q += v * massArray[boneIndex]; + + sumW += massArray[boneIndex]; + } + + return q / sumW; + } + +} // namespace human + +} diff --git a/Runtime/mecanim/human/human.h b/Runtime/mecanim/human/human.h new file mode 100644 index 0000000..5f990b5 --- /dev/null +++ b/Runtime/mecanim/human/human.h @@ -0,0 +1,390 @@ +#pragma once + +#include "Runtime/mecanim/defs.h" +#include "Runtime/mecanim/memory.h" +#include "Runtime/mecanim/types.h" +#include "Runtime/mecanim/bitset.h" +#include "Runtime/Math/Simd/xform.h" +#include "Runtime/mecanim/math/axes.h" +#include "Runtime/mecanim/math/collider.h" + +#include "Runtime/mecanim/human/handle.h" +#include "Runtime/mecanim/human/hand.h" + +#include "Runtime/Serialize/Blobification/offsetptr.h" +#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h" +#include "Runtime/Animation/MecanimArraySerialization.h" + +namespace mecanim +{ + +namespace skeleton { struct Skeleton; struct SkeletonPose; } + +namespace human +{ + enum Bones + { + kHips = 0, + kLeftUpperLeg, + kRightUpperLeg, + kLeftLowerLeg, + kRightLowerLeg, + kLeftFoot, + kRightFoot, + kSpine, + kChest, + kNeck, + kHead, + kLeftShoulder, + kRightShoulder, + kLeftUpperArm, + kRightUpperArm, + kLeftLowerArm, + kRightLowerArm, + kLeftHand, + kRightHand, + kLeftToes, + kRightToes, + kLeftEye, + kRightEye, + kJaw, + kLastBone + }; + + enum BodyDoF + { + kSpineFrontBack = 0, + kSpineLeftRight, + kSpineRollLeftRight, + kChestFrontBack, + kChestLeftRight, + kChestRollLeftRight, + kLastBodyDoF + }; + + enum HeadDoF + { + kNeckFrontBack = 0, + kNeckLeftRight, + kNeckRollLeftRight, + kHeadFrontBack, + kHeadLeftRight, + kHeadRollLeftRight, + kLeftEyeDownUp, + kLeftEyeLeftRight, + kRightEyeDownUp, + kRightEyeLeftRight, + kJawDownUp, + kJawLeftRight, + kLastHeadDoF + }; + + enum LegDoF + { + kUpperLegFrontBack = 0, + kUpperLegInOut, + kUpperLegRollInOut, + kLegCloseOpen, + kLegRollInOut, + kFootCloseOpen, + kFootInOut, + kToesUpDown, + kLastLegDoF + }; + + enum ArmDoF + { + kShoulderDownUp = 0, + kShoulderFrontBack, + kArmDownUp, + kArmFrontBack, + kArmRollInOut, + kForeArmCloseOpen, + kForeArmRollInOut, + kHandDownUp, + kHandInOut, + kLastArmDoF + }; + + enum DoF + { + kBodyDoFStart = 0, + kHeadDoFStart = kBodyDoFStart + kLastBodyDoF, + kLeftLegDoFStart = kHeadDoFStart + kLastHeadDoF, + kRightLegDoFStart = kLeftLegDoFStart + kLastLegDoF, + kLeftArmDoFStart = kRightLegDoFStart + kLastLegDoF, + kRightArmDoFStart = kLeftArmDoFStart + kLastArmDoF, + kLastDoF = kRightArmDoFStart + kLastArmDoF + }; + + enum Goal + { + kLeftFootGoal, + kRightFootGoal, + kLeftHandGoal, + kRightHandGoal, + kLastGoal + }; + + struct GoalInfo + { + int32_t m_Index; + int32_t m_TopIndex; + int32_t m_MidIndex; + int32_t m_EndIndex; + }; + + const static GoalInfo s_HumanGoalInfo[kLastGoal] = + { + { kLeftFoot, kLeftUpperLeg, kLeftLowerLeg, kLeftFoot }, + { kRightFoot, kRightUpperLeg, kRightLowerLeg, kRightFoot }, + { kLeftHand, kLeftUpperArm, kLeftLowerArm, kLeftHand }, + { kRightHand, kRightUpperArm, kRightLowerArm, kRightHand } + }; + + enum HumanPoseMaskInfo + { + kMaskRootIndex = 0, + kMaskDoFStartIndex = kMaskRootIndex + 1, + kMaskGoalStartIndex = kMaskDoFStartIndex + kLastDoF, + kMaskLeftHand = kMaskGoalStartIndex + kLastGoal, + kMaskRightHand = kMaskLeftHand + 1, + kLastMaskIndex = kMaskRightHand +1 + }; + + typedef mecanim::bitset<kLastMaskIndex> HumanPoseMask; + + bool MaskHasLegs(const HumanPoseMask& mask); + + HumanPoseMask FullBodyMask(); + + struct Human + { + DEFINE_GET_TYPESTRING(Human) + + Human(); + + math::xform m_RootX; + + OffsetPtr<skeleton::Skeleton> m_Skeleton; + OffsetPtr<skeleton::SkeletonPose> m_SkeletonPose; + OffsetPtr<hand::Hand> m_LeftHand; + OffsetPtr<hand::Hand> m_RightHand; + + uint32_t m_HandlesCount; + OffsetPtr<human::Handle> m_Handles; + + uint32_t m_ColliderCount; + OffsetPtr<math::Collider> m_ColliderArray; + + int32_t m_HumanBoneIndex[kLastBone]; + float m_HumanBoneMass[kLastBone]; + int32_t m_ColliderIndex[kLastBone]; + + + float m_Scale; + + float m_ArmTwist; + float m_ForeArmTwist; + float m_UpperLegTwist; + float m_LegTwist; + + float m_ArmStretch; + float m_LegStretch; + + float m_FeetSpacing; + + bool m_HasLeftHand; + bool m_HasRightHand; + + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER(m_RootX); + + TRANSFER(m_Skeleton); + TRANSFER(m_SkeletonPose); + TRANSFER(m_LeftHand); + TRANSFER(m_RightHand); + + TRANSFER_BLOB_ONLY(m_HandlesCount); + MANUAL_ARRAY_TRANSFER2(Handle, m_Handles, m_HandlesCount); + + TRANSFER_BLOB_ONLY(m_ColliderCount); + MANUAL_ARRAY_TRANSFER2(math::Collider, m_ColliderArray, m_ColliderCount); + + STATIC_ARRAY_TRANSFER(mecanim::int32_t, m_HumanBoneIndex, kLastBone); + STATIC_ARRAY_TRANSFER(float, m_HumanBoneMass, kLastBone); + STATIC_ARRAY_TRANSFER(mecanim::int32_t, m_ColliderIndex, kLastBone); + + TRANSFER(m_Scale); + + TRANSFER(m_ArmTwist); + TRANSFER(m_ForeArmTwist); + TRANSFER(m_UpperLegTwist); + TRANSFER(m_LegTwist); + + TRANSFER(m_ArmStretch); + TRANSFER(m_LegStretch); + + TRANSFER(m_FeetSpacing); + + TRANSFER(m_HasLeftHand); + TRANSFER(m_HasRightHand); + transfer.Align(); + } + }; + + struct HumanGoal + { + DEFINE_GET_TYPESTRING(HumanGoal) + + HumanGoal() : m_WeightT(0.0f), m_WeightR(0.0f) {}; + + math::xform m_X; + float m_WeightT; + float m_WeightR; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER(m_X); + TRANSFER(m_WeightT); + TRANSFER(m_WeightR); + } + }; + + struct HumanPose + { + DEFINE_GET_TYPESTRING(HumanPose) + + HumanPose(); + + math::xform m_RootX; + math::float4 m_LookAtPosition; + math::float4 m_LookAtWeight; + + HumanGoal m_GoalArray[kLastGoal]; + hand::HandPose m_LeftHandPose; + hand::HandPose m_RightHandPose; + + float m_DoFArray[kLastDoF]; + + template<class TransferFunction> + inline void Transfer (TransferFunction& transfer) + { + TRANSFER(m_RootX); + TRANSFER(m_LookAtPosition); + TRANSFER(m_LookAtWeight); + + STATIC_ARRAY_TRANSFER(HumanGoal, m_GoalArray, kLastGoal); + TRANSFER(m_LeftHandPose); + TRANSFER(m_RightHandPose); + + STATIC_ARRAY_TRANSFER(float, m_DoFArray, kLastDoF); + } + }; + + int32_t MuscleFromBone(int32_t boneIndex, int32_t doFIndex); + int32_t BoneFromMuscle(int32_t doFIndex); + + bool RequiredBone(uint32_t boneIndex); + const char* BoneName(uint32_t boneIndex); + const char* MuscleName(uint32_t boneIndex); + + Human* CreateHuman(skeleton::Skeleton *skeleton,skeleton::SkeletonPose *skeletonPose, uint32_t handlesCount, uint32_t colliderCount, memory::Allocator& alloc); + void DestroyHuman(Human *human, memory::Allocator& alloc); + + void HumanAdjustMass(Human *human); + void HumanSetupAxes(Human *human, skeleton::SkeletonPose const *skeletonPoseGlobal); + void HumanSetupCollider(Human *human, skeleton::SkeletonPose const *skeletonPoseGlobal); + void HumanCopyAxes(Human const *srcHuman, Human *human); + math::Axes GetAxes(Human const *human, int32_t boneIndex); + void GetMuscleRange(Human const *apHuman, int32_t aDoFIndex, float &aMin, float &aMax); + math::float4 AddAxis(Human const *human, int32_t index, math::float4 const &q); + math::float4 RemoveAxis(Human const *human, int32_t index, const math::float4 &q); + math::xform NormalizedHandleX(Human const *human, int32_t handleIndex); + + math::float4 HumanComputeBoneMassCenter(Human const *human, skeleton::SkeletonPose const *skeletonPoseGlobal, int32_t boneIndex); + math::float4 HumanComputeMassCenter(Human const *human, skeleton::SkeletonPose const *skeletonPoseGlobal); + float HumanComputeMomentumOfInertia(Human const *human, skeleton::SkeletonPose const *skeletonPoseGlobal); + math::float4 HumanComputeOrientation(Human const* human,skeleton::SkeletonPose const* apPoseGlobal); + math::xform HumanComputeRootXform(Human const* human,skeleton::SkeletonPose const* apPoseGlobal); + float HumanGetFootHeight(Human const* human, bool left); + math::float4 HumanGetFootBottom(Human const* human, bool left); + math::xform HumanGetColliderXform(Human const* human, math::xform const& x, int32_t boneIndex); + math::xform HumanSubColliderXform(Human const* human, math::xform const& x, int32_t boneIndex); + math::float4 HumanGetGoalOrientationOffset(Goal goalIndex); + + void HumanPoseClear(HumanPose& pose); + void HumanPoseCopy(HumanPose &pose,HumanPose const &poseA, bool doFOnly = false); + void HumanPoseCopy(HumanPose &pose,HumanPose const &poseA, HumanPoseMask const &humanPoseMask); + void HumanPoseAdd(HumanPose &pose,HumanPose const &poseA,HumanPose const &poseB); + void HumanPoseSub(HumanPose &pose,HumanPose const &poseA,HumanPose const &poseB); + void HumanPoseWeight(HumanPose &pose,HumanPose const &poseA, float weight); + void HumanPoseMirror(HumanPose &pose,HumanPose const &poseA); + void HumanPoseBlend(HumanPose &pose, HumanPose **poseArray, float *weightArray, uint32_t count); + void HumanPoseAddOverrideLayer(HumanPose &poseBase,HumanPose const &pose, float weight, HumanPoseMask const &humanPoseMask); + void HumanPoseAddAdditiveLayer(HumanPose &poseBase,HumanPose const &pose, float weight, HumanPoseMask const &humanPoseMask); + + void RetargetFrom( Human const *human, + skeleton::SkeletonPose const *skeletonPose, + HumanPose *humanPose, + skeleton::SkeletonPose *skeletonPoseWsRef, + skeleton::SkeletonPose *skeletonPoseWsGbl, + skeleton::SkeletonPose *skeletonPoseWsLcl, + skeleton::SkeletonPose *skeletonPoseWsWs, + int32_t maxFixIter = 5); + + void RetargetTo( Human const *human, + HumanPose const *humanPoseBase, + HumanPose const *humanPose, + const math::xform &x, + HumanPose *humanPoseOut, + skeleton::SkeletonPose *skeletonPose, + skeleton::SkeletonPose *skeletonPoseWs); + + // apSkeletonPoseWorkspace must be set to global pose before calling + void FullBodySolve(Human const *human, HumanPose const *humanPose, skeleton::SkeletonPose *skeletonPose, skeleton::SkeletonPose *skeletonPoseWorkspaceA, skeleton::SkeletonPose *skeletonPoseWorkspaceB); + void TwistSolve(Human const *human, skeleton::SkeletonPose *skeletonPose, skeleton::SkeletonPose *skeletonPoseWorkspace); + + float DeltaPoseQuality(HumanPose &deltaPose, float tolerance = 0.15f); + + skeleton::SetupAxesInfo const& GetAxeInfo(uint32_t index); + +}// namespace human + +} + +template<> +class SerializeTraits< mecanim::human::HumanPoseMask > : public SerializeTraitsBase< mecanim::human::HumanPoseMask > +{ +public: + + inline static const char* GetTypeString (value_type*) { return "HumanPoseMask"; } + inline static bool IsAnimationChannel () { return false; } + inline static bool MightContainPPtr () { return false; } + inline static bool AllowTransferOptimization () { return true; } + inline static bool IsContinousMemoryArray () { return true; } + + typedef mecanim::human::HumanPoseMask value_type; + + template<class TransferFunction> inline + static void Transfer (value_type& data, TransferFunction& transfer) + { + transfer.Transfer(data.word(0), "word0"); + if(1<value_type::Words+1) + transfer.Transfer(data.word(1), "word1"); + if(2<value_type::Words+1) + transfer.Transfer(data.word(2), "word2"); + if(3<value_type::Words+1) + transfer.Transfer(data.word(3), "word3"); + } + + static void resource_image_assign_external (value_type& data, void* begin, void* end) + { + } +}; + + |