constraints/CharacterSolver/HIK2014Solver/hikhostmb.cxx

constraints/CharacterSolver/HIK2014Solver/hikhostmb.cxx
/***************************************************************************************
Autodesk(R) Open Reality(R) Samples
(C) 2012 Autodesk, Inc. and/or its licensors
All rights reserved.
AUTODESK SOFTWARE LICENSE AGREEMENT
Autodesk, Inc. licenses this Software to you only upon the condition that
you accept all of the terms contained in the Software License Agreement ("Agreement")
that is embedded in or that is delivered with this Software. By selecting
the "I ACCEPT" button at the end of the Agreement or by copying, installing,
uploading, accessing or using all or any portion of the Software you agree
to enter into the Agreement. A contract is then formed between Autodesk and
either you personally, if you acquire the Software for yourself, or the company
or other legal entity for which you are acquiring the software.
AUTODESK, INC., MAKES NO WARRANTY, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE REGARDING THESE MATERIALS, AND MAKES SUCH MATERIALS AVAILABLE SOLELY ON AN
"AS-IS" BASIS.
IN NO EVENT SHALL AUTODESK, INC., BE LIABLE TO ANYONE FOR SPECIAL, COLLATERAL,
INCIDENTAL, OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING OUT OF PURCHASE
OR USE OF THESE MATERIALS. THE SOLE AND EXCLUSIVE LIABILITY TO AUTODESK, INC.,
REGARDLESS OF THE FORM OF ACTION, SHALL NOT EXCEED THE PURCHASE PRICE OF THE
MATERIALS DESCRIBED HEREIN.
Autodesk, Inc., reserves the right to revise and improve its products as it sees fit.
Autodesk and Open Reality are registered trademarks or trademarks of Autodesk, Inc.,
in the U.S.A. and/or other countries. All other brand names, product names, or
trademarks belong to their respective holders.
GOVERNMENT USE
Use, duplication, or disclosure by the U.S. Government is subject to restrictions as
set forth in FAR 12.212 (Commercial Computer Software-Restricted Rights) and
DFAR 227.7202 (Rights in Technical Data and Computer Software), as applicable.
Manufacturer is Autodesk, Inc., 10 Duke Street, Montreal, Quebec, Canada, H3C 2L7.
***************************************************************************************/
#include "hikhostmb.h"
#include "filterset2fbcharacter.h"
#include "orcharactersolver_hik.h"
static const double K_DEG_TO_RAD = .017453292519943295769236907684886127134428718885417; // pi/180
// HIK Utils
HIKNodeId FBBodyNodeIdToHIKNodeId(FBBodyNodeId pBodyNode)
{
if(pBodyNode >= 0 && pBodyNode < kFBLastNodeId_Old)
{
const HIKNodeId lHIKNodeId = gFBBodyNodeToHIKNodeId[pBodyNode];
// make sure it didn't change (test only in debug)
OR_HIK_ASSERT( lHIKNodeId == (int)HIKNodeIdFromNodeName( FBCharacterBodyNodeNameFromId(pBodyNode) ) );
return lHIKNodeId;
}
else
{
return LastNodeId;
}
}
int FBEffectorIdToHIKId(FBEffectorId pEffector)
{
if(pEffector != kFBInvalidEffectorId)
{
const int lHIKEffectorId = (int)pEffector; //this didn't change, we have exactly the same order
// make sure it didn't change(test only in debug)
OR_HIK_ASSERT( lHIKEffectorId == HIKEffectorIdFromEffectorName( FBCharacterEffectorNameFromId( pEffector )) );
return lHIKEffectorId;
}
return -1;
}
HIKNodeId ExtraIndexToHIKNodeId(int pExtraIndex)
{
if(pExtraIndex == LEFT_EXTRA_COLLAR)
{
}
else if(pExtraIndex == RIGHT_EXTRA_COLLAR)
{
}
else
{
return LastNodeId;
}
}
int HIKNodeIdToExtraIndex(HIKNodeId pNodeId)
{
if(pNodeId == LeftCollarExtraNodeId)
{
return LEFT_EXTRA_COLLAR;
}
else if(pNodeId == RightCollarExtraNodeId)
{
return RIGHT_EXTRA_COLLAR;
}
else
{
return -1;
}
}
HIKFloorContact FBFloorContactIDToHIKLeftHandFloor(FBFloorContactID pFloorContact)
{
switch (pFloorContact)
{
break;
break;
break;
break;
}
}
void HIKHostPropertiesInit(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost)
{
for(int lPIter = 0; lPIter < HIKLastPropertyId; lPIter++)
{
pHIKCharacterHost.GetProperty(lPIter).Get().mDefaultMode = HIKGetPropertyInfoDefaultMode(lPIter);
pHIKCharacterHost.GetProperty(lPIter).Get().mDefaultValue = HIKGetPropertyInfoDefaultValue(lPIter);
}
}
void HIKHostPropertiesFromCharacter(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost, FBCharacter* pCharacter)
{
int lIter = 0;
for(lIter = 0; lIter < HIKLastPropertyId; lIter++)
{
pHIKCharacterHost.GetProperty(lIter).Get().Init(0,0,0,1.0,false);
}
if(pCharacter != NULL)
{
for(lIter = 0; lIter < FilterSet2FBCharacterParam::mParamCount; lIter++)
{
int lId = HIKGetPropertyId(FilterSet2FBCharacterParam::GetAt(lIter).mFilterSetName);
if(lId != -1)
{
FBProperty* lModeP = FilterSet2FBCharacterParam::GetAt(lIter).mFbxCharacterPropertyModeName != NULL ? pCharacter->PropertyList.Find(FilterSet2FBCharacterParam::GetAt(lIter).mFbxCharacterPropertyModeName, false) : NULL;
FBProperty* lValueP = FilterSet2FBCharacterParam::GetAt(lIter).mFbxCharacterPropertyName != NULL ? pCharacter->PropertyList.Find(FilterSet2FBCharacterParam::GetAt(lIter).mFbxCharacterPropertyName, false) : NULL;
int lValueIndex = FilterSet2FBCharacterParam::GetAt(lIter).mIndex;
if( lId == HIKLeftUpLegRollExId ||
{
lPropUnit = HIKPropertyPercent;
}
double lValueScale = (lPropUnit == HIKPropertyPercent) ? 100.0 : 1.0;
bool lIsEnum = HIKGetPropertyInfoUnit(lId) == HIKPropertyEnum;
pHIKCharacterHost.GetProperty(lId).Get().Init(lModeP,lValueP,lValueIndex,lValueScale,lIsEnum);
}
}
}
}
static void HIKHostFromFBCharacterAndSolver(HIKHost<HIKHostNodeMB> &pHost, FBCharacter* pCharacter, FBCharacterSolver* pCharacterSolver, FBConstraint* pConstraint, bool pCtrlRigNodes, bool pSetReference)
{
OR_HIK_ASSERT(pCharacter);
OR_HIK_ASSERT(pCharacterSolver == NULL || pCharacter == (FBCharacter*)pCharacterSolver->TargetCharacter);
FBModel* lModel;
if(!pCtrlRigNodes)
{
// regular part
for ( int lCounter = kFBHipsNodeId; lCounter < kFBLastNodeId_Old; lCounter++ )
{
if(lCounter != kFBReferenceNodeId || pSetReference)
{
int lHIKId = FBBodyNodeIdToHIKNodeId((FBBodyNodeId)lCounter);
lModel = pCharacter->GetModel((FBBodyNodeId)lCounter);
if (lModel)
pHost.GetNode(lHIKId).Get().SetNode(lModel, pConstraint, (HIKNodeId)lHIKId );
else
pHost.GetNode(lHIKId).Get().Clear();
}
}
// extra bones
if(pCharacterSolver)
{
const int lExtraCount = pCharacterSolver->GetExtraBoneCount();
for( int lCounter=0; lCounter < lExtraCount; lCounter++)
{
lModel = pCharacterSolver->GetExtraBoneModelAt(lCounter);
int lHIKId = ExtraIndexToHIKNodeId(lCounter);
if (lModel)
pHost.GetNode(lHIKId).Get().SetNode(lModel, pConstraint, (HIKNodeId)lHIKId );
else
pHost.GetNode(lHIKId).Get().Clear();
}
}
}
else
{
// regular part
for ( int lCounter = kFBHipsNodeId; lCounter < kFBLastNodeId_Old; lCounter++ )
{
if(lCounter != kFBReferenceNodeId || pSetReference)
{
int lHIKId = FBBodyNodeIdToHIKNodeId((FBBodyNodeId)lCounter);
lModel = pCharacter->GetCtrlRigModel((FBBodyNodeId)lCounter);
if (lModel)
pHost.GetNode(lHIKId).Get().SetNode(lModel, pConstraint, (HIKNodeId)lHIKId );
else
pHost.GetNode(lHIKId).Get().Clear();
}
}
// extra bones
if(pCharacterSolver)
{
const int lExtraCount = pCharacterSolver->GetExtraFKCount();
for( int lCounter=0; lCounter < lExtraCount; lCounter++)
{
lModel = pCharacterSolver->GetExtraFKModelAt(lCounter);
int lHIKId = ExtraIndexToHIKNodeId(lCounter);
if (lModel)
pHost.GetNode(lHIKId).Get().SetNode(lModel, pConstraint, (HIKNodeId)lHIKId );
else
pHost.GetNode(lHIKId).Get().Clear();
}
}
}
}
static void HIKCharacterHostFloorContactsFromFBCharacter(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost, FBCharacter* pCharacter)
{
FBModel* lModel;
for(int lFloorId = FBLeftFootMemberIndex; lFloorId < FBLastCharacterMember; lFloorId++)
{
HIKFloorContact lHIKFloorId = FBFloorContactIDToHIKLeftHandFloor((FBFloorContactID)lFloorId);
lModel = pCharacter->GetFloorContactModel((FBFloorContactID)lFloorId);
if(lModel)
pHIKCharacterHost.GetFloorNode(lHIKFloorId).Get().SetNode(lModel,NULL);
else
pHIKCharacterHost.GetFloorNode(lHIKFloorId).Get().Clear();
}
}
void HIKCharacterHostFromFBCharacter(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost, FBCharacter* pCharacter, bool pFloorContacts)
{
// floor contacts
if(pFloorContacts)
{
HIKCharacterHostFloorContactsFromFBCharacter(pHIKCharacterHost, pCharacter);
}
// regular and extra character part
HIKHostFromFBCharacterAndSolver(pHIKCharacterHost, pCharacter, pCharacter->GetExternalSolver(), NULL, false, true); //kxl: this reference part is unclear
}
void HIKCharacterHostFromFBCharacterSolver(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost, FBCharacterSolver* pCharacterSolver, FBConstraint* pConstraint, bool pFloorContacts)
{
FBCharacter* lCharacter = pCharacterSolver->TargetCharacter;
// floor contacts
if(pFloorContacts)
{
HIKCharacterHostFloorContactsFromFBCharacter(pHIKCharacterHost, lCharacter);
}
// regular and extra character part
HIKHostFromFBCharacterAndSolver(pHIKCharacterHost, lCharacter, pCharacterSolver, pConstraint, false, true);
}
void HIKControlRigHostFromFBCharacterSolver(HIKControlRigHost<HIKHostNodeMB> &pHIKControlRigHost, FBCharacterSolver* pCharacterSolver, FBControlSet* pControlSet, FBConstraint* pConstraint)
{
FBModel* lModel;
FBCharacter* lCharacter = pCharacterSolver->TargetCharacter;
// regular and extra character part
HIKHostFromFBCharacterAndSolver(pHIKControlRigHost, lCharacter, pCharacterSolver, pConstraint, true, true);
// effectors
for(int lIKIter = kFBHipsEffectorId; lIKIter < kFBLastEffectorId; lIKIter++)
{
int lPivotCount = pControlSet->GetIKEffectorPivotCount((FBEffectorId)lIKIter);
for(int lPivotIter = 0; lPivotIter < FBLastEffectorSetIndex; lPivotIter++)
{
lModel = lPivotIter < lPivotCount ? pControlSet->GetIKEffectorModel((FBEffectorId)lIKIter, lPivotIter) : NULL;
if(lModel != NULL && lModel->GetHIObject() != NULL) // Make sure lModel is valid.
{
pHIKControlRigHost.GetEffector(lIKIter,lPivotIter).Get().SetNode(lModel,pConstraint, (HIKEffectorId)lIKIter);
}
else
{
pHIKControlRigHost.GetEffector(lIKIter,lPivotIter).Get().Clear();
}
}
}
}
void HIKCharacterHostFromFBCharacterPose(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost, FBCharacter* pPoseCharacter, FBCharacterPose* pPose)
{
OR_HIK_ASSERT(pPoseCharacter && pPose);
// regular part
HIKHostFromFBCharacterAndSolver(pHIKCharacterHost, pPoseCharacter, NULL, NULL, false, true);
// extra part
FBModel* lModel;
const int lExtraCount = pPose->GetExtraBoneCount();
for( int lCounter=0; lCounter < lExtraCount; lCounter++)
{
lModel = pPose->GetExtraBoneModelAt(lCounter);
int lHIKId = ExtraIndexToHIKNodeId(lCounter);
if (lModel)
pHIKCharacterHost.GetNode(lHIKId).Get().SetNode(lModel, NULL);
else
pHIKCharacterHost.GetNode(lHIKId).Get().Clear();
}
}
static void CopyCharacterization( HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost, HIKCharacter *pHIKCharacter, HIKNodeId pNodeId,
FBTVector &pT, FBRVector &pR, FBVector4d &pS, FBRVector &pPROffset )
{
OR_HIK_ASSERT(pHIKCharacterHost.GetNode(pNodeId).Valid());
HIKSetCharacterizeNodeStateTQSdv(pHIKCharacter,pNodeId,pT.mValue,lQ.mValue,pS.mValue);
pHIKCharacterHost.TransfertRotationsAndLimits(pHIKCharacter, pNodeId, true);
if ( !pHIKCharacterHost.IsParentDirect(pNodeId) )
{
FBTVector lParentTOffset;
FBQuaternion lParentQOffset;
FBVector4d lParentSOffset;
lParentTOffset.Init(); lParentTOffset.mValue[3] = 1.0;
FBRotationToQuaternion(lParentQOffset, pPROffset);
lParentSOffset[0] = lParentSOffset[1] = lParentSOffset[2] = lParentSOffset[3] = 1.0;
HIKSetParentOffsetdv(pHIKCharacter,LeftCollarExtraNodeId,lParentTOffset.mValue,lParentQOffset.mValue,lParentSOffset.mValue);
}
}
static void CopyCharacterization( HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost, HIKCharacter *pHIKCharacter,
FBCharacter* pCharacter, FBCharacterSolver* pCharacterSolver, FBCharacterPose* pCharacterPose,
HIKNodeId pNodeId, FBBodyNodeId pBodyNodeId = kFBLastNodeId_Old )
{
OR_HIK_ASSERT(pCharacter);
OR_HIK_ASSERT(pCharacterSolver == NULL || pCharacter == (FBCharacter*)pCharacterSolver->TargetCharacter);
OR_HIK_ASSERT(pHIKCharacterHost.GetNode(pNodeId).Valid());
FBRVector lPROffset;
// regular node
if(pBodyNodeId != kFBLastNodeId_Old)
{
pCharacter->GetTOffset(pBodyNodeId, &lT);
pCharacter->GetROffset(pBodyNodeId, &lR);
pCharacter->GetSOffset(pBodyNodeId, (FBSVector*)&lS);
pCharacter->GetParentROffset(pBodyNodeId, &lPROffset);
CopyCharacterization(pHIKCharacterHost, pHIKCharacter, pNodeId, lT, lR, lS, lPROffset );
}
else if(pCharacterSolver)
{
int lExtraIndex = HIKNodeIdToExtraIndex(pNodeId);
if(lExtraIndex != -1)
{
pCharacterSolver->GetTransformOffset(*(FBVector3d*)&lT, lR, *(FBSVector*)&lS, lExtraIndex);
pCharacterSolver->GetParentRotationOffset(lPROffset, lExtraIndex);
CopyCharacterization(pHIKCharacterHost, pHIKCharacter, pNodeId, lT, lR, lS, lPROffset );
}
else
{
OR_HIK_ASSERT(false);
}
}
else if(pCharacterPose)
{
int lExtraIndex = HIKNodeIdToExtraIndex(pNodeId);
if(lExtraIndex != -1)
{
pCharacterPose->GetExtraBoneTransformOffset(*(FBVector3d*)&lT, lR, *(FBSVector*)&lS, lExtraIndex);
pCharacterPose->GetExtraBoneParentRotationOffset(lPROffset, lExtraIndex);
CopyCharacterization(pHIKCharacterHost, pHIKCharacter, pNodeId, lT, lR, lS, lPROffset );
}
}
}
static void HIKCharacterFromFBCharacterAndSolver( HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost,HIKCharacter*& pHIKCharacter,
FBCharacter* pCharacter, FBCharacterSolver* pCharacterSolver, FBCharacterPose* pCharacterPose )
{
OR_HIK_ASSERT(pHIKCharacter == NULL); //we initialize character in here
OR_HIK_ASSERT(pCharacter);
OR_HIK_ASSERT(pCharacterSolver == NULL || pCharacter == (FBCharacter*)pCharacterSolver->TargetCharacter);
pHIKCharacter = pHIKCharacterHost.CharacterCreate(&malloc);
// Regular FBCharacter nodes
for ( int lCounter = kFBHipsNodeId; lCounter < kFBLastNodeId_Old; lCounter++ )
{
int lHIKId = FBBodyNodeIdToHIKNodeId((FBBodyNodeId)lCounter);
if(pHIKCharacterHost.GetNode(lHIKId).Valid())
{
CopyCharacterization(pHIKCharacterHost, pHIKCharacter, pCharacter, pCharacterSolver, NULL, (HIKNodeId)lHIKId, (FBBodyNodeId)lCounter);
}
}
// Extra nodes
if(pCharacterSolver || pCharacterPose)
{
if(pHIKCharacterHost.GetNode(LeftCollarExtraNodeId).Valid())
{
CopyCharacterization(pHIKCharacterHost, pHIKCharacter, pCharacter, pCharacterSolver, pCharacterPose, LeftCollarExtraNodeId);
}
if(pHIKCharacterHost.GetNode(RightCollarExtraNodeId).Valid())
{
CopyCharacterization(pHIKCharacterHost, pHIKCharacter, pCharacter, pCharacterSolver, pCharacterPose, RightCollarExtraNodeId);
}
}
// characterize
HIKCharacterizeGeometry(pHIKCharacter);
HIKInverseJoint(pHIKCharacter,HIKLeftKnee, pCharacter->InverseLeftKnee);
HIKInverseJoint(pHIKCharacter,HIKRightKnee, pCharacter->InverseRightKnee);
HIKInverseJoint(pHIKCharacter,HIKLeftElbow, pCharacter->InverseLeftElbow);
HIKInverseJoint(pHIKCharacter,HIKRightElbow, pCharacter->InverseRightElbow);
}
void HIKCharacterFromFBCharacter(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost,HIKCharacter*& pHIKCharacter,FBCharacter* pCharacter)
{
HIKCharacterFromFBCharacterAndSolver(pHIKCharacterHost, pHIKCharacter, pCharacter, pCharacter->GetExternalSolver(), NULL);
}
void HIKCharacterFromFBCharacterSolver(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost,HIKCharacter*& pHIKCharacter,FBCharacterSolver* pCharacterSolver)
{
FBCharacter* lCharacter = pCharacterSolver->TargetCharacter;
HIKCharacterFromFBCharacterAndSolver(pHIKCharacterHost, pHIKCharacter, lCharacter, pCharacterSolver, NULL);
}
void HIKCharacterFromFBActor(HIKCharacter*& pHIKActorCharacter, FBActor* pActor)
{
for(int lNodeIter = 0; lNodeIter < LastNodeId; lNodeIter++)
{
lHIKDef.mUsedNodes[lNodeIter] = HIKNodeNotUsed;
}
for(int lActorIter = kFBSkeletonHipsIndex; lActorIter < kFBSkeletonLastIndex; lActorIter++)
{
lHIKDef.mUsedNodes[gActor2HIK[lActorIter]] |= HIKNodeUsed;
}
pHIKActorCharacter = HIKCharacterCreate(&lHIKDef,&malloc,AutodeskCustomerString);
FBSkeletonState* lSkeletonState = pActor->GetDefaultSkeletonState();
if (lSkeletonState)
{
for(int lActorIter = kFBSkeletonHipsIndex; lActorIter < kFBSkeletonLastIndex; lActorIter++)
{
FBMatrix lGX;
FBSVector lGS;
pActor->GetDefinitionScaleVector((FBSkeletonNodeId)lActorIter, lGS);
lSkeletonState->GetNodeMatrix((FBSkeletonNodeId)lActorIter, lGX);
FBMult(lGX,lGX,lGS);
HIKSetCharacterizeNodeStatedv(pHIKActorCharacter,gActor2HIK[lActorIter], (double*)lGX);
}
}
HIKCharacterizeGeometry(pHIKActorCharacter);
}
void HIKCharacterFromFBCharacterPose(HIKCharacterHost<HIKHostNodeMB,HIKHostPropertyMB> &pHIKCharacterHost,HIKCharacter*& pHIKCharacter,FBCharacter* pPoseCharacter, FBCharacterPose* pPose)
{
HIKCharacterFromFBCharacterAndSolver(pHIKCharacterHost, pHIKCharacter, pPoseCharacter, NULL, pPose);
}
int GetSolvingStepBasedOnActivePart(int pIndex)
{
int lSolvingStep = 0;
switch(pIndex)
{
case kFBCtrlSetPartChest: lSolvingStep = HIKSolvingStepSpine; break;
case kFBCtrlSetPartLeftArm: lSolvingStep = HIKSolvingStepLeftArm; break;
case kFBCtrlSetPartRightArm: lSolvingStep = HIKSolvingStepRightArm; break;
case kFBCtrlSetPartLeftLeg: lSolvingStep = HIKSolvingStepLeftLeg; break;
case kFBCtrlSetPartRightLeg: lSolvingStep = HIKSolvingStepRightLeg; break;
case kFBCtrlSetPartHead: lSolvingStep = HIKSolvingStepHead; break;
case kFBCtrlSetPartLeftHand: lSolvingStep = HIKSolvingStepLeftHand; break;
case kFBCtrlSetPartRightHand: lSolvingStep = HIKSolvingStepRightHand; break;
case kFBCtrlSetPartLeftFoot: lSolvingStep = HIKSolvingStepLeftFoot; break;
case kFBCtrlSetPartRightFoot: lSolvingStep = HIKSolvingStepRightFoot; break;
default: break;
}
return lSolvingStep;
}
void SetNormalizedNodeStateForHierarchy( HIKCharacter *pHIKCharacter, HIKCharacterState *pState, KHIKNodeState pDataSet[LastNodeId], HIKNodeId pNodeId,
FBTVector *pT, FBQuaternion *pQ, FBVector4d *pS, bool pGlobal )
{
OR_HIK_ASSERT(pT != NULL || pQ != NULL || pS != NULL);
int lNodeIdDesc[LastNodeId + 1];
HIKFillCharacterDescription(pHIKCharacter, lNodeIdDesc);
HIKDataDescription lDescription = {
HIKDataDescription::HIKLocalSpace,
offsetof(KHIKNodeState, mTfv),
offsetof(KHIKNodeState, mQfv),
offsetof(KHIKNodeState, mSfv),
sizeof(KHIKNodeState),
lNodeIdDesc
};
HIKGetNormalizedCharacterStateTransformTQS( pHIKCharacter, pState, &lDescription, pDataSet);
int lParentNodeId = HIKGetParentNodeId(pHIKCharacter, (int)pNodeId);
if(pGlobal && lParentNodeId != -1)
{
// get parent state
FBMatrix lPGX;
HIKGetNodeNormalizedStatedv( pHIKCharacter, pState, lParentNodeId, (double*)lPGX );
// get node state
HIKGetNodeNormalizedStateTQSdv( pHIKCharacter, pState, pNodeId, lT.mValue, lQ.mValue, lS.mValue );
// update transforms that were given
if(pT) lT = *pT;
if(pQ) lQ = *pQ;
if(pS) lS = *pS;
// compute local (since we don't have all required quaternion computations, we have to do it with matrix)
FBMatrix lGX;
FBRVector lRV;
FBTRSToMatrix(lGX, lT, lRV, *(FBSVector*)&lS);
FBMatrix lLX;
FBGetLocalMatrix(lLX, lPGX, lGX);
// compute T Q S from local matrix - watch out, we reuse already allocated variables
FBMatrixToTRS(lT, lRV, *(FBSVector*)&lS, lLX);
if(pT)
{
pDataSet[pNodeId].mTfv[0] = lT.mValue[0];
pDataSet[pNodeId].mTfv[1] = lT.mValue[1];
pDataSet[pNodeId].mTfv[2] = lT.mValue[2];
pDataSet[pNodeId].mTfv[3] = lT.mValue[3];
}
if(pQ)
{
pDataSet[pNodeId].mQfv[0] = lQ.mValue[0];
pDataSet[pNodeId].mQfv[1] = lQ.mValue[1];
pDataSet[pNodeId].mQfv[2] = lQ.mValue[2];
pDataSet[pNodeId].mQfv[3] = lQ.mValue[3];
}
if(pS)
{
pDataSet[pNodeId].mSfv[0] = lS.mValue[0];
pDataSet[pNodeId].mSfv[1] = lS.mValue[1];
pDataSet[pNodeId].mSfv[2] = lS.mValue[2];
pDataSet[pNodeId].mSfv[3] = 1;
}
}
else
{
if(pT)
{
pDataSet[pNodeId].mTfv[0] = pT->mValue[0];
pDataSet[pNodeId].mTfv[1] = pT->mValue[1];
pDataSet[pNodeId].mTfv[2] = pT->mValue[2];
pDataSet[pNodeId].mTfv[3] = pT->mValue[3];
}
if(pQ)
{
pDataSet[pNodeId].mQfv[0] = pQ->mValue[0];
pDataSet[pNodeId].mQfv[1] = pQ->mValue[1];
pDataSet[pNodeId].mQfv[2] = pQ->mValue[2];
pDataSet[pNodeId].mQfv[3] = pQ->mValue[3];
}
if(pS)
{
pDataSet[pNodeId].mSfv[0] = pS->mValue[0];
pDataSet[pNodeId].mSfv[1] = pS->mValue[1];
pDataSet[pNodeId].mSfv[2] = pS->mValue[2];
pDataSet[pNodeId].mSfv[3] = 1;
}
}
HIKSetNormalizedCharacterStateTransformTQS(pHIKCharacter, pState, &lDescription, pDataSet);
}
void ResetControRigModelTransformation( HIKCharacter *pHIKCharacter, HIKEvaluationState* pStanceState, HIKNodeId pNodeId, FBModel* pModel )
{
FBTVector lLT;
FBRVector lLR;
int lNodeIdDesc[LastNodeId + 1];
HIKFillCharacterDescription(pHIKCharacter, lNodeIdDesc);
HIKDataDescription lDescription = {
HIKDataDescription::HIKLocalSpace,
offsetof(KHIKNodeState, mTfv),
offsetof(KHIKNodeState, mQfv),
offsetof(KHIKNodeState, mSfv),
sizeof(KHIKNodeState),
lNodeIdDesc
};
HIKGetNormalizedCharacterStateTransformTQS( pHIKCharacter, pStanceState->mState, &lDescription, pStanceState->mDataSet);
lLT.mValue[0] = pStanceState->mDataSet[pNodeId].mTfv[0];
lLT.mValue[1] = pStanceState->mDataSet[pNodeId].mTfv[1];
lLT.mValue[2] = pStanceState->mDataSet[pNodeId].mTfv[2];
lLT.mValue[3] = pStanceState->mDataSet[pNodeId].mTfv[3];
lLQ.mValue[0] = pStanceState->mDataSet[pNodeId].mQfv[0];
lLQ.mValue[1] = pStanceState->mDataSet[pNodeId].mQfv[1];
lLQ.mValue[2] = pStanceState->mDataSet[pNodeId].mQfv[2];
lLQ.mValue[3] = pStanceState->mDataSet[pNodeId].mQfv[3];
lLS.mValue[0] = pStanceState->mDataSet[pNodeId].mSfv[0];
lLS.mValue[1] = pStanceState->mDataSet[pNodeId].mSfv[1];
lLS.mValue[2] = pStanceState->mDataSet[pNodeId].mSfv[2];
lLS.mValue[3] = pStanceState->mDataSet[pNodeId].mSfv[3];
//pModel->SetVector(*(FBVector3d*)&lLT, kModelTranslation, false);
//pModel->SetVector(*(FBVector3d*)&lLR, kModelRotation, false);
//pModel->SetVector(*(FBVector3d*)&lLS, kModelScaling, false);
pModel->Translation = *(FBVector3d*)&lLT;
pModel->Rotation = *(FBVector3d*)&lLR;
pModel->Scaling = *(FBVector3d*)&lLS;
}
bool GetNodeIdOrEffectIdFromModel( FBCharacterSolver* pSolver, FBModel* pModel, int& pHIKNodeId, int& pHIKEffectorId, FBEffectorId& pEffectorId, FBEffectorSetID& pPivotIndex )
{
// make sure output is reset
pHIKNodeId = -1;
pHIKEffectorId = -1;
pEffectorId = kFBInvalidEffectorId;
pPivotIndex = FBEffectorSetDefault;
// get character
FBCharacter* lCharacter = pSolver->TargetCharacter;
OR_HIK_ASSERT(lCharacter && pSolver);
// check skeleton bone
int lBodyNodeId = lCharacter->GetIndexByModel( pModel );
if(lBodyNodeId != kFBInvalidNodeId)
{
pHIKNodeId = FBBodyNodeIdToHIKNodeId((FBBodyNodeId)lBodyNodeId);
return true;
}
// check for extra bones
const int lExtraBoneCount = pSolver->GetExtraBoneCount();
for(int i = 0; i < lExtraBoneCount; i++)
{
if(pSolver->GetExtraBoneModelAt(i) == pModel)
{
pHIKNodeId = ExtraIndexToHIKNodeId(i);
return true;
}
}
// control rig bone
lBodyNodeId = lCharacter->GetCtrlRigIndexByModel( pModel );
if(lBodyNodeId != kFBInvalidNodeId)
{
pHIKNodeId = FBBodyNodeIdToHIKNodeId((FBBodyNodeId)lBodyNodeId);
return true;
}
// check for extra bones
const int lExtraFKCount = pSolver->GetExtraFKCount();
for(int i = 0; i < lExtraFKCount; i++)
{
if(pSolver->GetExtraFKModelAt(i) == pModel)
{
pHIKNodeId = ExtraIndexToHIKNodeId(i);
return true;
}
}
OR_HIK_ASSERT(lExtraBoneCount == lExtraFKCount);
// check effectors
for(int i = 0; i < kFBLastEffectorId; i++)
{
for(int j = 0; j < FBLastEffectorSetIndex; j++)
{
if(lCharacter->GetEffectorModel((FBEffectorId)i, (FBEffectorSetID)j) == pModel)
{
pEffectorId = (FBEffectorId)i;
pPivotIndex = (FBEffectorSetID)j;
pHIKEffectorId = FBEffectorIdToHIKId(pEffectorId);
return true;
}
}
}
return false;
}
// HIKHostNodeMB
AnimationNode_Id::AnimationNode_Id()
{
mId = 0;
}
AnimationNode_Id::AnimationNode_Id(const AnimationNode_Id &pSource)
{
mId = pSource.mId;
}
AnimationNode_Id::AnimationNode_Id(const int pSource)
{
mId = pSource;
}
AnimationNode_Id::AnimationNode_Id(HIKEffectorId pId)
{
mId = ((pId+1) << 11) | 1;
OR_HIK_ASSERT( IsValidEffectorId() && (GetEffectorId() == pId) && IsValidNodeId() == false );
OR_HIK_ASSERT( IsValidType() == false );
}
AnimationNode_Id::AnimationNode_Id(HIKNodeId pId)
{
int lEffectorId = HIKNodeIdToHIKEffectorId_LastInChain((HIKNodeId)pId) & 0x3FF/*(10 bits)*/;
mId = ((lEffectorId+1) << 11) | ((pId+1) << 1) | 1;
OR_HIK_ASSERT( IsValidNodeId() && (GetEffectorId() == lEffectorId) && (GetNodeId() == pId));
OR_HIK_ASSERT( IsValidType() == false );
}
HIKHostNodeMB::HIKHostNodeMB()
{
Clear();
}
void HIKHostNodeMB::SetNode(FBModel *pNode, FBConstraint *pConstraint, AnimationNode_Id pConnectorId)
{
OR_HIK_ASSERT(pNode);
Clear();
mNode = pNode;
if(pNode->Is(FBModelMarker::TypeInfo))
{
FBModelMarker* lMarker = FBCast<FBModelMarker>(pNode);
if(lMarker && lMarker->Type==kFBMarkerTypeIKEffector)
{
mReachT = mNode->PropertyList.Find("IK Reach Translation",false);
mReachR = mNode->PropertyList.Find("IK Reach Rotation",false);
}
}
if(pConstraint != NULL)
{
FBAnimationNode *lAnimationNode = pConstraint->AnimationNodeInGet();
if (lAnimationNode)
{
mDestTConn = pConstraint->AnimationNodeInCreate(pConnectorId.GetIdWithType(kModelTranslation), mNode, ANIMATIONNODE_TYPE_TRANSLATION);
mDestRConn = pConstraint->AnimationNodeInCreate(pConnectorId.GetIdWithType(kModelRotation), mNode, ANIMATIONNODE_TYPE_ROTATION);
//(kxl) Internal solver doesn't constraint scale for effectors!
//if(!pConnectorId.IsValid() || pConnectorId.IsValidNodeId())
{
mDestSConn = pConstraint->AnimationNodeInCreate(pConnectorId.GetIdWithType(kModelScaling), mNode, ANIMATIONNODE_TYPE_SCALING);
}
}
}
}
void HIKHostNodeMB::Clear()
{
mNode = NULL;
mDestTConn = NULL;
mDestRConn = NULL;
mDestSConn = NULL;
mReachT = NULL;
mReachR = NULL;
}
bool HIKHostNodeMB::IsDestinationConn(FBAnimationNode* pConnector)
{
return pConnector &&
(( mDestTConn && mDestTConn->GetHIObject() == pConnector->GetHIObject() )
|| ( mDestRConn && mDestRConn->GetHIObject() == pConnector->GetHIObject() )
|| ( mDestSConn && mDestSConn->GetHIObject() == pConnector->GetHIObject() ));
}
// HIKHostPropertyMB
HIKHostPropertyMB::HIKHostPropertyMB()
{
mDefaultMode = 0;
mDefaultValue = 0.0;
mModeP = 0;
mValueP = 0;
mValueIndex = 0;
mValueScale = 1.0;
mIsEnum = false;
}
void HIKHostPropertyMB::Init(FBProperty *pModeP, FBProperty *pValueP,int pValueIndex,double pValueScale,bool pIsEnum)
{
mModeP = pModeP;
mValueP = pValueP;
mValueIndex = pValueIndex;
mValueScale = pValueScale;
mIsEnum = pIsEnum;
}
// HIKHostNode<HIKHostNodeMB>
static double dClamp(double x, double lMin, double lMax)
{
return (x < lMin) ? lMin : ((x > lMax) ? lMax : x);
}
template <>
bool HIKHostNode<HIKHostNodeMB>::Valid()
{
FBModel *lModel = Get().mNode;
bool lValid = (lModel != NULL) && (lModel->GetHIObject() != NULL);
return lValid;
}
template <>
void HIKHostNode<HIKHostNodeMB>::ReadXForm(double *pXForm, FBEvaluateInfo* pEvalInfo)
{
FBMatrix *lMatrix = reinterpret_cast<FBMatrix *>(pXForm);
lMatrix->Identity();
if(Valid())
{
Get().mNode->GetMatrix(*lMatrix, kModelTransformation, true, pEvalInfo);
}
}
template <>
void HIKHostNode<HIKHostNodeMB>::WriteXForm(double *pXForm, FBEvaluateInfo* pEvalInfo)
{
if(Valid())
{
FBSVector lS;
FBMatrixToTRS(lT,lR,lS,*reinterpret_cast<FBMatrix *>(pXForm));
if(Get().mDestTConn != NULL) Get().mDestTConn->WriteData(lT,pEvalInfo);
if(Get().mDestRConn != NULL) Get().mDestRConn->WriteData(lR,pEvalInfo);
if(Get().mDestSConn != NULL) Get().mDestSConn->WriteData(lS,pEvalInfo);
}
}
template <>
void HIKHostNode<HIKHostNodeMB>::WriteXFormCandidate(double *pXForm, FBEvaluateInfo* pEvalInfo)
{
if(Valid())
{
Get().mNode->SetMatrix( *reinterpret_cast<FBMatrix *>(pXForm), kModelTransformation, true, false, pEvalInfo);
}
}
template <>
void HIKHostNode<HIKHostNodeMB>::ReadTQS(FBTVector &pT, FBQuaternion &pQ, FBVector4d &pS, FBEvaluateInfo* pEvalInfo)
{
if(Valid())
{
Get().mNode->GetVector(*(FBVector3d*)&pT, kModelTranslation, true, pEvalInfo);
Get().mNode->GetVector(*(FBVector3d*)&lR, kModelRotation, true, pEvalInfo);
Get().mNode->GetVector(*(FBVector3d*)&pS, kModelScaling, true, pEvalInfo);
pS.mValue[3]=1;
}
else
{
pT.Init();
pQ.Init();
pS.mValue[0]=pS.mValue[1]=pS.mValue[2]=pS.mValue[3]=1;
}
}
template <>
int HIKHostNode<HIKHostNodeMB>::IsEvaluationRecursiveTQS(FBEvaluateInfo* pEvalInfo)
{
int lRecursiveNodes = eNoRecursion;
if(Valid())
{
if(Get().mNode->Translation.GetAnimationNode() && Get().mNode->Translation.GetAnimationNode()->IsEvaluationRecursive(pEvalInfo))
{
lRecursiveNodes |= eRecursiveT;
}
if(Get().mNode->Rotation.GetAnimationNode() && Get().mNode->Rotation.GetAnimationNode()->IsEvaluationRecursive(pEvalInfo))
{
lRecursiveNodes |= eRecursiveR;
}
if(Get().mNode->Scaling.GetAnimationNode() && Get().mNode->Scaling.GetAnimationNode()->IsEvaluationRecursive(pEvalInfo))
{
lRecursiveNodes |= eRecursiveS;
}
}
return lRecursiveNodes;
}
template <>
void HIKHostNode<HIKHostNodeMB>::WriteTQS(FBTVector &pT, FBQuaternion &pQ, FBVector4d &pS, FBEvaluateInfo* pEvalInfo)
{
if(Valid())
{
if(Get().mDestTConn != NULL) Get().mDestTConn->WriteData(pT.mValue,pEvalInfo);
if(Get().mDestRConn != NULL) Get().mDestRConn->WriteData(lR.mValue,pEvalInfo);
if(Get().mDestSConn != NULL) Get().mDestSConn->WriteData(pS.mValue,pEvalInfo);
}
}
template <>
void HIKHostNode<HIKHostNodeMB>::WriteTQSIfNotRecursive(FBTVector &pT, FBQuaternion &pQ, FBVector4d &pS, FBEvaluateInfo* pEvalInfo, int &pRecursivityInfo)
{
if(Valid())
{
if(Get().mDestTConn != NULL)
{
if((pRecursivityInfo & eRecursiveT) > 0 )
{
Get().mDestTConn->DisableIfNotWritten(pEvalInfo);
}
else
{
Get().mDestTConn->WriteData(pT.mValue,pEvalInfo);
}
}
if(Get().mDestRConn != NULL)
{
if((pRecursivityInfo & eRecursiveR) > 0 )
{
Get().mDestRConn->DisableIfNotWritten(pEvalInfo);
}
else
{
Get().mDestRConn->WriteData(lR.mValue,pEvalInfo);
}
}
if(Get().mDestSConn != NULL)
{
if((pRecursivityInfo & eRecursiveS) > 0 )
{
Get().mDestSConn->DisableIfNotWritten(pEvalInfo);
}
else
{
Get().mDestSConn->WriteData(pS.mValue,pEvalInfo);
}
}
}
}
template <>
void HIKHostNode<HIKHostNodeMB>::WriteCandidateTQS(const FBTVector &pT, const FBQuaternion &pQ, const FBVector4d &pS, FBEvaluateInfo* pEvalInfo)
{
if(Valid())
{
Get().mNode->SetVector( *(FBVector3d*)&pT, kModelTranslation, true, false, pEvalInfo);
Get().mNode->SetVector( *(FBVector3d*)&lR, kModelRotation, true, false, pEvalInfo);
Get().mNode->SetVector( *(FBVector3d*)&pS, kModelScaling, true, false, pEvalInfo);
}
}
template <>
void HIKHostNode<HIKHostNodeMB>::SetCandidateTQS(FBTVector &pT, FBQuaternion &pQ, FBVector4d &pS, FBEvaluateInfo* pEvalInfo)
{
if(Valid())
{
Get().mNode->Translation.SetGlobalCandidate( pT.mValue, sizeof(pT), pEvalInfo);
Get().mNode->Rotation.SetGlobalCandidate( lR.mValue, sizeof(lR), pEvalInfo);
Get().mNode->Scaling.SetGlobalCandidate( pS.mValue, sizeof(lR), pEvalInfo);
}
}
template <>
double HIKHostNode<HIKHostNodeMB>::ReadReachT( FBEvaluateInfo* pEvalInfo )
{
double lRet = 0.0;
if(Valid())
{
if(Get().mReachT != NULL)
{
double lValue = 0;
Get().mReachT->GetData(&lValue, sizeof(lValue), pEvalInfo);
lRet = dClamp( lValue/100.0, 0.0, 1.0);
}
}
return lRet;
}
template <>
double HIKHostNode<HIKHostNodeMB>::ReadReachR( FBEvaluateInfo* pEvalInfo )
{
double lRet = 0.0;
if(Valid())
{
if(Get().mReachR != NULL)
{
double lValue = 0;
Get().mReachR->GetData(&lValue, sizeof(lValue), pEvalInfo);
lRet = dClamp( lValue/100.0, 0.0, 1.0);
}
}
return lRet;
}
template <>
void HIKHostNode<HIKHostNodeMB>::ReadIKPivot(double *pIKPivot, FBEvaluateInfo* pEvalInfo )
{
FBTVector *lVector = reinterpret_cast<FBTVector *>(pIKPivot);
lVector->Init();
if(Valid())
{
FBModelMarker* lMarker = dynamic_cast<FBModelMarker*>(Get().mNode);
if(lMarker != NULL)
{
lMarker->IKPivot.GetData(lVector, sizeof(lVector), pEvalInfo );
}
}
}
template <>
bool HIKHostNode<HIKHostNodeMB>::GetIKSync()
{
bool lIKSync = false;
if(Valid())
{
FBModelMarker* lMarker = dynamic_cast<FBModelMarker*>(Get().mNode);
if(lMarker != NULL)
{
lIKSync = lMarker->IKSync;
}
}
return lIKSync;
}
template <>
void HIKHostNode<HIKHostNodeMB>::GetVector(FBVector3d &retVector, FBModelTransformationType pWhat, bool pGlobalInfo, FBEvaluateInfo* pEvalInfo )
{
if(Valid())
{
mNode.mNode->GetVector(retVector,pWhat,pGlobalInfo,pEvalInfo);
}
else
{
if(pWhat == kModelScaling)
retVector[0]=retVector[1]=retVector[2]=1;
else
retVector.Init();
}
}
template <>
bool HIKHostNode<HIKHostNodeMB>::GetUseTranslationLimits()
{
bool lRet = false;
if( Valid() && mNode.mNode->TranslationActive )
{
lRet = true;
}
return lRet;
}
template <>
bool HIKHostNode<HIKHostNodeMB>::GetUseRotationLimits()
{
bool lRet = false;
if( Valid() && mNode.mNode->RotationActive )
{
lRet = true;
}
return lRet;
}
template <>
int HIKHostNode<HIKHostNodeMB>::GetRotationOrder()
{
int lRet = HIKOrderEulerXYZ;
if(Valid() && mNode.mNode->RotationActive )
{
lRet = mNode.mNode->RotationOrder * 2;
}
return lRet;
}
template <>
void HIKHostNode<HIKHostNodeMB>::GetPreQ(double *pPreQ)
{
pPreQ[0] = 0.0;
pPreQ[1] = 0.0;
pPreQ[2] = 0.0;
pPreQ[3] = 1.0;
if(Valid() && mNode.mNode->RotationActive )
{
FBRVector lR = mNode.mNode->PreRotation;
FBRotationToQuaternion(*reinterpret_cast<FBQuaternion *>(pPreQ), lR);
}
}
template <>
void HIKHostNode<HIKHostNodeMB>::GetPostQ(double *pPostQ)
{
pPostQ[0] = 0.0;
pPostQ[1] = 0.0;
pPostQ[2] = 0.0;
pPostQ[3] = 1.0;
if(Valid() && mNode.mNode->RotationActive )
{
FBRVector lR = mNode.mNode->PostRotation;
FBRotationToQuaternion(*reinterpret_cast<FBQuaternion *>(pPostQ), lR);
}
}
template <>
int HIKHostNode<HIKHostNodeMB>::GetRotationMinXYZ(double *pXYZ)
{
int lActiveMask = 0;
if(Valid() && mNode.mNode->RotationActive )
{
*reinterpret_cast<FBVector3d *>(pXYZ) = mNode.mNode->RotationMin;
FBTVector *lRotationMin = reinterpret_cast<FBTVector *>(pXYZ);
FBMult(*lRotationMin, *lRotationMin, K_DEG_TO_RAD);
lActiveMask |= mNode.mNode->RotationMinX ? HIKActiveMinX : 0;
lActiveMask |= mNode.mNode->RotationMinY ? HIKActiveMinY : 0;
lActiveMask |= mNode.mNode->RotationMinZ ? HIKActiveMinZ : 0;
}
return lActiveMask;
}
template <>
int HIKHostNode<HIKHostNodeMB>::GetRotationMaxXYZ(double *pXYZ)
{
int lActiveMask = 0;
if(Valid() && mNode.mNode->RotationActive )
{
*reinterpret_cast<FBVector3d *>(pXYZ) = mNode.mNode->RotationMax;
FBTVector *lRotationMax = reinterpret_cast<FBTVector *>(pXYZ);
FBMult(*lRotationMax, *lRotationMax, K_DEG_TO_RAD);
lActiveMask |= mNode.mNode->RotationMaxX ? HIKActiveMaxX : 0;
lActiveMask |= mNode.mNode->RotationMaxY ? HIKActiveMaxY : 0;
lActiveMask |= mNode.mNode->RotationMaxZ ? HIKActiveMaxZ : 0;
}
return lActiveMask;
}
template <>
int HIKHostNode<HIKHostNodeMB>::GetTranslationMinXYZ(double *pXYZ)
{
int lActiveMask = 0;
if(Valid() && mNode.mNode->TranslationActive )
{
*reinterpret_cast<FBVector3d *>(pXYZ) = mNode.mNode->TranslationMin;
lActiveMask |= mNode.mNode->TranslationMinX ? HIKActiveMinX : 0;
lActiveMask |= mNode.mNode->TranslationMinY ? HIKActiveMinY : 0;
lActiveMask |= mNode.mNode->TranslationMinZ ? HIKActiveMinZ : 0;
}
return lActiveMask;
}
template <>
int HIKHostNode<HIKHostNodeMB>::GetTranslationMaxXYZ(double *pXYZ)
{
int lActiveMask = 0;
if(Valid() && mNode.mNode->TranslationActive )
{
*reinterpret_cast<FBVector3d *>(pXYZ) = mNode.mNode->TranslationMax;
lActiveMask |= mNode.mNode->TranslationMaxX ? HIKActiveMaxX : 0;
lActiveMask |= mNode.mNode->TranslationMaxY ? HIKActiveMaxY : 0;
lActiveMask |= mNode.mNode->TranslationMaxZ ? HIKActiveMaxZ : 0;
}
return lActiveMask;
}
// HIKHostProperty<HIKHostPropertyMB>
template <>
int HIKHostProperty<HIKHostPropertyMB>::ReadMode( FBEvaluateInfo* pEvalInfo )
{
int lMode = Get().mDefaultMode;
if(Get().mModeP != NULL)
{
Get().mModeP->GetData(&lMode, sizeof(lMode));
}
return lMode;
}
template <>
double HIKHostProperty<HIKHostPropertyMB>::ReadValue( FBEvaluateInfo* pEvalInfo )
{
double lValue = Get().mDefaultValue;
if(Get().mValueP != NULL)
{
int lValueIndex = Get().mValueIndex;
FBPropertyType lPropType = Get().mValueP->GetPropertyType();
FBVector4d lVector;
Get().mValueP->GetData(&lVector, sizeof(lVector), pEvalInfo);
switch ( lPropType )
{
case kFBPT_int:
{
lValue = *((int*)&lVector);
}
break;
case kFBPT_bool:
{
lValue = *((bool*)&lVector);
}
break;
case kFBPT_enum:
{
lValue = *((int*)&lVector);
}
break;
default:
{
lValue = lVector[lValueIndex];
}
break;
}
}
return lValue / Get().mValueScale;
}
void HIKAdjustPostureForQuadriped(HIKCharacter *pHIKCharacter)
{
HIKCharacterState* lState = HIKCharacterStateCreate(pHIKCharacter, &malloc);
HIKGetDefaultState(pHIKCharacter, lState);
HIKSubQuadripedOffset(pHIKCharacter, lState);
HIKAddQuadripedOffset(pHIKCharacter, lState);
float lX[16];
int i;
for(i=0;i<LastNodeId;i++)
{
HIKGetNodeStatefv(pHIKCharacter, lState, i, lX);
HIKSetCharacterizeNodeStatefv(pHIKCharacter, i, lX);
}
HIKCharacterStateDestroy(lState, &free);
}
void UndoSetup(FBCharacter* pCharacter)
{
FBUndoManager lUndoManager;
if ( lUndoManager.TransactionIsOpen() )
{
FBCharacterSolver* lExtSolver = pCharacter->GetExternalSolver();
ORCharacterSolver_HIK* lConstraint = NULL;
if(lExtSolver)
{
lConstraint = dynamic_cast<ORCharacterSolver_HIK*>(lExtSolver);
if(lConstraint)
{
// we had Extra Shoulder TRS for Manipulation Undos
FBModel* lShoulder = lConstraint->GetExtraFKModelAt(LEFT_EXTRA_COLLAR);
if (lShoulder)
{
lUndoManager.TransactionAddModelTRS(lShoulder);
lShoulder = pCharacter->GetCtrlRigModel(kFBLeftShoulderNodeId);
if (lShoulder)
lUndoManager.TransactionAddModelTRS(lShoulder);
}
lShoulder = lConstraint->GetExtraFKModelAt(RIGHT_EXTRA_COLLAR);
if (lShoulder)
{
lUndoManager.TransactionAddModelTRS(lShoulder);
lShoulder = pCharacter->GetCtrlRigModel(kFBRightShoulderNodeId);
if (lShoulder)
lUndoManager.TransactionAddModelTRS(lShoulder);
}
if ( lConstraint->ArmSNS || lConstraint->LegSNS )
{
// We Need to add FKs Translation to Undos because MoBu only change Rotations on FK normally
// Since it's a minor hit on performance, we don't discriminate which one we should keep
for (int lBodyNodeIndex = kFBHipsNodeId; lBodyNodeIndex < kFBLastNodeId_Old; lBodyNodeIndex++)
{
FBModel *lModel = pCharacter->GetCtrlRigModel( (FBBodyNodeId)lBodyNodeIndex );
if ( lModel )
{
lUndoManager.TransactionAddModelTRS(lModel);
}
}
}
}
}
}
}