//*************************************************************************************** // function : SumTargets // description: multiply all the weights by the set of new orientations and positions // and sum the result to give the new orientation and position. // // aweights : array of weights // qrot : resulting summed rotation quaternion // vpos : resulting summed position vector3 // atargetori : array of target orientations // atargetpos : array of target positions //*************************************************************************************** void CAxisInterpOp::SumTargets( XSI::MATH::CQuaternion& qrot, XSI::MATH::CVector3& vpos, unsigned long size, double* aweights, double* atargetori, double* atargetpos ) { double w; XSI::MATH::CRotation r1; XSI::MATH::CQuaternion q1; XSI::MATH::CQuaternion q2; XSI::MATH::CVector3 v1; qrot.Set(0,0,0,0); for ( unsigned long i=0; i < size; i++ ) { w = aweights[i]; if ( w != 0 ) { q1.SetFromXYZAnglesValues( d2r(atargetori[(i*3)+0]), d2r(atargetori[(i*3)+1]), d2r(atargetori[(i*3)+2]) ); // w.qi q2.Set( q1.GetW() * w, q1.GetX() * w, q1.GetY() * w, q1.GetZ() * w ); qrot.AddInPlace( q2 ); // w.vi v1.Set( atargetpos[(i*3)+0], atargetpos[(i*3)+1], atargetpos[(i*3)+2] ); v1.ScaleInPlace( w ); vpos.AddInPlace( v1 ); } } qrot.Normalize(); }
inline void DebugPrint( const XSI::CString& str, const XSI::MATH::CQuaternion& q ) { Application app; wchar_t wszBuf[256]; XSI::MATH::CQuaternion q = tGParent.GetRotationQuaternion(); double x, y, z; q.GetXYZAnglesValues(x,y,z); swprintf( wszBuf, L"%s R(%f,%f,%f)]", (const wchar_t*)str, r2d(x),r2d(y),r2d(z) ); app.LogMessage( (const wchar_t*)wszBuf ); }
void CAxisInterpOp::ComputeWeights ( XSI::MATH::CQuaternion& qbone2, unsigned long size, // number of triggers double* aweights, double* atriggers, double* atolerances ) { XSI::MATH::CQuaternion q2; #ifdef _DEBUG_COMPUTEWEIGHTS Application app; wchar_t wszBuf[256]; swprintf( wszBuf, L"ComputeWeights qbone2->[%f V(%f,%f,%f)]", qbone2.GetW(), qbone2.GetX(), qbone2.GetY(), qbone2.GetZ() ); app.LogMessage( (const wchar_t*)wszBuf ); double x, y, z; qbone2.GetXYZAnglesValues(x,y,z); swprintf( wszBuf, L"ComputeWeights qbone2->R(%f,%f,%f)]", r2d(x),r2d(y),r2d(z) ); app.LogMessage( (const wchar_t*)wszBuf ); #endif // dim tsec : tsec = timer // fntrace "ComputeWeights("&j&") bone2 angle: " & fnstr(q2rot(qbone2)) double sumw(0), weight(0), dot_product(0), tolerance(0); for ( unsigned long j=0,i=0; i < size*3; i=i+3,j=j+1 ) { tolerance = d2r(atolerances[j]); #ifdef _DEBUG_COMPUTEWEIGHTS swprintf( wszBuf, L"trigger(%d) ori: (%f,%f,%f)", j, atriggers[i], atriggers[i+1], atriggers[i+2] ); app.LogMessage( (const wchar_t*)wszBuf ); swprintf( wszBuf, L"trigger(%d) tolerance: %f", j, tolerance ); app.LogMessage( (const wchar_t*)wszBuf ); #endif q2.SetFromXYZAnglesValues( d2r(atriggers[i]), d2r(atriggers[i+1]), d2r(atriggers[i+2]) ); // compute dot product of quaternion dot_product = qbone2.GetX() * q2.GetX() + qbone2.GetY() * q2.GetY() + qbone2.GetZ() * q2.GetZ() + qbone2.GetW() * q2.GetW(); #ifdef _DEBUG_COMPUTEWEIGHTS swprintf( wszBuf, L"trigger(%d) dot: %f", j, dot_product ); app.LogMessage( (const wchar_t*)wszBuf ); #endif if ( tolerance == 0 ) { weight = 0; } else { #ifdef _DEBUG_COMPUTEWEIGHTS // swprintf( wszBuf, L"ComputeWeights(%d) _acos(%f) = %f", j, fabs(dot_product), _acos(fabs(dot_product)) ); // app.LogMessage( (const wchar_t*)wszBuf ); swprintf( wszBuf, L"trigger(%d) acos(%f) = %f", j, fabs(dot_product), acos(fabs(dot_product)) ); app.LogMessage( (const wchar_t*)wszBuf ); #endif weight = 1.0 - (2.0 * acos(fabs(dot_product)) / tolerance); #ifdef _DEBUG_COMPUTEWEIGHTS swprintf( wszBuf, L"trigger(%d) weight: %f", j, weight ); app.LogMessage( (const wchar_t*)wszBuf ); #endif if ( weight < 0 ) { weight = 0; } } #ifdef _DEBUG_COMPUTEWEIGHTS swprintf( wszBuf, L"trigger(%d) computed weight: %f", j, weight ); app.LogMessage( (const wchar_t*)wszBuf ); #endif aweights[j] = weight; // fntrace "ComputeWeights("&j&") raw: " & aW(j) sumw=sumw+aweights[j]; } // make sure sum of weights totals 1 if ( sumw != 0 ) { for ( unsigned long i=0; i < size; i++ ) { if ( aweights[i] != 0 ) { aweights[i] = aweights[i] / sumw; //fntrace "ComputeWeights("&i&") normalized: " & aW(i) } #ifdef _DEBUG_COMPUTEWEIGHTS swprintf( wszBuf, L"trigger(%d) normalized = %f", i, aweights[i] ); app.LogMessage( (const wchar_t*)wszBuf ); #endif } } //fntrace "AxisInterpOp::ComputeWeights: took " & timer-tsec & " seconds" }
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; }
bool bulletSimulation::SetFrame(int in_Frame) { // see if we have to reset the world if(in_Frame <= 0) { ResetWorld(); return true; } // now let's skip if we already have that frame or the interval>5 - we don't want bullet to compute the whole sequence if you move to the last frame. if(mLastFrame >= in_Frame || (in_Frame-mLastFrame)>5) { return false; } mChangingFrame = true; // if this is not the first frame, let's update all rbd! for(btRigidBodyIt it = mRigidBodies.begin();it!=mRigidBodies.end();it++) { // skip corrupt bodies if(it->second->body==NULL) continue; if(it->first.secondary != -1) continue; btCollisionShape * shape = (btBoxShape*)it->second->body->getCollisionShape(); if(shape != NULL) { // refresh the kine ptr it->second->kine.Set(it->second->kine.GetAsText()); XSI::MATH::CTransformation xf = XSI::KinematicState(it->second->kine).GetTransform();//(float)in_Frame); shape->setLocalScaling(btVector3(xf.GetSclX(),xf.GetSclY(),xf.GetSclZ())); // skip non valid ops if(!it->second->op.IsValid()) continue; // update the mass an inertia it->second->mass = XSI::CustomOperator(it->second->op).GetParameterValue(L"mass"); btVector3 inertia(0,0,0); if(it->second->mass > 0.0f) shape->calculateLocalInertia(it->second->mass,inertia); it->second->body->setMassProps(it->second->mass,inertia); // if we are passive rigid body, let's update the transform if(it->second->mass == 0.0f) { btDefaultMotionState * motionState = (btDefaultMotionState*)it->second->body->getMotionState(); if(motionState != NULL) { btTransform transform; transform.setOrigin(btVector3(xf.GetPosX(),xf.GetPosY(),xf.GetPosZ())); XSI::MATH::CQuaternion q = xf.GetRotationQuaternion(); transform.setRotation(btQuaternion(q.GetX(),q.GetY(),q.GetZ(),q.GetW())); it->second->body->proceedToTransform( transform ); } } } } // step to the given frame if(in_Frame > 0) { while(in_Frame > mLastFrame) { float dt=(1.0f/mFps)/(float)mSubSteps; //Step every subframe for (int i=0;i<mSubSteps;i++) mDynamicsWorld->stepSimulation(dt,0,1.0f/mFps); mLastFrame++; } } mLastFrame = in_Frame; mChangingFrame = false; return true; }