Example #1
0
//This will set the formation
void FormationBhvr::SetFormation(TimeValue t)
{
	INode *node;
	Matrix3 tempMatrix;


	//Make sure that the leader is not part of the follower array..
	RemoveLeaderFromFormation(t);


	INode *leader =  GetLeader(t);

	if(leader==NULL)
		return;
	Matrix3 leaderPosition = GetCurrentMatrix(leader,t);
	leaderPosition.NoScale(); //kill any scale if we have it 
	leaderPosition.Invert();  //it's inverted...


	int numDelegates = GetFollowerCount(t);	

	//zero out the formation matrix that's used for saving it out.
	pblock->ZeroCount(follower_matrix1);
	pblock->ZeroCount(follower_matrix2);
	pblock->ZeroCount(follower_matrix3);
	pblock->ZeroCount(follower_matrix4);

	for(int i =0;i<numDelegates;i++)
	{

		node = GetFollower(t,i);
		if(node)
		{
			tempMatrix = GetCurrentMatrix(node,t);
			tempMatrix.NoScale();
			Matrix3 leaderMat =tempMatrix*leaderPosition;
			AppendFollowerMatrix(t,leaderMat);

			//killed because matrix3 wasn't working ...pblock->Append(follower_matrix,1,&leaderMat);
		 
		
		}
		else
		{
			//we still set up follower_matrix so that the counts
			//of the follower_matrix tab and the follower tab are equal.
			tempMatrix.IdentityMatrix();
			AppendFollowerMatrix(t,tempMatrix);

			//pblock->Append(follower_matrix,1,&tempMat);
	
		}
	}

}
void	SplineData::RotateSelectedCrossSections(Quat q)
{
	Tab<int> selSplines;
	Tab<int> selCrossSections;
	GetSelectedCrossSections(selSplines,selCrossSections);

	//move the cross sections
	for (int i = 0; i < selSplines.Count(); i++)
	{
		int splineIndex = selSplines[i];
		int crossSectionIndex = selCrossSections[i];
		SplineCrossSection *section = GetCrossSection(splineIndex,crossSectionIndex);

		Matrix3 sTM = section->mTM;
		sTM.NoScale();
		sTM.NoTrans();

		Quat tq = TransformQuat(sTM,q);
		//no back into our initial space
		tq = TransformQuat(section->mIBaseTM,tq);

		section->mQuat += tq;


	}

	RecomputeCrossSections();	
}
void     makBoneTrans2(INode* pNode , sBoneTrans_t& boneTrans , Matrix3& mat)
{
	Point3   Trans = mat.GetTrans();
	Matrix3  RotMat = mat;
	Matrix3  ScaleMat = mat;

    RotMat.NoScale();
    ScaleMat = mat * Inverse(RotMat);
    //算出Scale Matrix;

	RotMat.NoTrans();	
	Quat RotQuat(RotMat);

	//ScaleMat.NoRot();
	//ScaleMat.NoTrans();

	boneTrans.m_Rotate    = conv_type<sQuat_t , Quat>(RotQuat);
	boneTrans.m_Trans     = conv_type<sVector_t   ,Point3 >(Trans);
	boneTrans.m_Scale.x   = ScaleMat.GetRow(0).x;
	boneTrans.m_Scale.y   = ScaleMat.GetRow(1).y;
	boneTrans.m_Scale.z   = ScaleMat.GetRow(2).z;
	if( abs(boneTrans.m_Scale.x - boneTrans.m_Scale.y) > 0.000001 ||
		abs(boneTrans.m_Scale.y - boneTrans.m_Scale.z) > 0.000001 ||
		abs(boneTrans.m_Scale.z - boneTrans.m_Scale.x) > 0.000001 )
	{
            std::wstring _NodeName = INodeName(pNode);
            XEVOL_LOG(eXL_DEBUG_HIGH , L"   {警告} :  骨头[ %s ] 的上有NonUniformScale\r\n", _NodeName.c_str() );
	}
}
Example #4
0
//The display function that is used to display the formation.
int FormationBhvr::Display(TimeValue t, ViewExp *vpt) 
{
    // setup

	int i,j;
   	
	if(DisplayFormation(t)==FALSE) return FALSE;

	if(GetFollowerCount(t)<=0) return FALSE;
	if(GetFollowerMatrixCount(t)<=0) return FALSE;

	INode *leaderNode;
	leaderNode = GetLeader(t);
	if(leaderNode==NULL) return FALSE;
	
	
	//check tgo see if we have created a default sphere for drawing yet...
    //if we haven't then create it..
	if (numpts == 0) 
		GetSpherePoints(Point3(0.0f,0.0f,0.0f), 1.0, SpherePts);

	
	GraphicsWindow *gw = vpt->getGW();
   
	//set the identity matrix...
	Matrix3 idMat;
	idMat.IdentityMatrix();
    gw->setTransform(idMat);

	gw->setColor(LINE_COLOR,.815f,.976f,1.0f);

	float scaleRadius = GetDisplayScale(t);
	
	//set the drawing radius values based upon what the radius size is.
	for (i=0; i<NUMAROUND * 3; i++) ScaledPts[i] = ((SpherePts[i] * scaleRadius));
	 
	//for each follower we need to increase the bounding box by it's
	//world position location...
	for(i =0;i<GetFollowerCount(t);i++)
	{
		INode *followerNode = GetFollower(t,i);
		if(followerNode) //if we have a a node...
		{
	
			Matrix3 leaderMat = GetCurrentMatrix(leaderNode,t);
			leaderMat.NoScale();
			Matrix3 followerMat = GetFollowerMatrix(t,i);
			Matrix3 worldSpace = followerMat *leaderMat;
			for (j=0; j<NUMAROUND * 3; j++) CurPts[j] = worldSpace*ScaledPts[j]; //adding the center to the point positions
			
		   	gw->polyline(NUMAROUND,&CurPts[0],NULL,NULL,TRUE,NULL);
		 	gw->polyline(NUMAROUND,&CurPts[NUMAROUND],NULL,NULL,TRUE,NULL);
    		gw->polyline(NUMAROUND,&CurPts[NUMAROUND * 2],NULL,NULL,TRUE,NULL);

		
		}
	}

	return TRUE;
}
Example #5
0
Matrix3 MshExp::TransformNode(INode* pNode,TimeValue CurTime, int TransformType){
	Matrix3 mat;

	switch((TransformType&0xff))
	{
		case TN_AFTER_WORLD://After World
			mat = pNode->GetObjTMAfterWSM(CurTime);
			break;
		case TN_BEFORE_WORLD://Before World
			mat = pNode->GetObjTMBeforeWSM(CurTime);
			break;
		case TN_TRANSFORM:
			mat = pNode->GetNodeTM(CurTime);
			break;
		default:
			mat = Matrix3(1);
			break;
	}

	if(TransformType&TN_NO_TRANSLATION)
		mat.NoTrans();
	if(TransformType&TN_NO_ROTATION)
		mat.NoRot();
	if(TransformType&TN_NO_SCALE)
		mat.NoScale();

	return mat;
}
Example #6
0
void ProtHelpObject::GetMat(TimeValue t, INode* inode, ViewExp& vpt, Matrix3& tm) 
{
   if ( ! vpt.IsAlive() )
	{
		tm.Zero();
		return;
	}
	 tm = inode->GetObjectTM(t);
   tm.NoScale();
   float scaleFactor = vpt.NonScalingObjectSize() * vpt.GetVPWorldWidth(tm.GetTrans()) / 360.0f;
   tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor));
}
void SplineData::AlignCrossSection(int splineIndex, int crossSectionIndex,Point3 vec)
{
	if ((splineIndex >= 0) && (splineIndex < mSplineElementData.Count()))
	{
		int numCrossSections = NumberOfCrossSections(splineIndex);

		if ((crossSectionIndex >= 0) && (crossSectionIndex < numCrossSections))
		{

			//put the vec in spline space
			SplineCrossSection *crossSection = GetCrossSection(splineIndex,crossSectionIndex);


			Matrix3 crossSectionTM = crossSection->mTM;
			crossSectionTM.NoScale();
			crossSectionTM.NoTrans();
			Matrix3 icrossSectionTM = Inverse(crossSectionTM);


			Point3 crossSectionZVec = crossSection->mTangentNormalized;


			Point3 yvec = Normalize(vec);

			Point3 xvec = Normalize(CrossProd(yvec,crossSectionZVec));
			Point3 zvec = Normalize(CrossProd(xvec,yvec));

			Matrix3 rtm(1);
			rtm.SetRow(0,xvec);
			rtm.SetRow(1,yvec);
			rtm.SetRow(2,zvec);
			rtm.SetRow(3,Point3(0.0f,0.0f,0.0f));

			Matrix3 relativeTM =  crossSection->mIBaseTM * rtm;

			Quat q(relativeTM);


			q = TransformQuat(crossSection->mIBaseTM,q);

			crossSection->mQuat = q;

			return;
		}
	}
	DbgAssert(0);


}
Example #8
0
static void UnwrapMatrixFromNormal(Point3& normal, Matrix3& mat)
	{
	Point3 vx;
	vx.z = .0f;
	vx.x = -normal.y;
	vx.y = normal.x;	
	if ( vx.x == .0f && vx.y == .0f ) {
		vx.x = 1.0f;
		}
	mat.SetRow(0,vx);
	mat.SetRow(1,normal^vx);
	mat.SetRow(2,normal);
	mat.SetTrans(Point3(0,0,0));
	mat.NoScale();
	}
Matrix3 SGP_MaxInterface::GetNodeTM(INode *pNode, float time)
{
	// initialize matrix with the identity
	Matrix3 tm;
	tm.IdentityMatrix();

	// only do this for valid nodes
	if(pNode != NULL)
	{
		// get the node transformation
		tm = pNode->GetNodeTM(SecToTicks(time));

		// make the transformation uniform
		tm.NoScale();
	}

	return tm;
}
void	SplineData::MoveSelectedCrossSections(Point3 vec)
{
	

 	Tab<int> selSplines;
	Tab<int> selCrossSections;
	GetSelectedCrossSections(selSplines,selCrossSections);
	if (selSplines.Count() == 0) return;
//get the spline length
	float l = mSplineElementData[selSplines[0]]->GetSplineLength();
//get the sel cross u
	SplineCrossSection *section = GetCrossSection(selSplines[0],selCrossSections[0]);

	//transform into spline space
	Matrix3 sTM = section->mTM;
	sTM.NoScale();
	Point3 tv = VectorTransform(sTM,vec);
	//no back into our initial space
	Point3 v = VectorTransform(section->mIBaseTM,tv);

//compute how much u to move
	
	float incU = v.z/l;
	//move the cross sections
	for (int i = 0; i < mSplineElementData.Count(); i++)
	{
		if (mSplineElementData[i]->IsSelected())
		{
			for (int j = 0; j < (NumberOfCrossSections(i)); j++)
			{
				if (CrossSectionIsSelected(i,j))
				{
					SplineCrossSection *section = GetCrossSection(i,j);

					Matrix3 sTM = section->mTM;
					sTM.NoScale();

					tv = VectorTransform(sTM,vec);
					v = VectorTransform(section->mIBaseTM,tv);
					float tempU = section->mOffset.z + incU;
					
					if (tempU > 1.0f)
						tempU = 1.0f;
					if (tempU < 0.0f)
						tempU = 0.0f;
					float prevU = 0.0f;
					if (j != 0)
						prevU = GetCrossSection(i,j-1)->mOffset.z;
					float nextU = 1.0;
					if ((j+1) < NumberOfCrossSections(i))
						nextU = GetCrossSection(i,j+1)->mOffset.z;

					if ((tempU < nextU) && (tempU > prevU))
					{
						//we cant slide the end/start cross sections
						if ((j != 0) && (j != NumberOfCrossSections(i)-1))
							section->mOffset.z = tempU;
					}

					

					section->mOffset.x += v.x;
					section->mOffset.y += v.y;


				}
			}
		}
	}

	RecomputeCrossSections();	
}
Example #11
0
int FormationBhvr::Perform(INode *node, TimeValue t, int numsubsamples, BOOL DisplayHelpers, float BhvrWeight,
			PerformOut &out)
{
	Object *o = node->GetObjectRef();
    if (o->ClassID() != DELEG_CLASSID) return FALSE; // this should never happen
    IDelegate *IDeleg = (IDelegate *) o->GetInterface(I_DELEGINTERFACE);
	Point3 vel= IDeleg->GetCurrentVelocity();

	Point3 pos = IDeleg->GetCurrentPosition();

	INode *leader = GetLeader(t);
	if(leader==NULL)
		return 0;

	
	Matrix3 formationMat;
	//Get the local formation matrix and check

	if(FindFollowerMatrix(t,node,formationMat)==FALSE)
		return 0; //that node doesn't exist in the formation so exit.

	//returned values.
	Point3 frc,goal;
	float speedwt, speedAtGoalwt;

	//Find the Formation Position Target in World Space.

 	Matrix3 currentLeaderMat = GetCurrentMatrix(leader,t);
	currentLeaderMat.NoScale();
	Matrix3 worldSpace = formationMat*currentLeaderMat;
	Point3 target =  worldSpace.GetTrans();

	//set the goal as the target
	goal = target;

	//set the force as the direction to move towards the target
	frc =  goal - pos;

	float length = frc.FLength();

	if(length!=0.0f) //we are not at the goal
	{
		frc  /=length;
		
		//set up the leader Vector
		Point3 leaderVec = leaderVel*leaderSpeed;

	
	
		//If the  target is behind you but moving towards you don't turn around to
		//go toward it.  Instead move in the direction of the leader.
		if(frc%vel<0.0f &&  //if you are behind it
			length/IDeleg->GetAverageSpeed(t)<10 && //AND less than 20 frames
			vel%leaderVel>0.0f) //AND it is going toward you.
		{
			
			//set frc as leader's Velocity.
			frc = leaderVel;

			//move at half the leaderSpeed.  Leader will still catch
			//up to you and you'll have some speed when it does.
			
			//set the speewt
			speedwt = (leaderSpeed*0.5f)/IDeleg->GetAverageSpeed(t);
		}
		else //we should just move towards the target.
		{
			//We need to find the speed to be it.  We do this by
			//finding the time we will intersect our target based
			//upon the leader's velocity and our own velocity.

			vel -= leaderVec;
			
			//find time to intersect..
			float newSpeed = vel.FLength();
			float timeToIntersect = length/newSpeed;

			//from that time.. figure out what it speed should be..
			newSpeed = timeToIntersect * IDeleg->GetMaxAccel(t);
			if(newSpeed>IDeleg->GetAverageSpeed(t))
				newSpeed = IDeleg->GetAverageSpeed(t);


			//check to see if we will move past the goal.. if so
			//move the goal along the leader vec.  This reduces overshooting
			//the goal and decreases wobbling.
			if((newSpeed+leaderSpeed)>length) 	
			{
				goal += leaderVel*(leaderSpeed);  
				frc = goal -pos;
				float newLength = frc.FLength();

				if(newLength!=0.0f) //check for if zero to avoid divide by zero..
				{
					frc /= newLength;
					speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t);
										
				}
				else
				{
					speedwt = 0.0f;
				}

			}
			else //far enough away.. leave the ole frc value..
				speedwt = (newSpeed+leaderSpeed)/IDeleg->GetAverageSpeed(t);
			
		}
	}
	else  //we are at the goal
	{
		frc.x = frc.y = frc.z = 0.0f;
	
		//set the speedwt to be the leaderSpeed
		speedwt = leaderSpeed/IDeleg->GetAverageSpeed(t);
	}

	frc *= BhvrWeight *IDeleg->GetAverageSpeed(t); //scale by weight and average speed..

	//set the speedWtAtGoal.. We want it to be the speed of the leader
	speedAtGoalwt = leaderSpeed/IDeleg->GetAverageSpeed(t);

	//Display Any Helpers.
	if (DisplayHelpers && IDeleg->OkToDisplayMyForces())
	{
		if (DisplayTarget(t)) IDeleg->SphereDisplay(goal,pblock->GetFloat(target_scale),GetTargetColor(t));
		if (DisplayForce(t))  IDeleg->LineDisplay(IDeleg->GetCurrentPosition(),IDeleg->GetCurrentPosition()+frc,GetForceColor(t),TRUE);
	}

	//set up the out structure..
	out.frc = frc;
	out.goal = goal;
	out.speedwt = speedwt;
	out.speedAtGoalwt = speedAtGoalwt;

	return BHVR_SETS_FORCE | BHVR_SETS_GOAL | BHVR_SETS_SPEED;
}
Example #12
0
void SGP_MaxInterface::GetTracks( int nNodeCount, INode** nodes, Track** tracks )
{
	StartProgressInfo(_M("Get node track..."));

	TimeValue nStartTick = GetStartTick();
	TimeValue nEndTick = GetEndTick();
	int nTickPerFrame = GetTickPerFrame();
	int nFrameCount = 0;

	for( TimeValue t = nStartTick; t <= nEndTick; t += nTickPerFrame )
		nFrameCount++;

	for( int i = 0; i < nNodeCount; i++ )
	{
		tracks[i]->vectorVisible.resize( nFrameCount );
		tracks[i]->vectorTrans.resize( nFrameCount );
		tracks[i]->vectorRot.resize( nFrameCount );
		tracks[i]->vectorScale.resize( nFrameCount );

		Matrix3 matrix = nodes[i]->GetObjTMAfterWSM ( 0 );
		bool bMirror = DotProd ( CrossProd ( matrix.GetRow ( 0 ), matrix.GetRow ( 1 ) ), matrix.GetRow ( 2 ) ) < 0.0 ? true : false;
		tracks[i]->bMirror = bMirror;
	}
	TimeValue t = nStartTick;
	for( int nFrameId = 0; nFrameId < nFrameCount; nFrameId++, t += nTickPerFrame )
	{
		SetProgressInfo( 100.0f*nFrameId/nFrameCount );

		for( int nNodeId = 0; nNodeId < nNodeCount; nNodeId++ )
		{
			INode* pNode = nodes[nNodeId];
			Track* pTrack = tracks[nNodeId];

			Matrix3 tm = pNode->GetNodeTM(t);

			// The coordinate system of 3DMax9 is Right-X Up-Z Screenin-Y
			// But coordinate system of SGP Engine is like D3D Right-X Up-Y Screenin-Z
			// Node Transform Matrix should be swaped.
			/*
			If your matrix looks like this:
			{ rx, ry, rz, 0 }  
			{ ux, uy, uz, 0 }  
			{ lx, ly, lz, 0 }  
			{ px, py, pz, 1 }
			To change it from left to right or right to left, flip it like this:
			{ rx, rz, ry, 0 }  
			{ lx, lz, ly, 0 }  
			{ ux, uz, uy, 0 }  
			{ px, pz, py, 1 }
			*/
			Point3 Row0 = tm.GetRow(0);
			Point3 Row1 = tm.GetRow(1);
			Point3 Row2 = tm.GetRow(2);
			Point3 Row3 = tm.GetRow(3);
			sgp::swapVariables( Row0.y,  Row0.z );
			sgp::swapVariables( Row1.x,  Row2.x );
			sgp::swapVariables( Row1.y,  Row2.z );
			sgp::swapVariables( Row1.z,  Row2.y );
			sgp::swapVariables( Row3.y,  Row3.z );
			tm.SetRow(0, Row0);
			tm.SetRow(1, Row1);
			tm.SetRow(2, Row2);
			tm.SetRow(3, Row3);


			Point3 trans;
			Quat quat;
			Point3 scale;

			{
				// calculate the translation component
				Point3 p;
				p = tm.GetTrans();

				trans.x = p.x;
				trans.y = p.y;
				trans.z = p.z;

				scale.x = tm.GetRow(0).Length();
				scale.y = tm.GetRow(1).Length();
				scale.z = tm.GetRow(2).Length();

				tm.NoScale();

				// calculate the rotation component
				Quat q(tm);
				if( tracks[nNodeId]->bMirror )
				{
					float m[4][3];
					memcpy( m, &tm, sizeof(float)*4*3 );

					m[0][0] *= -1;
					m[1][0] *= -1;
					m[2][0] *= -1;
	
					Matrix3 mm(m);

					Quat q0(mm);
					q = q0;
				}

				quat.x = q.x;
				quat.y = q.y;
				quat.z = q.z;
				quat.w = q.w;
			}


			pTrack->vectorTrans.getReference(nFrameId) = trans;
			pTrack->vectorRot.getReference(nFrameId) = quat;
			pTrack->vectorScale.getReference(nFrameId) = scale;

			float fv = pNode->GetVisibility( t );
			if( fv == 0 )
				pTrack->vectorVisible.getReference(nFrameId) = false;
			else
				pTrack->vectorVisible.getReference(nFrameId) = true;
		}
	}
	StopProgressInfo();
}