void EntityInstanceNode::Flatten() { EntityNode& instanceClassNode = EntityNode::Get( m_Entity->GetEntity()->GetPath() ); if( instanceClassNode == EntityNode::Null ) return; MFnDagNode instanceFn( thisMObject() ); MFnDagNode nodeFn( instanceClassNode.thisMObject() ); u32 len = nodeFn.childCount(); MDagPath path; MFnTransform newTransformFn; MObject newTransform = newTransformFn.create(); MTransformationMatrix matrix = instanceFn.transformationMatrix(); newTransformFn.set( matrix ); newTransformFn.getPath( path ); for( u32 i = 0; i < len; ++i ) { MFnDagNode nodeFn( nodeFn.child( i ) ); MDagPath child; nodeFn.getPath( child ); MDagPath result; Maya::duplicate( child, path, result, false, false ); } Maya::LockHierarchy( thisMObject(), false ); }
// // This callback gets called for the PostToolChanged and SelectionChanged events. // It checks to see if the current context is the dragAttrContext, which is the context // applied by default when a custom numeric attribute is selected in the channel box. // In this case, the customAttrManip context is set. // static void eventCB(void * data) { // This check prevents recursion from happening when overriding the manip. if (isSetting) return; MSelectionList selList; MGlobal::getActiveSelectionList(selList); MString curCtx = ""; MGlobal::executeCommand("currentCtx", curCtx); MDagPath path; MObject dependNode; for (unsigned int i=0; i<selList.length(); i++) { if ((selList.getDependNode(i, dependNode)) == MStatus::kSuccess) { MFnTransform node; if (node.hasObj(dependNode)) node.setObject(dependNode); else continue; if (node.typeId() == rockingTransformNode::id) { // If the current context is the dragAttrContext, check to see // if the custom channel box attributes are selected. If so, // attach the custom manipulator. if ((curCtx == "dragAttrContext") || (curCtx == "")) { // Make sure that the correct channel box attributes are selected // before setting the tool context. unsigned int c; MStringArray cboxAttrs; MGlobal::executeCommand( "channelBox -q -selectedMainAttributes $gChannelBoxName", cboxAttrs); for (c=0; c<cboxAttrs.length(); c++) { if (cboxAttrs[c] == customAttributeString) { isSetting = true; MGlobal::executeCommand("setToolTo myCustomAttrContext"); isSetting = false; return; } } } if ((curCtx == "moveSuperContext") || (curCtx == "manipMoveContext") || (curCtx == "")) { isSetting = true; MGlobal::executeCommand("setToolTo myCustomTriadContext"); isSetting = false; return; } } } } }
MStatus lrutils::makeHomeNull(MObject obj, MFnTransform& transformFn, MObject& groupObj) { MStatus status = MS::kFailure; status = transformFn.setObject(obj); MyCheckStatusReturn(status, "invalid MObject provided for MFnTransform.setObject()"); if( status == MS::kSuccess ) { MDagModifier dagMod; groupObj = dagMod.createNode( "transform", MObject::kNullObj, &status ); MyCheckStatusReturn(status, "MDagModifier.createNode() failed"); dagMod.doIt(); MFnTransform groupFn; groupFn.setObject(groupObj); groupFn.set(transformFn.transformation()); groupFn.addChild(obj); MString groupName = transformFn.name(); groupName = groupName.substring(0, groupName.numChars() - 4); groupName += "GRP"; groupFn.setName(groupName); } return status; }
MObject HesperisTransformCreator::create(BaseTransform * data, MObject & parentObj, const std::string & nodeName) { MObject otm = MObject::kNullObj; if(!HesperisIO::FindNamedChild(otm, nodeName, parentObj)) { MFnTransform ftransform; otm = ftransform.create(parentObj); std::string validName(nodeName); SHelper::noColon(validName); ftransform.setName(validName.c_str()); } // MGlobal::displayInfo(MString("todo transform in ")+nodeName.c_str()); return otm; }
void GDExporter::GetUniqueRenderContexts( MFnTransform& transform, std::list<GDRenderContext>& uniqueContexts ) { for(unsigned int i = 0; i < transform.childCount(); ++i) { if( transform.child(i).apiType() == MFn::kMesh ) { MFnMesh childMesh( transform.child(i) ); if( childMesh.isIntermediateObject() ) continue; MDagPath meshPath; childMesh.getPath(meshPath); MFnDependencyNode depNode(meshPath.node()); MStatus fpResult; MPlug gdRenderContextPlug = childMesh.findPlug("GDRenderContext", &fpResult); if( fpResult != MS::kSuccess ) continue; GDRenderContext newContext(gdRenderContextPlug); bool bFound = false; std::list<GDRenderContext>::iterator uniqueIter = uniqueContexts.begin(); for(; uniqueIter != uniqueContexts.end(); ++uniqueIter ) { if( (*uniqueIter) == newContext ) { bFound = true; break; } } if( bFound == false ) uniqueContexts.push_back( newContext ); else gdRenderContextPlug.child(0).setValue( (*uniqueIter).name.c_str() ); } else if( transform.child(i).apiType() == MFn::kTransform ) { MFnTransform childTransform( transform.child(i) ); GetUniqueRenderContexts( childTransform, uniqueContexts ); } } }
MStatus lrutils::makeGroup(MObject & obj, MString name) { MStatus status = MS::kFailure; MDagModifier dagMod; MObject groupObj = dagMod.createNode( "transform", MObject::kNullObj, &status ); MyCheckStatusReturn(status, "MDagModifier.createNode() failed"); dagMod.doIt(); MFnTransform groupFn; groupFn.setObject(groupObj); MString groupName = name; groupName += "_GRP"; groupFn.setName(groupName); obj = groupObj; return status; }
void Exporter::RecursiveJointExtraction(MFnTransform& joint, int parentIndex){ Bone output; output.parent = parentIndex; output.invBindPose = joint.transformation().asMatrixInverse().matrix; MItDependencyNodes matIt(MFn::kAnimCurve); while (!matIt.isDone()) { MFnAnimCurve animCurve(matIt.item()); if (!strcmp(animCurve.name().substring(0, joint.name().length() - 1).asChar(), joint.name().asChar())){ cout << animCurve.name().asChar() << endl; std::string type = animCurve.name().substring(joint.name().length(), animCurve.name().length()).asChar(); output.frames.resize(animCurve.time(animCurve.numKeys() - 1).value()); for (int i = 0; i < output.frames.size(); i++) { MTime time; time.setValue(i); output.frames[i].time = time.value(); if (!strcmp(type.c_str(), "_translateX")){ cout << animCurve.evaluate(time) << endl; output.frames[i].trans.x = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_translateY")){ cout << animCurve.evaluate(time) << endl; output.frames[i].trans.y = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_translateZ")){ cout << animCurve.evaluate(time) << endl; output.frames[i].trans.z = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_rotateX")){ cout << animCurve.evaluate(time) << endl; output.frames[i].rot.x = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_rotateY")){ cout << animCurve.evaluate(time) << endl; output.frames[i].rot.y = animCurve.evaluate(time); } if (!strcmp(type.c_str(), "_rotateZ")){ cout << animCurve.evaluate(time) << endl; output.frames[i].rot.z = animCurve.evaluate(time); } } } matIt.next(); } scene_.skeleton.push_back(output); int children = joint.childCount(); int parent = scene_.skeleton.size() - 1; for (int i = 0; i < children; i++) RecursiveJointExtraction(MFnTransform(joint.child(i)), parent); };
MStatus lrutils::setParentConstraintOffset(MObject constraintObj, MTransformationMatrix transform) { MStatus status = MS::kFailure; MFnTransform constraintFn; status = constraintFn.setObject( constraintObj ); MyCheckStatusReturn(status, "invalid MObject provided for MFnTransform.setObject()"); MString constraintName = constraintFn.name(); if ( status = MS::kSuccess ) { MVector vTranslation = transform.getTranslation(MSpace::kTransform); MGlobal::executeCommand( "setAttr \""+constraintName+".target[0].targetOffsetTranslateX\" "+vTranslation.x+";"); MGlobal::executeCommand( "setAttr \""+constraintName+".target[0].targetOffsetTranslateY\" "+vTranslation.y+";"); MGlobal::executeCommand( "setAttr \""+constraintName+".target[0].targetOffsetTranslateZ\" "+vTranslation.z+";"); double* rotation = new double[3]; MTransformationMatrix::RotationOrder rotOrder = MTransformationMatrix::kXYZ; transform.getRotation(rotation,rotOrder); MGlobal::executeCommand( "setAttr \""+constraintName+".target[0].targetOffsetRotateX\" "+rotation[0]+";"); MGlobal::executeCommand( "setAttr \""+constraintName+".target[0].targetOffsetRotateY\" "+rotation[1]+";"); MGlobal::executeCommand( "setAttr \""+constraintName+".target[0].targetOffsetRotateZ\" "+rotation[2]+";"); } return status; }
bool HesperisIO::ReadTransforms(HBase * parent, MObject &target) { std::vector<std::string > tmNames; parent->lsTypedChild<HTransform>(tmNames); std::vector<std::string>::const_iterator it = tmNames.begin(); for(;it!=tmNames.end();++it) { std::string nodeName = *it; SHelper::behead(nodeName, parent->pathToObject()); SHelper::behead(nodeName, "/"); HBase child(*it); MObject otm = MObject::kNullObj; if(!FindNamedChild(otm, nodeName, target)) { MFnTransform ftransform; otm = ftransform.create(target); SHelper::noColon(nodeName); ftransform.setName(nodeName.c_str()); } ReadTransforms(&child, otm); ReadCurves(&child, otm); child.close(); } return true; }
double splineSolverNode::getJointsTotalLenght() { double totalLength = 0; MPoint pBaseJoint, pEndJoint; for (int i = 0; i < joints.size(); i++) { MFnIkJoint j( joints[i]); pBaseJoint = j.rotatePivot(MSpace::kWorld); if( i == joints.size() - 1) //Effector Position pEndJoint = tran.rotatePivot(MSpace::kWorld); else { //get position of next joint MFnIkJoint j2( joints[i + 1]); pEndJoint = j2.rotatePivot(MSpace::kWorld); } MVector vBaseJoint(pBaseJoint[0]-pEndJoint[0], pBaseJoint[1]-pEndJoint[1], pBaseJoint[2]-pEndJoint[2]); totalLength += vBaseJoint.length(); } return totalLength; }
MStatus lrutils::setLocation(MObject obj, MVectorArray location, MFnTransform& transformFn, bool translate, bool rotation, bool scale) { MStatus status = MS::kFailure; status = transformFn.setObject(obj); MyCheckStatusReturn(status, "invalid MObject provided for MFnTransform.setObject()"); if( status == MS::kSuccess ) { if(translate) { MVector vTranslation = location[0] ; //stringstream text; text << "(" << vTranslation.x << ", " << vTranslation.y << ", " << vTranslation.z << ")"; //MGlobal::displayInfo( text.str().c_str() ); status = transformFn.setTranslation(vTranslation, MSpace::kTransform); stringstream text; text << "MFnTransform.setTranslation() failed, status code [" << status.errorString().asChar() << "]"; MyCheckStatusReturn(status, text.str().c_str() ); vTranslation = transformFn.getTranslation(MSpace::kWorld); //text.clear(); text << "(" << vTranslation.x << ", " << vTranslation.y << ", " << vTranslation.z << ")"; //MGlobal::displayInfo( text.str().c_str() ); } if(rotation) { MVector vRotation = location[1]*3.141592/180.0; MEulerRotation eRotation = MEulerRotation(vRotation); status = transformFn.setRotation(eRotation); } if(scale) { MVector vScale = location[2]; double* scale = new double[3]; vScale.get(scale); transformFn.setScale(scale); //make the scale of the controller the identity MGlobal::executeCommand("select -r "+transformFn.name()+";"); MGlobal::executeCommand("makeIdentity -s true -apply true;"); } } return status; }
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; }
MStatus splineSolverNode::doSimpleSolver() // // Solve single joint in the x-y plane // // - first it calculates the angle between the handle and the end-effector. // - then it determines which way to rotate the joint. // { //Do Real Solve // MStatus stat; float curCurveLength = curveFn.length(); MPlug crvLengPlug = fnHandle.findPlug("cvLen"); double initCurveLength = crvLengPlug.asDouble(); //Twist MPlug twistRamp = fnHandle.findPlug("twistRamp"); MRampAttribute curveAttribute( twistRamp, &stat ); MPlug startTwistPlug = fnHandle.findPlug("strtw"); double startTwist = startTwistPlug.asDouble(); MPlug endTwistPlug = fnHandle.findPlug("endtw"); double endTwist = endTwistPlug.asDouble(); //Scale Ramp MPlug scaleRamp = fnHandle.findPlug("scaleRamp"); MRampAttribute curveScaleAttribute( scaleRamp, &stat ); //Roll MPlug rollPlug = fnHandle.findPlug("roll"); double roll = rollPlug.asDouble(); MPlug strPlug = fnHandle.findPlug("str"); float stretchRatio = strPlug.asDouble(); float normCrvLength = curCurveLength / initCurveLength; double scale[3] = {1 +stretchRatio*(normCrvLength -1), 1, 1}; //Get Anchor Position MPlug ancPosPlug = fnHandle.findPlug("ancp"); double anchorPos = ancPosPlug.asDouble(); MPlug jointsTotLengthPlug = fnHandle.findPlug("jsLen"); double jointsTotalLength = jointsTotLengthPlug.asDouble(); double difLengthCurveJoints = curCurveLength - (jointsTotalLength * scale[0]); float startLength = 0.0 + anchorPos*( difLengthCurveJoints ); float parm = curveFn.findParamFromLength( startLength ); MPoint pBaseJoint, pEndJoint; curveFn.getPointAtParam( parm, pBaseJoint ); //get Init normal MPlug initNormalPlug = fnHandle.findPlug("norm"); double nx = initNormalPlug.child(0).asDouble(); double ny = initNormalPlug.child(1).asDouble(); double nz = initNormalPlug.child(2).asDouble(); MVector eyeUp( nx, ny, nz ); //get Init Tangent MPlug initTangentPlug = fnHandle.findPlug("tang"); double tx = initTangentPlug.child(0).asDouble(); double ty = initTangentPlug.child(1).asDouble(); double tz = initTangentPlug.child(2).asDouble(); MVector eyeV( tx, ty, tz ); MFnIkJoint j( joints[0] ); j.setTranslation( MVector( pBaseJoint ), MSpace::kWorld ); float jointRotPercent = 1.0/joints.size(); float currJointRot = 0; float prevTwist = 0; double angle; //j.setScale(scale); for (int i = 0; i < joints.size(); i++) { MFnIkJoint j( joints[i]); pBaseJoint = j.rotatePivot(MSpace::kWorld); //Calculate Scale float scaleValue; curveScaleAttribute.getValueAtPosition(currJointRot, scaleValue, &stat); //if ( scale[0] >= 1 ) // Stretch scale[1] = 1 + scaleValue * ( 1 - scale[0] ); /* else //Squash scale[1] = 1 + scaleValue * ( 1.0 - scale[0] ); */ if (scale[1] < 0) scale[1] = 0; scale[2] = scale[1]; j.setScale(scale); //j.setRotation( rot, j.rotationOrder() ); if( i == joints.size() - 1) //Effector Position pEndJoint = tran.rotatePivot(MSpace::kWorld); else { //get position of next joint MFnIkJoint j2( joints[i + 1]); pEndJoint = j2.rotatePivot(MSpace::kWorld); } MVector vBaseJoint(pBaseJoint[0]-pEndJoint[0], pBaseJoint[1]-pEndJoint[1], pBaseJoint[2]-pEndJoint[2]); startLength += vBaseJoint.length(); MVector eyeAim(1.0,0.0,0.0); MPoint pFinalPos; float parm = curveFn.findParamFromLength( startLength ); //Aim to final Pos curveFn.getPointAtParam( parm, pFinalPos, MSpace::kWorld ); MVector eyeU(pBaseJoint[0]-pFinalPos[0], pBaseJoint[1]-pFinalPos[1], pBaseJoint[2]-pFinalPos[2]); eyeU.normalize(); MVector eyeW( eyeU ^ eyeV ); eyeW.normalize(); eyeV = eyeW ^ eyeU; MQuaternion qU( -eyeAim, eyeU ); MVector upRotated( eyeUp.rotateBy( qU )); angle = acos( upRotated*eyeV ); //Calculate Twist { float twistValue; curveAttribute.getValueAtPosition(currJointRot, twistValue, &stat); double rotVal = (1-twistValue)*startTwist + twistValue*endTwist; angle += MAngle(rotVal, MAngle::kDegrees).asRadians(); currJointRot += jointRotPercent; } //Calculate Roll angle += roll; MQuaternion qV(angle, eyeU); MQuaternion q(qU*qV); j.setRotation( q, MSpace::kWorld ); } return MS::kSuccess; }
/******************************************************************************************************** * Method to translate a single camera * ********************************************************************************************************/ MStatus OgreExporter::writeCamera(MFnCamera& camera) { MPlug plug; MPlugArray srcplugarray; double dist; MAngle angle; MFnTransform* cameraTransform = NULL; MFnAnimCurve* animCurve = NULL; // get camera transform for (int i=0; i<camera.parentCount(); i++) { if (camera.parent(i).hasFn(MFn::kTransform)) { cameraTransform = new MFnTransform(camera.parent(i)); continue; } } // start camera description m_params.outCameras << "camera " << cameraTransform->partialPathName().asChar() << "\n"; m_params.outCameras << "{\n"; //write camera type m_params.outCameras << "\ttype "; if (camera.isOrtho()) m_params.outCameras << "ortho\n"; else m_params.outCameras << "persp\n"; // write translation data m_params.outCameras << "\ttranslation\n"; m_params.outCameras << "\t{\n"; //translateX m_params.outCameras << "\t\tx "; plug = cameraTransform->findPlug("translateX"); if (plug.isConnected() && m_params.exportCamerasAnim) { plug.connectedTo(srcplugarray,true,false,&stat); for (int i=0; i < srcplugarray.length(); i++) { if (srcplugarray[i].node().hasFn(MFn::kAnimCurve)) { if (animCurve) delete animCurve; animCurve = new MFnAnimCurve(srcplugarray[i].node()); continue; } else if (i == srcplugarray.length()-1) { std::cout << "Invalid link to translateX attribute\n"; return MS::kFailure; } } m_params.outCameras << "anim " << animCurve->name().asChar() << "\n"; } else { plug.getValue(dist); m_params.outCameras << "= " << dist << "\n"; } //translateY m_params.outCameras << "\t\ty "; plug = cameraTransform->findPlug("translateY"); if (plug.isConnected() && m_params.exportCamerasAnim) { plug.connectedTo(srcplugarray,true,false,&stat); for (int i=0; i< srcplugarray.length(); i++) { if (srcplugarray[i].node().hasFn(MFn::kAnimCurve)) { if (animCurve) delete animCurve; animCurve = new MFnAnimCurve(srcplugarray[i].node()); continue; } else if (i == srcplugarray.length()-1) { std::cout << "Invalid link to translateY attribute\n"; return MS::kFailure; } } m_params.outCameras << "anim " << animCurve->name().asChar() << "\n"; } else { plug.getValue(dist); m_params.outCameras << "= " << dist << "\n"; } //translateZ m_params.outCameras << "\t\tz "; plug = cameraTransform->findPlug("translateZ"); if (plug.isConnected() && m_params.exportCamerasAnim) { plug.connectedTo(srcplugarray,true,false,&stat); for (int i=0; i< srcplugarray.length(); i++) { if (srcplugarray[i].node().hasFn(MFn::kAnimCurve)) { if (animCurve) delete animCurve; animCurve = new MFnAnimCurve(srcplugarray[i].node()); continue; } else if (i == srcplugarray.length()-1) { std::cout << "Invalid link to translateZ attribute\n"; return MS::kFailure; } } m_params.outCameras << "anim " << animCurve->name().asChar() << "\n"; } else { plug.getValue(dist); m_params.outCameras << "= " << dist << "\n"; } m_params.outCameras << "\t}\n"; // write rotation data m_params.outCameras << "\trotation\n"; m_params.outCameras << "\t{\n"; m_params.outCameras << "\t\tx "; //rotateX plug = cameraTransform->findPlug("rotateX"); if (plug.isConnected() && m_params.exportCamerasAnim) { plug.connectedTo(srcplugarray,true,false,&stat); for (int i=0; i< srcplugarray.length(); i++) { if (srcplugarray[i].node().hasFn(MFn::kAnimCurve)) { if (animCurve) delete animCurve; animCurve = new MFnAnimCurve(srcplugarray[i].node()); continue; } else if (i == srcplugarray.length()-1) { std::cout << "Invalid link to rotateX attribute\n"; return MS::kFailure; } } m_params.outCameras << "anim " << animCurve->name().asChar() << "\n"; } else { plug.getValue(angle); m_params.outCameras << "= " << angle.asDegrees() << "\n"; } //rotateY m_params.outCameras << "\t\ty "; plug = cameraTransform->findPlug("rotateY"); if (plug.isConnected() && m_params.exportCamerasAnim) { plug.connectedTo(srcplugarray,true,false,&stat); for (int i=0; i< srcplugarray.length(); i++) { if (srcplugarray[i].node().hasFn(MFn::kAnimCurve)) { if (animCurve) delete animCurve; animCurve = new MFnAnimCurve(srcplugarray[i].node()); continue; } else if (i == srcplugarray.length()-1) { std::cout << "Invalid link to rotateY attribute\n"; return MS::kFailure; } } m_params.outCameras << "anim " << animCurve->name().asChar() << "\n"; } else { plug.getValue(angle); m_params.outCameras << "= " << angle.asDegrees() << "\n"; } //rotateZ m_params.outCameras << "\t\tz "; plug = cameraTransform->findPlug("rotateZ"); if (plug.isConnected() && m_params.exportCamerasAnim) { plug.connectedTo(srcplugarray,true,false,&stat); for (int i=0; i< srcplugarray.length(); i++) { if (srcplugarray[i].node().hasFn(MFn::kAnimCurve)) { if (animCurve) delete animCurve; animCurve = new MFnAnimCurve(srcplugarray[i].node()); continue; } else if (i == srcplugarray.length()-1) { std::cout << "Invalid link to rotateZ attribute\n"; return MS::kFailure; } } m_params.outCameras << "anim " << animCurve->name().asChar() << "\n"; } else { plug.getValue(angle); m_params.outCameras << "= " << angle.asDegrees() << "\n"; } m_params.outCameras << "\t}\n"; // end camera description m_params.outCameras << "}\n\n"; if (cameraTransform != NULL) delete cameraTransform; if (animCurve != NULL) delete animCurve; return MS::kSuccess; }
// Creates an AnimChannel from a Maya compound attribute if there is meaningful // data. This means we found data that is non-identity. // // returns true if we extracted an AnimChannel and false otherwise (e.g., the // data was identity). static bool _GatherAnimChannel( XFormOpType opType, const MFnTransform& iTrans, MString parentName, MString xName, MString yName, MString zName, std::vector<AnimChannel>* oAnimChanList, bool isWritingAnimation, bool setOpName) { AnimChannel chan; chan.opType = opType; chan.isInverse = false; if (setOpName) { chan.opName = parentName.asChar(); } // We default to single precision (later we set the main translate op and // shear to double) chan.precision = UsdGeomXformOp::PrecisionFloat; unsigned int validComponents = 0; // this is to handle the case where there is a connection to the parent // plug but not to the child plugs, if the connection is there and you are // not forcing static, then all of the children are considered animated int parentSample = PxrUsdMayaUtil::getSampledType(iTrans.findPlug(parentName),false); // Determine what plug are needed based on default value & being // connected/animated MStringArray channels; channels.append(parentName+xName); channels.append(parentName+yName); channels.append(parentName+zName); GfVec3d nullValue(opType == SCALE ? 1.0 : 0.0); for (unsigned int i = 0; i<3; i++) { // Find the plug and retrieve the data as the channel default value. It // won't be updated if the channel is NOT ANIMATED chan.plug[i] = iTrans.findPlug(channels[i]); double plugValue = chan.plug[i].asDouble(); chan.defValue[i] = opType == ROTATE ? GfRadiansToDegrees(plugValue) : plugValue; chan.sampleType[i] = NO_XFORM; // If we allow animation and either the parentsample or local sample is // not 0 then we havea ANIMATED sample else we have a scale and the // value is NOT 1 or if the value is NOT 0 then we have a static xform if ((parentSample != 0 || PxrUsdMayaUtil::getSampledType(chan.plug[i], true) != 0) && isWritingAnimation) { chan.sampleType[i] = ANIMATED; validComponents++; } else if (!GfIsClose(chan.defValue[i], nullValue[i], 1e-7)) { chan.sampleType[i] = STATIC; validComponents++; } } // If there are valid component, then we will add the animation channel. // Rotates with 1 component will be optimized to single axis rotation if (validComponents>0) { if (opType == SCALE) { chan.usdOpType = UsdGeomXformOp::TypeScale; } else if (opType == TRANSLATE) { chan.usdOpType = UsdGeomXformOp::TypeTranslate; // The main translate is set to double precision if (parentName == "translate") { chan.precision = UsdGeomXformOp::PrecisionDouble; } } else if (opType == ROTATE) { chan.usdOpType = UsdGeomXformOp::TypeRotateXYZ; if (validComponents == 1) { if (chan.sampleType[0] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateX; if (chan.sampleType[1] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateY; if (chan.sampleType[2] != NO_XFORM) chan.usdOpType = UsdGeomXformOp::TypeRotateZ; } else { // Rotation Order ONLY applies to the "rotate" attribute if (parentName == "rotate") { switch (iTrans.rotationOrder()) { case MTransformationMatrix::kYZX: chan.usdOpType = UsdGeomXformOp::TypeRotateYZX; break; case MTransformationMatrix::kZXY: chan.usdOpType = UsdGeomXformOp::TypeRotateZXY; break; case MTransformationMatrix::kXZY: chan.usdOpType = UsdGeomXformOp::TypeRotateXZY; break; case MTransformationMatrix::kYXZ: chan.usdOpType = UsdGeomXformOp::TypeRotateYXZ; break; case MTransformationMatrix::kZYX: chan.usdOpType = UsdGeomXformOp::TypeRotateZYX; break; default: break; } } } } else if (opType == SHEAR) { chan.usdOpType = UsdGeomXformOp::TypeTransform; chan.precision = UsdGeomXformOp::PrecisionDouble; } else { return false; } oAnimChanList->push_back(chan); return true; } return false; }
MStatus lrutils::loadGeoReference(MString geoFilePath, MString geoName, MString & name, MObject & geoObj) { MStatus status = MS::kFailure; MString projPath = MGlobal::executeCommandStringResult(MString("workspace -q -rd;"),false,false); MString relativePath = geoFilePath.substring(2,geoFilePath.numChars() - 1); //assemble the full file path of the geometry file MString fullGeoPath = projPath + relativePath; //load the geometry file as a reference into the current scene //check to see if the referenced file has already been used MStringArray refNodeList; status = MFileIO::getReferences(refNodeList, true); MyCheckStatus(status, "getReferences failed"); int numReferences = 0; for(unsigned int i = 0; i < refNodeList.length(); i++) { MString tmp = refNodeList[i]; string tmp1 = tmp.asChar(); string tmp2 = fullGeoPath.asChar(); if(std::string::npos != tmp1.find(tmp2)) numReferences++; } string str (geoFilePath.asChar()); string key ("/"); size_t found = str.rfind(key); string fileName = str.substr(found+1,str.length()-found-4); string fileNamespace; if(numReferences > 0) { stringstream tmp; tmp << fileName << (numReferences+1); fileNamespace = tmp.str(); } else { fileNamespace = fileName; } { stringstream tmp; tmp << "file -r -type \"mayaAscii\" -gl -loadReferenceDepth \"all\" -namespace \"" << fileNamespace.c_str() << "\" -options \"v=0\" \"" << fullGeoPath.asChar() << "\";"; MString referenceCommand = MString(tmp.str().c_str()); MGlobal::executeCommand(referenceCommand); } //get the referenced geometry transform node and add the metaParent //attribute to it MSelectionList selection; if(numReferences > 0) { name += (boost::lexical_cast<string>(numReferences+1)).c_str(); } stringstream geoRefName; geoRefName << fileNamespace << ":" << geoName; MString mGeoRefName = MString(geoRefName.str().c_str()); status = selection.add( mGeoRefName, true ); MyCheckStatusReturn(status, "add geoRefName "+mGeoRefName+" to selection failed."); if(selection.length() ) selection.getDependNode(0, geoObj); MFnTransform transformFn; transformFn.setObject(geoObj); MFnMessageAttribute mAttr; MObject transformAttr = mAttr.create("metaParent", "metaParent"); transformFn.addAttribute(transformAttr); if( !geoObj.isNull() ) status = MS::kSuccess; return status; }
void MayaTransformWriter::pushTransformStack(const MFnTransform & iTrans, bool iForceStatic) { // inspect the translate addTranslate(iTrans, "translate", "translateX", "translateY", "translateZ", Alembic::AbcGeom::kTranslateHint, false, iForceStatic, false, mSample, mAnimChanList); // inspect the rotate pivot translate addTranslate(iTrans, "rotatePivotTranslate", "rotatePivotTranslateX", "rotatePivotTranslateY", "rotatePivotTranslateZ", Alembic::AbcGeom::kRotatePivotTranslationHint, false, iForceStatic, false, mSample, mAnimChanList); // inspect the rotate pivot addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY", "rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint, false, iForceStatic, false, mSample, mAnimChanList); // inspect rotate names MString rotateNames[3]; rotateNames[0] = "rotateX"; rotateNames[1] = "rotateY"; rotateNames[2] = "rotateZ"; unsigned int rotOrder[3]; // if this returns false then the rotation order was kInvalid or kLast MTransformationMatrix::RotationOrder eRotOrder(iTrans.rotationOrder()); if (util::getRotOrder(eRotOrder, rotOrder[0], rotOrder[1], rotOrder[2])) { addRotate(iTrans, "rotate", rotateNames, rotOrder, Alembic::AbcGeom::kRotateHint, iForceStatic, false, mSample, mAnimChanList, mRotateOpIndex); } // now look at the rotation orientation, aka rotate axis rotateNames[0] = "rotateAxisX"; rotateNames[1] = "rotateAxisY"; rotateNames[2] = "rotateAxisZ"; rotOrder[0] = 0; rotOrder[1] = 1; rotOrder[2] = 2; addRotate(iTrans, "rotateAxis", rotateNames, rotOrder, Alembic::AbcGeom::kRotateOrientationHint, iForceStatic, false, mSample, mAnimChanList, mRotateAxisOpIndex); // invert the rotate pivot if necessary addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY", "rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint, true, iForceStatic, false, mSample, mAnimChanList); // inspect the scale pivot translation addTranslate(iTrans, "scalePivotTranslate", "scalePivotTranslateX", "scalePivotTranslateY", "scalePivotTranslateZ", Alembic::AbcGeom::kScalePivotTranslationHint, false, iForceStatic, false, mSample, mAnimChanList); // inspect the scale pivot point addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY", "scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, false, iForceStatic, false, mSample, mAnimChanList); // inspect the shear addShear(iTrans, iForceStatic, mSample, mAnimChanList); // add the scale addScale(iTrans, "scale", "scaleX", "scaleY", "scaleZ", false, iForceStatic, false, mSample, mAnimChanList); // inverse the scale pivot point if necessary addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY", "scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, true, iForceStatic, false, mSample, mAnimChanList); // remember current rotation if (mFilterEulerRotations) { double xx(0), yy(0), zz(0); // there are 2 rotation order enum definitions: // MEulerRotation::RotationOrder = MTransformationMatrix::RotationOrder-1 if (getSampledRotation( mSample, mRotateOpIndex, xx, yy, zz )) { mPrevRotateSolution.setValue(xx, yy, zz, (MEulerRotation::RotationOrder)(eRotOrder-1)); } if (getSampledRotation( mSample, mRotateAxisOpIndex, xx, yy, zz )) { mPrevRotateAxisSolution.setValue(xx, yy, zz, MEulerRotation::kXYZ); } } }
MStatus splineSolverNode::preSolve() { MStatus stat; setRotatePlane(false); setSingleChainOnly(true); setPositionOnly(false); //Get Handle MIkHandleGroup * handle_group = handleGroup(); if (NULL == handle_group) { return MS::kFailure; } MObject handle = handle_group->handle( 0 ); MDagPath handlePath = MDagPath::getAPathTo( handle ); fnHandle.setObject( handlePath ); //Get Curve MPlug inCurvePlug = fnHandle.findPlug( "inCurve" ); MDataHandle curveHandle = inCurvePlug.asMDataHandle(); MObject inputCurveObject = curveHandle.asNurbsCurveTransformed(); curveFn.setObject( inputCurveObject ); float initCurveLength = curveFn.length(); MVector initNormal = curveFn.normal(0); MVector initTangent = curveFn.tangent(0); float stretchRatio = 1; // Get the position of the end_effector // MDagPath effectorPath; fnHandle.getEffector(effectorPath); tran.setObject( effectorPath ); // Get the start joint position // MDagPath startJointPath; fnHandle.getStartJoint( startJointPath ); joints.clear(); //Get Joints while (true) { effectorPath.pop(); joints.push_back( effectorPath ); if (effectorPath == startJointPath) break; } std::reverse(joints.begin(), joints.end()); if (!fnHandle.hasAttribute("str")) { //Add Custom Attributes to Handle MFnNumericAttribute fnAttr; MObject attr = fnAttr.create("stretchRatio", "str", MFnNumericData::kDouble, stretchRatio); fnAttr.setKeyable(1); fnAttr.setWritable(1); fnAttr.setMin(0); fnAttr.setMax(1); fnAttr.setHidden(0); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); attr = fnAttr.create("anchorPosition", "ancp", MFnNumericData::kDouble, 0.0); fnAttr.setKeyable(1); fnAttr.setWritable(1); fnAttr.setMin(0); fnAttr.setMax(1); fnAttr.setHidden(0); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); attr = fnAttr.create("curveLength", "cvLen", MFnNumericData::kDouble, initCurveLength); fnAttr.setKeyable(0); fnAttr.setWritable(1); fnAttr.setHidden(1); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); attr = fnAttr.create("initNormal", "norm", MFnNumericData::k3Double); fnAttr.setDefault(initNormal.x, initNormal.y, initNormal.z); fnAttr.setKeyable(0); fnAttr.setWritable(1); fnAttr.setHidden(1); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); attr = fnAttr.create("initTangent", "tang", MFnNumericData::k3Double); fnAttr.setDefault(initTangent.x, initTangent.y, initTangent.z); fnAttr.setKeyable(0); fnAttr.setWritable(1); fnAttr.setHidden(1); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); attr = fnAttr.create("jointsLength", "jsLen", MFnNumericData::kDouble, getJointsTotalLenght()); fnAttr.setKeyable(0); fnAttr.setWritable(1); fnAttr.setHidden(1); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); attr = fnAttr.create("startTwist", "strtw", MFnNumericData::kDouble, 0.0); fnAttr.setKeyable(1); fnAttr.setWritable(1); fnAttr.setHidden(0); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); attr = fnAttr.create("endTwist", "endtw", MFnNumericData::kDouble, 0.0); fnAttr.setKeyable(1); fnAttr.setWritable(1); fnAttr.setHidden(0); fnAttr.setStorable(1); fnAttr.setReadable(1); fnHandle.addAttribute(attr, MFnDependencyNode::kLocalDynamicAttr); MObject twistRamp = MRampAttribute::createCurveRamp("twistRamp", "twr"); fnHandle.addAttribute(twistRamp, MFnDependencyNode::kLocalDynamicAttr); MObject scaleRamp = MRampAttribute::createCurveRamp("scaleRamp", "scr"); fnHandle.addAttribute(scaleRamp, MFnDependencyNode::kLocalDynamicAttr); } else { MPlug strPlug = fnHandle.findPlug("str"); stretchRatio = strPlug.asDouble(); } return MS::kSuccess; }
// Populate the AnimationChannel vector with various ops based on the Maya // transformation logic If scale and/or rotate pivot are declared, create // inverse ops in the appropriate order void MayaTransformWriter::pushTransformStack( const MFnTransform& iTrans, const UsdGeomXformable& usdXformable, bool writeAnim) { // NOTE: I think this logic and the logic in MayaTransformReader // should be merged so the concept of "CommonAPI" stays centralized. // // By default we assume that the xform conforms to the common API // (xlate,pivot,rotate,scale,pivotINVERTED) As soon as we encounter any // additional xform (compensation translates for pivots, rotateAxis or // shear) we are not conforming anymore bool conformsToCommonAPI = true; // Keep track of where we have rotate and scale Pivots and their inverse so // that we can combine them later if possible unsigned int rotPivotIdx = -1, rotPivotINVIdx = -1, scalePivotIdx = -1, scalePivotINVIdx = -1; // Check if the Maya prim inheritTransform MPlug inheritPlug = iTrans.findPlug("inheritsTransform"); if (!inheritPlug.isNull()) { if(!inheritPlug.asBool()) { usdXformable.SetResetXformStack(true); } } // inspect the translate, no suffix to be closer compatibility with common API _GatherAnimChannel(TRANSLATE, iTrans, "translate", "X", "Y", "Z", &mAnimChanList, writeAnim, false); // inspect the rotate pivot translate if (_GatherAnimChannel(TRANSLATE, iTrans, "rotatePivotTranslate", "X", "Y", "Z", &mAnimChanList, writeAnim, true)) { conformsToCommonAPI = false; } // inspect the rotate pivot bool hasRotatePivot = _GatherAnimChannel(TRANSLATE, iTrans, "rotatePivot", "X", "Y", "Z", &mAnimChanList, writeAnim, true); if (hasRotatePivot) { rotPivotIdx = mAnimChanList.size()-1; } // inspect the rotate, no suffix to be closer compatibility with common API _GatherAnimChannel(ROTATE, iTrans, "rotate", "X", "Y", "Z", &mAnimChanList, writeAnim, false); // inspect the rotateAxis/orientation if (_GatherAnimChannel(ROTATE, iTrans, "rotateAxis", "X", "Y", "Z", &mAnimChanList, writeAnim, true)) { conformsToCommonAPI = false; } // invert the rotate pivot if (hasRotatePivot) { AnimChannel chan; chan.usdOpType = UsdGeomXformOp::TypeTranslate; chan.precision = UsdGeomXformOp::PrecisionFloat; chan.opName = "rotatePivot"; chan.isInverse = true; mAnimChanList.push_back(chan); rotPivotINVIdx = mAnimChanList.size()-1; } // inspect the scale pivot translation if (_GatherAnimChannel(TRANSLATE, iTrans, "scalePivotTranslate", "X", "Y", "Z", &mAnimChanList, writeAnim, true)) { conformsToCommonAPI = false; } // inspect the scale pivot point bool hasScalePivot = _GatherAnimChannel(TRANSLATE, iTrans, "scalePivot", "X", "Y", "Z", &mAnimChanList, writeAnim, true); if (hasScalePivot) { scalePivotIdx = mAnimChanList.size()-1; } // inspect the shear. Even if we have one xform on the xform list, it represents a share so we should name it if (_GatherAnimChannel(SHEAR, iTrans, "shear", "XY", "XZ", "YZ", &mAnimChanList, writeAnim, true)) { conformsToCommonAPI = false; } // add the scale. no suffix to be closer compatibility with common API _GatherAnimChannel(SCALE, iTrans, "scale", "X", "Y", "Z", &mAnimChanList, writeAnim, false); // inverse the scale pivot point if (hasScalePivot) { AnimChannel chan; chan.usdOpType = UsdGeomXformOp::TypeTranslate; chan.precision = UsdGeomXformOp::PrecisionFloat; chan.opName = "scalePivot"; chan.isInverse = true; mAnimChanList.push_back(chan); scalePivotINVIdx = mAnimChanList.size()-1; } // If still potential common API, check if the pivots are the same and NOT animated/connected if (hasRotatePivot != hasScalePivot) { conformsToCommonAPI = false; } if (conformsToCommonAPI && hasRotatePivot && hasScalePivot) { AnimChannel rotPivChan, scalePivChan; rotPivChan = mAnimChanList[rotPivotIdx]; scalePivChan = mAnimChanList[scalePivotIdx]; // If they have different sampleType or are ANIMATED, does not conformsToCommonAPI anymore for (unsigned int i = 0;i<3;i++) { if (rotPivChan.sampleType[i] != scalePivChan.sampleType[i] || rotPivChan.sampleType[i] == ANIMATED) { conformsToCommonAPI = false; } } // If The defaultValue is not the same, does not conformsToCommonAPI anymore if (!GfIsClose(rotPivChan.defValue, scalePivChan.defValue, 1e-9)) { conformsToCommonAPI = false; } // If opType, usdType or precision are not the same, does not conformsToCommonAPI anymore if (rotPivChan.opType != scalePivChan.opType || rotPivChan.usdOpType != scalePivChan.usdOpType || rotPivChan.precision != scalePivChan.precision) { conformsToCommonAPI = false; } if (conformsToCommonAPI) { // To Merge, we first rename rotatePivot and the scalePivot inverse // to pivot. Then we remove the scalePivot and the inverse of the // rotatePivot. // // This means that pivot and its inverse will wrap rotate and scale // since no other ops have been found // // NOTE: scalePivotIdx > rotPivotINVIdx mAnimChanList[rotPivotIdx].opName = "pivot"; mAnimChanList[scalePivotINVIdx].opName = "pivot"; mAnimChanList.erase(mAnimChanList.begin()+scalePivotIdx); mAnimChanList.erase(mAnimChanList.begin()+rotPivotINVIdx); } } // Loop over anim channel vector and create corresponding XFormOps // including the inverse ones if needed TF_FOR_ALL(iter, mAnimChanList) { AnimChannel& animChan = *iter; animChan.op = usdXformable.AddXformOp( animChan.usdOpType, animChan.precision, TfToken(animChan.opName), animChan.isInverse); }
void MayaTransformWriter::pushTransformStack(double iFrame, const MFnTransform & iTrans) { bool forceStatic = (iFrame == DBL_MAX); // inspect the translate addTranslate(iTrans, "translate", "translateX", "translateY", "translateZ", Alembic::AbcGeom::kTranslateHint, false, forceStatic, mSample, mAnimChanList); // inspect the rotate pivot translate addTranslate(iTrans, "rotatePivotTranslate", "rotatePivotTranslateX", "rotatePivotTranslateY", "rotatePivotTranslateZ", Alembic::AbcGeom::kRotatePivotTranslationHint, false, forceStatic, mSample, mAnimChanList); // inspect the rotate pivot addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY", "rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint, false, forceStatic, mSample, mAnimChanList); // inspect rotate names MString rotateNames[3]; rotateNames[0] = "rotateX"; rotateNames[1] = "rotateY"; rotateNames[2] = "rotateZ"; unsigned int rotOrder[3]; // if this returns false then the rotation order was kInvalid or kLast if (util::getRotOrder(iTrans.rotationOrder(), rotOrder[0], rotOrder[1], rotOrder[2])) { addRotate(iTrans, "rotate", rotateNames, rotOrder, Alembic::AbcGeom::kRotateHint, forceStatic, false, mSample, mAnimChanList); } // now look at the rotation orientation, aka rotate axis rotateNames[0] = "rotateAxisX"; rotateNames[1] = "rotateAxisY"; rotateNames[2] = "rotateAxisZ"; rotOrder[0] = 0; rotOrder[1] = 1; rotOrder[2] = 2; addRotate(iTrans, "rotateAxis", rotateNames, rotOrder, Alembic::AbcGeom::kRotateOrientationHint, forceStatic, false, mSample, mAnimChanList); // invert the rotate pivot if necessary addTranslate(iTrans, "rotatePivot", "rotatePivotX", "rotatePivotY", "rotatePivotZ", Alembic::AbcGeom::kRotatePivotPointHint, true, forceStatic, mSample, mAnimChanList); // inspect the scale pivot translation addTranslate(iTrans, "scalePivotTranslate", "scalePivotTranslateX", "scalePivotTranslateY", "scalePivotTranslateZ", Alembic::AbcGeom::kScalePivotTranslationHint, false, forceStatic, mSample, mAnimChanList); // inspect the scale pivot point addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY", "scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, false, forceStatic, mSample, mAnimChanList); // inspect the shear addShear(iTrans, forceStatic, mSample, mAnimChanList); // add the scale addScale(iTrans, "scale", "scaleX", "scaleY", "scaleZ", forceStatic, mSample, mAnimChanList); // inverse the scale pivot point if necessary addTranslate(iTrans, "scalePivot", "scalePivotX", "scalePivotY", "scalePivotZ", Alembic::AbcGeom::kScalePivotPointHint, true, forceStatic, mSample, mAnimChanList); }