//***************************************************************************************
// 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;
}
Exemplo n.º 5
0
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;
}