void SMDImporter::RecurseCreateNull ( XSI::X3DObject in_pParent, SMDNode* in_pNode ) { LPWSTR l_wszModelName; DSA2W(&l_wszModelName,FixName ( in_pNode->m_szName ) ); XSI::Null myNull = DoesObjectExist ( in_pParent, XSI::CString(l_wszModelName) ); if ( !myNull.IsValid() ) { in_pParent.AddNull ( l_wszModelName, myNull ); } in_pNode->m_x3d = myNull; XSI::KinematicState l_lLocal = myNull.GetKinematics().GetLocal(); XSI::MATH::CTransformation xfo; if ( in_pNode->m_pKeys.GetUsed() ) { SMDKey* l_pKey = in_pNode->GetKey (0); xfo = l_lLocal.GetTransform(); xfo.SetRotationFromXYZAnglesValues ( l_pKey->m_vRotation.GetX(), l_pKey->m_vRotation.GetY(), l_pKey->m_vRotation.GetZ() ); xfo.SetTranslationFromValues ( l_pKey->m_vPosition.GetX(), l_pKey->m_vPosition.GetY(), l_pKey->m_vPosition.GetZ() ); } if ( in_pNode->m_pParent ==NULL ) { XSI::MATH::CTransformation xfo2; xfo2.SetRotationFromXYZAnglesValues ( -1.570796, 0.0, 0.0 ); xfo.MulInPlace(xfo2); } l_lLocal.PutTransform ( xfo ); for (int c=0;c<in_pNode->m_pChildren.GetUsed();c++) { RecurseCreateNull ( myNull, in_pNode->GetChild(c)); } }
XSI::CStatus CAxisInterpOp::Update ( UpdateContext& ctx, OutputPort& output ) { Operator op(ctx.GetOperator()); /////////////////////////////////////////////////////////////// // get operator parameters /////////////////////////////////////////////////////////////// XSI::CString triggers(op.GetParameterValue(L"Triggers")); // triggers changed if ( m_csTriggers != triggers ) { m_csTriggers = triggers; Init( ctx, 0 ); } double boneperc = op.GetParameterValue(L"BoneDist"); /////////////////////////////////////////////////////////////// // get objects connected to input & output ports /////////////////////////////////////////////////////////////// InputPort rootboneport(op.GetPort(L"globalkineport",L"RootBoneGroup",0)); InputPort parentboneport(op.GetPort(L"globalkineport",L"ParentBoneGroup",0)); InputPort parentbonelenport(op.GetPort(L"bonelengthport",L"ParentBoneGroup",0)); InputPort childboneport(op.GetPort(L"globalkineport",L"ChildBoneGroup",0)); KinematicState gkRoot(rootboneport.GetValue()); KinematicState gkParent(parentboneport.GetValue()); double parentbonelen(parentbonelenport.GetValue()); KinematicState gkChild(childboneport.GetValue()); KinematicState gkHelper(output.GetValue()); // GET TRANSFORMATIONS OF ROOT, PARENT & CHILD CTransformation tGRoot = gkRoot.GetTransform(); CTransformation tGBone1 = gkParent.GetTransform(); CTransformation tGBone2 = gkChild.GetTransform(); #ifdef _DEBUG_UPDATE { Application app; wchar_t wszBuf[256]; XSI::MATH::CQuaternion q = tGBone1.GetRotationQuaternion(); double x, y, z; q.GetXYZAnglesValues(x,y,z); swprintf( wszBuf, L"parent R(%f,%f,%f)]", r2d(x),r2d(y),r2d(z) ); app.LogMessage( (const wchar_t*)wszBuf ); } #endif #ifdef _DEBUG_UPDATE { Application app; wchar_t wszBuf[256]; XSI::MATH::CQuaternion q = tGBone2.GetRotationQuaternion(); double x, y, z; q.GetXYZAnglesValues(x,y,z); swprintf( wszBuf, L"child R(%f,%f,%f)]", r2d(x),r2d(y),r2d(z) ); app.LogMessage( (const wchar_t*)wszBuf ); } #endif /////////////////////////////////////////////////////////////// // perform update function /////////////////////////////////////////////////////////////// // GET LOCAL TRANSFORM OF CHILD RELATIVE TO PARENT XSI::MATH::CMatrix3 mBone1( tGBone1.GetRotationMatrix3() ); XSI::MATH::CMatrix3 mBone2( tGBone2.GetRotationMatrix3() ); #ifdef _DEBUG_UPDATE { Application app; wchar_t wszBuf[256]; double m0, m1, m2, m3, m4, m5, m6, m7, m8; mBone1.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8); swprintf( wszBuf, L"mBone1->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 ); app.LogMessage( (const wchar_t*)wszBuf ); } #endif #ifdef _DEBUG_UPDATE { Application app; wchar_t wszBuf[256]; double m0, m1, m2, m3, m4, m5, m6, m7, m8; mBone2.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8); swprintf( wszBuf, L"mBone2->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 ); app.LogMessage( (const wchar_t*)wszBuf ); } #endif mBone1.TransposeInPlace(); #ifdef _DEBUG_UPDATE { Application app; wchar_t wszBuf[256]; double m0, m1, m2, m3, m4, m5, m6, m7, m8; mBone1.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8); swprintf( wszBuf, L"mBone1.TransposeInPlace->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 ); app.LogMessage( (const wchar_t*)wszBuf ); } #endif XSI::MATH::CMatrix3 tmpMat3; for(int nR=0; nR<3; nR++) for(int nC=0; nC<3; nC++) { tmpMat3.SetValue(nR,nC , mBone2.GetValue(nR,0) * mBone1.GetValue(0,nC) + mBone2.GetValue(nR,1) * mBone1.GetValue(1,nC) + mBone2.GetValue(nR,2) * mBone1.GetValue(2,nC) ); } mBone2 = tmpMat3; // bug #90494 // mBone2.MulInPlace( mBone1 ); #ifdef _DEBUG_UPDATE { Application app; wchar_t wszBuf[256]; double m0, m1, m2, m3, m4, m5, m6, m7, m8; mBone2.Get(m0, m1, m2, m3, m4, m5, m6, m7, m8); swprintf( wszBuf, L"mBone2.MulInPlace( mBone1 )->\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f\n%.2f,%.2f,%.2f", m0, m1, m2, m3, m4, m5, m6, m7, m8 ); app.LogMessage( (const wchar_t*)wszBuf ); } #endif // GET ORIENTATION OF BONE2 RELATIVE TO BONE1 AS A QUATERNION XSI::MATH::CQuaternion qBone2 = mBone2.GetQuaternion(); // MATCH QUATERNIONS XSI::MATH::CVector3 vBasePos( op.GetParameterValue(L"BasePoseX"), op.GetParameterValue(L"BasePoseY"), op.GetParameterValue(L"BasePoseZ") ); #ifdef _DEBUG_UPDATE { Application app; wchar_t wszBuf[256]; double x, y, z; qBone2.GetXYZAnglesValues(x,y,z); swprintf( wszBuf, L"child2parent R(%f,%f,%f)]", r2d(x),r2d(y),r2d(z) ); app.LogMessage( (const wchar_t*)wszBuf ); } #endif ComputeBaseOffset(vBasePos, boneperc, parentbonelen ); ComputeWeights( qBone2, m_cTriggers, m_aWeights, m_aTriggerOri, m_aTriggerTol ); // SUM TARGET ORIENTATIONS & POSITIONS XSI::MATH::CQuaternion qNewOri; SumTargets( qNewOri, vBasePos, m_cTriggers, m_aWeights, m_aTargetOri, m_aTargetPos ); #ifdef _DEBUG_UPDATE Application app; wchar_t wszBuf[256]; double x, y, z; qNewOri.GetXYZAnglesValues(x,y,z); swprintf( wszBuf, L"qNewOri->R(%f,%f,%f)]", r2d(x),r2d(y),r2d(z) ); app.LogMessage( (const wchar_t*)wszBuf ); #endif // UPDATE TRANSFORMATION XSI::MATH::CTransformation tNewPose; tNewPose.SetRotationFromQuaternion( qNewOri ); tNewPose.SetTranslation( vBasePos ); tNewPose.MulInPlace( tGRoot ); /////////////////////////////////////////////////////////////// // update output port /////////////////////////////////////////////////////////////// gkHelper.PutTransform( tNewPose ); return CStatus::OK; }
CStatus CHelperBoneOp::Update ( UpdateContext& ctx, OutputPort& output ) { /////////////////////////////////////////////////////////////// // get operator /////////////////////////////////////////////////////////////// Operator op(ctx.GetOperator()); /////////////////////////////////////////////////////////////// // get output port /////////////////////////////////////////////////////////////// KinematicState gkHelper(output.GetValue()); /////////////////////////////////////////////////////////////// // get helper bone data /////////////////////////////////////////////////////////////// InputPort bonedataport(op.GetPort(L"bonedataport",L"HelperBoneGroup",0)); Property HelperBoneData(bonedataport.GetValue()); bool enabled = HelperBoneData.GetParameterValue(L"Enabled"); // not enabled: do nothing if (!enabled) return CStatus::OK; /////////////////////////////////////////////////////////////// // evaluate new transformation for helperbone /////////////////////////////////////////////////////////////// XSI::MATH::CTransformation tNewPose; bool bComputeInWorldSpace = (0!=(long)HelperBoneData.GetParameterValue(L"ComputationSpace")); /////////////////////////////////////////////////////////////// // get objects connected to input & output ports /////////////////////////////////////////////////////////////// InputPort rootboneport(op.GetPort(L"globalkineport",L"RootBoneGroup",0)); InputPort parentboneport(op.GetPort(L"globalkineport",L"ParentBoneGroup",0)); InputPort childboneport(op.GetPort(L"globalkineport",L"ChildBoneGroup",0)); KinematicState gkRoot(rootboneport.GetValue()); KinematicState gkParent(parentboneport.GetValue()); KinematicState gkChild(childboneport.GetValue()); // get helperbonedata values XSI::MATH::CVector3 vBasePos( HelperBoneData.GetParameterValue(L"BoneOffsetX"), HelperBoneData.GetParameterValue(L"BoneOffsetY"), HelperBoneData.GetParameterValue(L"BoneOffsetZ") ); double perc_along_root = (double)HelperBoneData.GetParameterValue(L"BoneDistance") / 100.0; double root_bone_length = (double)HelperBoneData.GetParameterValue(L"RootBoneLength"); XSI::GridData griddata(HelperBoneData.GetParameterValue(L"Triggers")); // read triggers ReadTriggerData(griddata); // GET TRANSFORMATIONS OF ROOT, PARENT & CHILD CTransformation tGRoot = gkRoot.GetTransform(); CTransformation tGParent = gkParent.GetTransform(); CTransformation tGChild = gkChild.GetTransform(); /////////////////////////////////////////////////////////////// // compute new orientation and position based on triggers /////////////////////////////////////////////////////////////// DebugPrint( L"parent", tGParent.GetRotationQuaternion() ); DebugPrint( L"child", tGChild.GetRotationQuaternion() ); // GET LOCAL TRANSFORM OF CHILD RELATIVE TO PARENT XSI::MATH::CMatrix3 m3Parent( tGParent.GetRotationMatrix3() ); DebugPrint(L"m3Parent->", m3Parent); XSI::MATH::CMatrix3 m3Child( tGChild.GetRotationMatrix3() ); DebugPrint(L"m3Parent->", m3Child); m3Parent.TransposeInPlace(); DebugPrint(L"m3Parent.TransposeInPlace->", m3Parent); // bug #90494 // m3Child.MulInPlace( m3Parent ); MulInPlace( m3Child, m3Parent ); DebugPrint(L"m3Child.MulInPlace->", m3Child); // GET ORIENTATION OF BONE2 RELATIVE TO BONE1 AS A QUATERNION XSI::MATH::CQuaternion qBone2 = m3Child.GetQuaternion(); DebugPrint( L"child2parent", qBone2 ); // MATCH QUATERNIONS ComputeWeights( qBone2, m_cTriggers, m_aEnabled, m_aWeights, m_aTriggerOri, m_aTriggerTol ); // SUM TARGET ORIENTATIONS & POSITIONS XSI::MATH::CQuaternion qNewOri; XSI::MATH::CVector3 vNewPos; SumTargets( qNewOri, vNewPos, m_cTriggers, m_aWeights, m_aTargetOri, m_aTargetPos ); DebugPrint( L"qNewPos->", qNewPos ); DebugPrint( L"vNewOri->", qNewOri ); // UPDATE TRANSFORMATION if (bComputeInWorldSpace) { // not implemented } else // Root object space { // compute initial helperbone position vBasePos.PutX( vBasePos.GetX() + (root_bone_length * perc_along_root) ); vNewPos.AddInPlace(vBasePos); // apply changes from triggers tNewPose.SetRotationFromQuaternion( qNewOri ); tNewPose.SetTranslation( vNewPos ); // map root object space to worldspace tNewPose.MulInPlace( tGRoot ); } /////////////////////////////////////////////////////////////// // update output port /////////////////////////////////////////////////////////////// gkHelper.PutTransform( tNewPose ); return CStatus::OK; }