示例#1
0
MStatus simulateBoids::doIt( const MArgList& args )
{
	
	//	Description: implements the MEL boids command
	//	Arguments: args - the argument list that was passes to the command from MEL

	MStatus status = MS::kSuccess;

	
    /****************************************
	*	building thread/dll data structure  *
	****************************************/

	InfoCache infoCache;
	SimulationParameters simParams;
	RulesParameters *applyingRules;
	double progressBar=0;
	double aov=pi/3;
	int i,numberOfDesires=0;
	
	// params retrievement
	MSelectionList sel;
	MObject node;
	MFnDependencyNode nodeFn;
	MFnTransform locatorFn;
	MPlug plug;

	// simulation params
	int simulationLengthValue;		// [int] in seconds
	int framesPerSecondValue;		// [int]
	int startFrameValue;			// [int]
	int boidsNumberValue;			// [int]
	// export params
	MString logFilePathValue;		// [char *]
	MString logFileNameValue;		// [char *]
	int logFileTypeValue;			// 0 = nCache; 1 = log file; 2 = XML; 
	// locomotion params
	int locomotionModeValue;		// [int]
	double maxSpeedValue;			// [double]
	double maxForceValue;			// [double]

	// double mass=1;				// [double]

	MTime currentTime, maxTime;
	MPlug plugX, plugY, plugZ;
	double tx, ty, tz;
	int frameLength ;
	Vector * leader = NULL;

	MStatus leaderFound=MStatus::kFailure;

	MGlobal::getActiveSelectionList(sel);
	for ( MItSelectionList listIter(sel); !listIter.isDone(); listIter.next() )
	{
		listIter.getDependNode(node);
		switch(node.apiType())
		{
			case MFn::kTransform:
				// get locator transform to follow
				leaderFound=locatorFn.setObject(node);
				cout << locatorFn.name().asChar() << " is selected as locator" << endl;
				break;
			case MFn::kPluginDependNode:
				nodeFn.setObject(node);
				cout << nodeFn.name().asChar() << " is selected as brain" << endl;
				break;
			default:
				break;
		}
		cout<< node.apiTypeStr()<<endl;
	}

	// rules params
	setRuleVariables(alignment);
	setRuleVariables(cohesion);
	setRuleVariables(separation);
	setRuleVariables(follow);

	getPlugValue(simulationLength);
	getPlugValue(framesPerSecond);
	getPlugValue(startFrame);
	getPlugValue(boidsNumber);
	getPlugValue(logFileType);
	getRulePlugValue(alignment);
	getRulePlugValue(cohesion);
	getRulePlugValue(separation);
	getRulePlugValue(follow);
	getPlugValue(locomotionMode);
	getPlugValue(maxSpeed);
	getPlugValue(maxForce);
	getTypePlugValue(logFilePath);
	getTypePlugValue(logFileName);
		// counting active rules number
	if(alignmentActiveValue)
		numberOfDesires++;
	if(cohesionActiveValue)
		numberOfDesires++;
	if(separationActiveValue)
		numberOfDesires++;
	if(followActiveValue)
		numberOfDesires++;


	currentTime = MTime((double)startFrameValue);														// MAnimControl::minTime();
	maxTime = MTime((double)(startFrameValue + (simulationLengthValue * framesPerSecondValue)));		// MAnimControl::maxTime();
	cout << "time unit enum (6 is 24 fps): " << currentTime.unit() << endl;	
	plugX = locatorFn.findPlug( MString( "translateX" ), &status );
	plugY = locatorFn.findPlug( MString( "translateY" ), &status );
	plugZ = locatorFn.findPlug( MString( "translateZ" ), &status );
	frameLength = simulationLengthValue * framesPerSecondValue;
	
	if(leaderFound==MS::kSuccess)
	{
		leader = new Vector[frameLength];	
		while ( currentTime < maxTime )
		{
			{
				int index = (int)currentTime.value() - startFrameValue;
				/*
				MGlobal::viewFrame(currentTime);
				pos = locatorFn.getTranslation(MSpace::kWorld);
				cout << "pos: " << pos.x << " " << pos.y << " " << pos.z << endl;
				*/
				status = plugX.getValue( tx, MDGContext(currentTime) );
				status = plugY.getValue( ty, MDGContext(currentTime) );
				status = plugZ.getValue( tz, MDGContext(currentTime) );

				leader[index].x = tx;
				leader[index].y = ty;
				leader[index].z = tz;
				//cout << "pos at time " << currentTime.value() << " has x: " << tx << " y: " << ty << " z: " << tz << endl;
				currentTime++;
			}	
		}
	}

	simParams.fps=framesPerSecondValue;
	simParams.lenght=simulationLengthValue;
	simParams.numberOfBoids=boidsNumberValue;
	simParams.maxAcceleration=maxForceValue;
	simParams.maxVelocity=maxSpeedValue;
	simParams.simplifiedLocomotion=TRUE;


	
	
	applyingRules=new RulesParameters[numberOfDesires];
	

	// cache settings
	MString saveString;
	saveString = logFilePathValue+"/"+logFileNameValue;
	infoCache.fileName=new char[saveString.length()+1];
	memcpy(infoCache.fileName,saveString.asChar(),sizeof(char)*(saveString.length()+1));
	infoCache.cacheFormat=ONEFILE;
	infoCache.fps=framesPerSecondValue;
	infoCache.start=startFrameValue/framesPerSecondValue;
	infoCache.end=simulationLengthValue+infoCache.start;	
	infoCache.loging=FALSE;
	infoCache.option=POSITIONVELOCITY;
	infoCache.particleSysName="BoidsNParticles";
	infoCache.saveMethod=MAYANCACHE;

	for(i=0;i<numberOfDesires;i++)
	{
		applyingRules[i].enabled=TRUE;
		applyingRules[i].precedence=1;
		applyingRules[i].aov=aov;
		applyingRules[i].visibilityOption=FALSE;
	}	

	if(cohesionActiveValue==0)
		applyingRules[COHESIONRULE].enabled=FALSE;
	else
	{
		applyingRules[COHESIONRULE].ruleName=COHESIONRULE;
		applyingRules[COHESIONRULE].ruleFactor=cohesionFactorValue;
		applyingRules[COHESIONRULE].ruleRadius=cohesionRadiusValue;
		applyingRules[COHESIONRULE].ruleWeight=cohesionWeightValue;
	}

	if(separationActiveValue==0)
		applyingRules[SEPARATIONRULE].enabled=FALSE;
	else
	{
		applyingRules[SEPARATIONRULE].ruleName=SEPARATIONRULE;
		applyingRules[SEPARATIONRULE].ruleFactor=separationFactorValue;
		applyingRules[SEPARATIONRULE].ruleRadius=separationRadiusValue;
		applyingRules[SEPARATIONRULE].ruleWeight=separationWeightValue;
	}

	if(alignmentActiveValue==0)
		applyingRules[ALIGNMENTRULE].enabled=FALSE;
	else
	{
		applyingRules[ALIGNMENTRULE].ruleName=ALIGNMENTRULE;
		applyingRules[ALIGNMENTRULE].ruleFactor=alignmentFactorValue;
		applyingRules[ALIGNMENTRULE].ruleRadius=alignmentRadiusValue;
		applyingRules[ALIGNMENTRULE].ruleWeight=alignmentWeightValue;
	}
	
	if(followActiveValue==0)
		applyingRules[FOLLOWRULE].enabled=FALSE;
	else
	{
		applyingRules[FOLLOWRULE].ruleName=FOLLOWRULE;
		applyingRules[FOLLOWRULE].ruleRadius=followRadiusValue;
		applyingRules[FOLLOWRULE].ruleFactor=followFactorValue;
		applyingRules[FOLLOWRULE].ruleWeight=followWeightValue;
	}
	

	// initializing simulation parameters
	boidInit(numberOfDesires, applyingRules, simParams , infoCache, leader);

	DLLData datadll;
	// preparing threads pool
	status = MThreadPool::init();
	
	if (status==MStatus::kSuccess)
	{
		MThreadPool::newParallelRegion(ThreadsCreator, &datadll);
		setResult( "Command executed!\n" );
		CHECK_MSTATUS(MProgressWindow::endProgress());
		MThreadPool::release();
	}

	switch(datadll.result)
	{
	case 0:
		status=MS::kSuccess;
		break;

	default:
		status=MS::kFailure;
	}

	MThreadPool::release();
	return status;
}
void DMPDSExporter::fillBones( DMPSkeletonData::SubSkeletonStruct* subSkel, string parent, DMPParameters* param, MDagPath& jointDag )
{
	MStatus status;
	if (jointDag.apiType() != MFn::kJoint)
	{
		return; // early out.
	}
	DMPSkeletonData::BoneStruct newBone;
	newBone.boneHandle = (unsigned int)subSkel->bones.size();
	newBone.name = jointDag.partialPathName().asUTF8();
	newBone.parentName = parent;

	MFnIkJoint fnJoint(jointDag, &status);
	//	matrix = [S] * [RO] * [R] * [JO] * [IS] * [T]
	/*
		These matrices are defined as follows:
		•[S] : scale
		•[RO] : rotateOrient (attribute name is rotateAxis)
		•[R] : rotate
		•[JO] : jointOrient
		•[IS] : parentScaleInverse
		•[T] : translate

		The methods to get the value of these matrices are:
		•[S] : getScale
		•[RO] : getScaleOrientation
		•[R] : getRotation
		•[JO] : getOrientation
		•[IS] : (the inverse of the getScale on the parent transformation matrix)
		•[T] : translation

	*/
	MVector trans = fnJoint.getTranslation(MSpace::kTransform);
	double scale[3];
	fnJoint.getScale(scale);
	MQuaternion R, RO, JO;
	fnJoint.getScaleOrientation(RO);
	fnJoint.getRotation(R);
	fnJoint.getOrientation(JO);
	MQuaternion rot = RO * R * JO; 
	
	newBone.translate[0] = trans.x * param->lum;
	newBone.translate[1] = trans.y * param->lum;
	newBone.translate[2] = trans.z * param->lum;

	newBone.orientation[0] = rot.w;
	newBone.orientation[1] = rot.x;
	newBone.orientation[2] = rot.y;
	newBone.orientation[3] = rot.z;

	newBone.scale[0] = scale[0];
	newBone.scale[1] = scale[1];
	newBone.scale[2] = scale[2];

	subSkel->bones.push_back(newBone);
	// Load child joints
	for (unsigned int i=0; i<jointDag.childCount();i++)
	{
		MObject child;
		child = jointDag.child(i);
		MDagPath childDag = jointDag;
		childDag.push(child);
		fillBones(subSkel, newBone.name, param, childDag);
	}
	// now go for animations
	if (param->bExportSkelAnimation)
	{
		for (unsigned int i = 0; i < subSkel->animations.size(); ++i)
		{
			DMPSkeletonData::TransformAnimation& anim = subSkel->animations[i];
			DMPSkeletonData::TransformTrack subTrack;
			subTrack.targetBone = newBone.name;

			MPlug		plugT;	// translate
 			MPlug		plugR;	// R
 			MPlug		plugRO;	// RO
 			MPlug		plugJO;	// JO
			MPlug		plugS;	// scale
			double		dataT[3];
			double		dataR[3];
			double		dataRO[3];
			double		dataJO[3];
			double		dataS[3];
			MFnDependencyNode	fnDependNode( jointDag.node(), &status );
			
			plugT = fnDependNode.findPlug("translate", false, &status);
 			plugR = fnDependNode.findPlug("rotate", false, &status);
 			plugRO = fnDependNode.findPlug("rotateAxis", false, &status);
 			plugJO = fnDependNode.findPlug("jointOrient", false, &status);
			plugS = fnDependNode.findPlug("scale", false, &status);

			float timeStep = param->samplerRate;
			if (param->animSampleType == DMPParameters::AST_Frame)
			{
				timeStep /= param->fps;
			}
			for (float curTime = anim.startTime; curTime <= anim.endTime; curTime += timeStep)
			{
				MTime		mayaTime;
				DMPSkeletonData::TransformKeyFrame keyframe;
				keyframe.time = curTime - anim.startTime;
				mayaTime.setUnit(MTime::kSeconds);
				mayaTime.setValue(curTime);

				// Get its value at the specified Time.
				plugT.child(0).getValue(dataT[0], MDGContext(mayaTime));
				plugT.child(1).getValue(dataT[1], MDGContext(mayaTime));
				plugT.child(2).getValue(dataT[2], MDGContext(mayaTime));

				plugR.child(0).getValue(dataR[0], MDGContext(mayaTime));
				plugR.child(1).getValue(dataR[1], MDGContext(mayaTime));
				plugR.child(2).getValue(dataR[2], MDGContext(mayaTime));

				plugRO.child(0).getValue(dataRO[0], MDGContext(mayaTime));
				plugRO.child(1).getValue(dataRO[1], MDGContext(mayaTime));
				plugRO.child(2).getValue(dataRO[2], MDGContext(mayaTime));

				plugJO.child(0).getValue(dataJO[0], MDGContext(mayaTime));
				plugJO.child(1).getValue(dataJO[1], MDGContext(mayaTime));
				plugJO.child(2).getValue(dataJO[2], MDGContext(mayaTime));

				plugS.child(0).getValue(dataS[0], MDGContext(mayaTime));
				plugS.child(1).getValue(dataS[1], MDGContext(mayaTime));
				plugS.child(2).getValue(dataS[2], MDGContext(mayaTime));

				// fill the frame.
				keyframe.translate[0] = dataT[0] * param->lum;
				keyframe.translate[1] = dataT[1] * param->lum;
				keyframe.translate[2] = dataT[2] * param->lum;
				// calculate quaternion.
				MEulerRotation	rotR(dataR[0], dataR[1], dataR[2]);
				MEulerRotation	rotRO(dataRO[0], dataRO[1], dataRO[2]);
				MEulerRotation	rotJO(dataJO[0], dataJO[1], dataJO[2]);

				MQuaternion finalRot = rotRO.asQuaternion()*rotR.asQuaternion()*rotJO.asQuaternion();
				
				keyframe.orientation[0] = finalRot.w;
				keyframe.orientation[1] = finalRot.x;
				keyframe.orientation[2] = finalRot.y;
				keyframe.orientation[3] = finalRot.z;

				keyframe.scale[0] = dataS[0];
				keyframe.scale[1] = dataS[1];
				keyframe.scale[2] = dataS[2];

				subTrack.frames.push_back(keyframe);
			}
			anim.tracks.push_back(subTrack);
		}
	}
}