void liqRibSubdivisionData::addExtraTags( MObject &dstNode, float extraTagValue, SBD_EXTRA_TAG extraTag ) { CM_TRACE_FUNC("liqRibSubdivisionData::addExtraTags("<<MFnDependencyNode(dstNode).name()<<","<<extraTagValue<<","<<extraTag<<")"); if( TAG_BOUNDARY == extraTag ) { v_tags.push_back( "interpolateboundary" ); v_nargs.push_back( 1 ); // 0 intargs v_nargs.push_back( 0 ); // 0 floatargs v_intargs.push_back( (int)extraTagValue ); return; } if( TAG_FACEVARYINGBOUNDARY == extraTag ) { v_tags.push_back( "facevaryinginterpolateboundary" ); v_nargs.push_back( 1 ); // 1 intargs v_nargs.push_back( 0 ); // 0 floatargs v_intargs.push_back( (int)extraTagValue ); } MStatus status = MS::kSuccess; MFnSet elemSet( dstNode, &status ); // dstNode is maya components set if( status == MS::kSuccess ) { MSelectionList members; status = elemSet.getMembers( members, true ); // get flatten members list if( status == MS::kSuccess ) { for ( unsigned i( 0 ) ; i < members.length() ; i++ ) { MObject component; MDagPath dagPath; members.getDagPath ( i, dagPath, component ); // since the crease set could contain more that one mesh // we only want the current one - Alf if( dagPath.fullPathName() != longName ) continue; switch ( extraTag ) { case TAG_CREASE: if( !component.isNull() && component.hasFn( MFn::kMeshEdgeComponent ) ) { MItMeshEdge edgeIter( dagPath, component ); for( ; !edgeIter.isDone(); edgeIter.next() ) { v_tags.push_back( "crease" ); v_nargs.push_back( 2 ); // 2 intargs v_nargs.push_back( 1 ); // 1 floatargs v_intargs.push_back( edgeIter.index( 0 ) ); v_intargs.push_back( edgeIter.index( 1 ) ); v_floatargs.push_back( extraTagValue ); // 1 floatargs } } break; case TAG_CORNER: if( !component.isNull() && component.hasFn( MFn::kMeshVertComponent ) ) { MItMeshVertex vertexIter( dagPath, component ); for( ; !vertexIter.isDone(); vertexIter.next() ) { v_tags.push_back( "corner" ); v_nargs.push_back( 1 ); // 1 intargs v_nargs.push_back( 1 ); // 1 floatargs v_intargs.push_back( vertexIter.index() ); v_floatargs.push_back( extraTagValue ); // 1 floatargs } } break; case TAG_HOLE: if( !component.isNull() && component.hasFn( MFn::kMeshPolygonComponent ) ) { MItMeshPolygon faceIter( dagPath, component ); for( ; !faceIter.isDone(); faceIter.next() ) { v_tags.push_back( "hole" ); v_nargs.push_back( 1 ); // 1 intargs v_nargs.push_back( 0 ); // 0 floatargs v_intargs.push_back( faceIter.index() ); } } break; case TAG_STITCH: if( !component.isNull() && component.hasFn( MFn::kMeshVertComponent ) ) { MItMeshVertex vertexIter( dagPath, component ); v_tags.push_back( "stitch" ); v_nargs.push_back( vertexIter.count() + 1 ); // vertex count in chain + 1 integer identifier v_nargs.push_back( 0 ); // 0 floatargs v_intargs.push_back( ( int ) extraTagValue ); for( ; !vertexIter.isDone(); vertexIter.next() ) { v_intargs.push_back( vertexIter.index() ); } } break; case TAG_BOUNDARY: default: break; } } } } }
MStatus AbcImport::doIt(const MArgList & args) { MStatus status; MArgParser argData(syntax(), args, &status); MString filename(""); MString connectRootNodes(""); MString filterString(""); MString excludeFilterString(""); MObject reparentObj = MObject::kNullObj; bool swap = false; bool createIfNotFound = false; bool removeIfNoUpdate = false; bool debugOn = false; if (argData.isFlagSet("help")) { MGlobal::displayInfo(usage); return status; } if (argData.isFlagSet("debug")) debugOn = true; if (argData.isFlagSet("reparent")) { MString parent(""); MDagPath reparentDagPath; status = argData.getFlagArgument("reparent", 0, parent); if (status == MS::kSuccess && getDagPathByName(parent, reparentDagPath) == MS::kSuccess) { reparentObj = reparentDagPath.node(); } else { MString theWarning = parent; theWarning += MString(" is not a valid DagPath"); printWarning(theWarning); } } if (!argData.isFlagSet("connect") && argData.isFlagSet("mode")) { MString modeStr; argData.getFlagArgument("mode", 0, modeStr); if (modeStr == "replace") deleteCurrentSelection(); else if (modeStr == "open") { MFileIO fileIo; fileIo.newFile(true); } } else if (argData.isFlagSet("connect")) { swap = true; argData.getFlagArgument("connect", 0, connectRootNodes); if (argData.isFlagSet("createIfNotFound")) { createIfNotFound = true; } if (argData.isFlagSet("removeIfNoUpdate")) removeIfNoUpdate = true; } if (argData.isFlagSet("filterObjects")) { argData.getFlagArgument("filterObjects", 0, filterString); } if (argData.isFlagSet("excludeFilterObjects")) { argData.getFlagArgument("excludeFilterObjects", 0, excludeFilterString); } // if the flag isn't specified we'll only do stuff marked with the Maya // meta data bool recreateColorSets = false; if (argData.isFlagSet("recreateAllColorSets")) { recreateColorSets = true; } status = argData.getCommandArgument(0, filename); MString abcNodeName; if (status == MS::kSuccess) { { MString fileRule, expandName; MString alembicFileRule = "alembicCache"; MString alembicFilePath = "cache/alembic"; MString queryFileRuleCmd; queryFileRuleCmd.format("workspace -q -fre \"^1s\"", alembicFileRule); MString queryFolderCmd; queryFolderCmd.format("workspace -en `workspace -q -fre \"^1s\"`", alembicFileRule); // query the file rule for alembic cache MGlobal::executeCommand(queryFileRuleCmd, fileRule); if (fileRule.length() > 0) { // we have alembic file rule, query the folder MGlobal::executeCommand(queryFolderCmd, expandName); } // resolve the expanded file rule if (expandName.length() == 0) { expandName = alembicFilePath; } // get the path to the alembic file rule MFileObject directory; directory.setRawFullName(expandName); MString directoryName = directory.resolvedFullName(); // resolve the relative path MFileObject absoluteFile; absoluteFile.setRawFullName(filename); #if MAYA_API_VERSION < 201300 if (absoluteFile.resolvedFullName() != absoluteFile.expandedFullName()) { #else if (!MFileObject::isAbsolutePath(filename)) { #endif // this is a relative path MString absoluteFileName = directoryName + "/" + filename; absoluteFile.setRawFullName(absoluteFileName); filename = absoluteFile.resolvedFullName(); } else { filename = absoluteFile.resolvedFullName(); } } MFileObject fileObj; status = fileObj.setRawFullName(filename); if (status == MS::kSuccess && fileObj.exists()) { ArgData inputData(filename, debugOn, reparentObj, swap, connectRootNodes, createIfNotFound, removeIfNoUpdate, recreateColorSets, filterString, excludeFilterString); abcNodeName = createScene(inputData); if (inputData.mSequenceStartTime != inputData.mSequenceEndTime && inputData.mSequenceStartTime != -DBL_MAX && inputData.mSequenceEndTime != DBL_MAX) { if (argData.isFlagSet("fitTimeRange")) { MTime sec(1.0, MTime::kSeconds); setPlayback( inputData.mSequenceStartTime * sec.as(MTime::uiUnit()), inputData.mSequenceEndTime * sec.as(MTime::uiUnit()) ); } if (argData.isFlagSet("setToStartFrame")) { MTime sec(1.0, MTime::kSeconds); MGlobal::viewFrame( inputData.mSequenceStartTime * sec.as(MTime::uiUnit()) ); } } } else { MString theError("In AbcImport::doIt(), "); theError += filename; theError += MString(" doesn't exist"); printError(theError); } } MPxCommand::setResult(abcNodeName); return status; }
void maTranslator::writeDagNodes(fstream& f) { fParentingRequired.clear(); MItDag dagIter; dagIter.traverseUnderWorld(true); MDagPath worldPath; dagIter.getPath(worldPath); // // We step over the world node before starting the loop, because it // doesn't get written out. // for (dagIter.next(); !dagIter.isDone(); dagIter.next()) { MDagPath path; dagIter.getPath(path); // // If the node has already been written, then all of its descendants // must have been written, or at least checked, as well, so prune // this branch of the tree from the iteration. // MFnDagNode dagNodeFn(path); if (dagNodeFn.isFlagSet(fCreateFlag)) { dagIter.prune(); continue; } // // If this is a default node, it will be written out later, so skip // it. // if (dagNodeFn.isDefaultNode()) continue; // // If this node is not writable, and is not a shared node, then mark // it as having been written, and skip it. // if (!dagNodeFn.canBeWritten() && !dagNodeFn.isShared()) { dagNodeFn.setFlag(fCreateFlag, true); continue; } unsigned int numParents = dagNodeFn.parentCount(); if (dagNodeFn.isFromReferencedFile()) { // // We don't issue 'creatNode' commands for nodes from referenced // files, but if the node has any parents which are not from // referenced files, other than the world, then make a note that // we'll need to issue extra 'parent' commands for it later on. // unsigned int i; for (i = 0; i < numParents; i++) { MObject altParent = dagNodeFn.parent(i); MFnDagNode altParentFn(altParent); if (!altParentFn.isFromReferencedFile() && (altParentFn.object() != worldPath.node())) { fParentingRequired.append(path); break; } } } else { // // Find the node's parent. // MDagPath parentPath = worldPath; if (path.length() > 1) { // // Get the parent's path. // parentPath = path; parentPath.pop(); // // If the parent is in the underworld, then find the closest // ancestor which is not. // if (parentPath.pathCount() > 1) { // // The first segment of the path contains whatever // portion of the path exists in the world. So the closest // worldly ancestor is simply the one at the end of that // first path segment. // path.getPath(parentPath, 0); } } MFnDagNode parentNodeFn(parentPath); if (parentNodeFn.isFromReferencedFile()) { // // We prefer to parent to a non-referenced node. So if this // node has any other parents, which are not from referenced // files and have not already been processed, then we'll // skip this instance and wait for an instance through one // of those parents. // unsigned i; for (i = 0; i < numParents; i++) { if (dagNodeFn.parent(i) != parentNodeFn.object()) { MObject altParent = dagNodeFn.parent(i); MFnDagNode altParentFn(altParent); if (!altParentFn.isFromReferencedFile() && !altParentFn.isFlagSet(fCreateFlag)) { break; } } } if (i < numParents) continue; // // This node only has parents within referenced files, so // create it without a parent and note that we need to issue // 'parent' commands for it later on. // writeCreateNode(f, path, worldPath); fParentingRequired.append(path); } else { writeCreateNode(f, path, parentPath); // // Let's see if this node has any parents from referenced // files, or any parents other than this one which are not // from referenced files. // unsigned int i; bool hasRefParents = false; bool hasOtherNonRefParents = false; for (i = 0; i < numParents; i++) { if (dagNodeFn.parent(i) != parentNodeFn.object()) { MObject altParent = dagNodeFn.parent(i); MFnDagNode altParentFn(altParent); if (altParentFn.isFromReferencedFile()) hasRefParents = true; else hasOtherNonRefParents = true; // // If we've already got positives for both tests, // then there's no need in continuing. // if (hasRefParents && hasOtherNonRefParents) break; } } // // If this node has parents from referenced files, then // make note that we will have to issue 'parent' commands // later on. // if (hasRefParents) fParentingRequired.append(path); // // If this node has parents other than this one which are // not from referenced files, then make note that the // parenting for the other instances still has to be done. // if (hasOtherNonRefParents) { fInstanceChildren.append(path); fInstanceParents.append(parentPath); } } // // Write out the node's 'addAttr', 'setAttr' and 'lockNode' // commands. // writeNodeAttrs(f, path.node(), true); writeLockNode(f, path.node()); } // // Mark the node as having been written. // dagNodeFn.setFlag(fCreateFlag, true); } // // Write out the parenting for instances. // writeInstances(f); }
String DocumentExporter::dagPathToColladaSid(const MDagPath & dagPath) { return mayaNameToColladaName(dagPath.partialPathName()); }
std::string HesperisIO::H5PathNameTo(const MDagPath & path) { std::string r(path.fullPathName().asChar()); H5PathName(r); return r; }
MFnMesh* GDExporter::GetSelectedMesh(void) { MSelectionList currSelection; MGlobal::getActiveSelectionList(currSelection); unsigned int selectionCount = currSelection.length(); MFnMesh* exportingMesh = 0; for(unsigned int selectionIndex = 0; selectionIndex < selectionCount; ++selectionIndex ) { MDagPath currPath; currSelection.getDagPath(selectionIndex, currPath); if( currPath.apiType() != MFn::kTransform ) continue; MFnTransform currTransform(currPath); unsigned int childCount = currTransform.childCount(); for(unsigned int childIndex = 0; childIndex < childCount; ++childIndex) { MObject childObject = currTransform.child(childIndex); if( childObject.apiType() == MFn::kMesh ) { MFnDagNode dagNode; dagNode.setObject(childObject); MDagPath childPath; dagNode.getPath(childPath); MFnMesh* pChildMesh = new MFnMesh(childPath); if( pChildMesh->isIntermediateObject() ) continue; bool bExportMesh = true; if( pChildMesh->isInstanced(false) ) if( childPath.instanceNumber() != 0 ) bExportMesh = false; if( bExportMesh ) { if( exportingMesh != 0 ) { delete exportingMesh; delete pChildMesh; MGlobal::displayError(MString("GDExporter - More than one mesh object selected.")); return 0; } exportingMesh = pChildMesh; } } } } if( exportingMesh == 0 ) { MGlobal::displayError(MString("GDExporter - No mesh objects currently selected.")); return 0; } return exportingMesh; }
void liqBoundingBoxLocator::draw( M3dView & view, const MDagPath & path, M3dView::DisplayStyle style, M3dView::DisplayStatus status ) { MFnDagNode dagFn( thisMObject() ); MFnDagNode transFn( dagFn.parent( 0 ) ); MStatus stat; bool drawBox( 0 ); MPlug plug = dagFn.findPlug( "drawBox", stat ); if ( stat == MS::kSuccess ) plug.getValue( drawBox ); if ( !drawBox ) return; MDoubleArray bb( 6 ); MGlobal::executeCommand( MString( "exactWorldBoundingBox " ) + transFn.fullPathName(), bb ); pts = shared_array< MPoint >( new MPoint[ 8 ] ); pts[0].x = bb[0]; pts[0].y = bb[4]; pts[0].z = bb[2]; pts[1].x = bb[0]; pts[1].y = bb[4]; pts[1].z = bb[5]; pts[2].x = bb[3]; pts[2].y = bb[4]; pts[2].z = bb[5]; pts[3].x = bb[3]; pts[3].y = bb[4]; pts[3].z = bb[2]; pts[4].x = bb[0]; pts[4].y = bb[1]; pts[4].z = bb[2]; pts[5].x = bb[0]; pts[5].y = bb[1]; pts[5].z = bb[5]; pts[6].x = bb[3]; pts[6].y = bb[1]; pts[6].z = bb[5]; pts[7].x = bb[3]; pts[7].y = bb[1]; pts[7].z = bb[2]; MMatrix m( path.inclusiveMatrix() ); for( unsigned i( 0 ); i < 8; i++ ) pts[i] *= m.inverse(); // draw box view.beginGL(); view.setDrawColor( MColor( .57f, 0, .57f ) ); glPushAttrib( GL_CURRENT_BIT ); glBegin(GL_LINE_STRIP); glVertex3f( (float)pts[0].x, (float)pts[0].y, (float)pts[0].z ); glVertex3f( (float)pts[1].x, (float)pts[1].y, (float)pts[1].z ); glVertex3f( (float)pts[2].x, (float)pts[2].y, (float)pts[2].z ); glVertex3f( (float)pts[3].x, (float)pts[3].y, (float)pts[3].z ); glVertex3f( (float)pts[0].x, (float)pts[0].y, (float)pts[0].z ); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f( (float)pts[4].x, (float)pts[4].y, (float)pts[4].z ); glVertex3f( (float)pts[5].x, (float)pts[5].y, (float)pts[5].z ); glVertex3f( (float)pts[6].x, (float)pts[6].y, (float)pts[6].z ); glVertex3f( (float)pts[7].x, (float)pts[7].y, (float)pts[7].z ); glVertex3f( (float)pts[4].x, (float)pts[4].y, (float)pts[4].z ); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f( (float)pts[0].x, (float)pts[0].y, (float)pts[0].z ); glVertex3f( (float)pts[4].x, (float)pts[4].y, (float)pts[4].z ); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f( (float)pts[1].x, (float)pts[1].y, (float)pts[1].z ); glVertex3f( (float)pts[5].x, (float)pts[5].y, (float)pts[5].z ); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f( (float)pts[2].x, (float)pts[2].y, (float)pts[2].z ); glVertex3f( (float)pts[6].x, (float)pts[6].y, (float)pts[6].z ); glEnd(); glBegin(GL_LINE_STRIP); glVertex3f( (float)pts[3].x, (float)pts[3].y, (float)pts[3].z ); glVertex3f( (float)pts[7].x, (float)pts[7].y, (float)pts[7].z ); glEnd(); view.endGL(); }
void NifAnimationImporter::ImportControllers( NiAVObjectRef niAVObj, MDagPath & path ) { list<NiTimeControllerRef> controllers = niAVObj->GetControllers(); //Iterate over the controllers, reacting properly to each type for ( list<NiTimeControllerRef>::iterator it = controllers.begin(); it != controllers.end(); ++it ) { if ( (*it)->IsDerivedType( NiKeyframeController::TYPE ) ) { //--NiKeyframeController--// NiKeyframeControllerRef niKeyCont = DynamicCast<NiKeyframeController>(*it); NiKeyframeDataRef niKeyData = niKeyCont->GetData(); MFnTransform transFn( path.node() ); MFnAnimCurve traXFn; MFnAnimCurve traYFn; MFnAnimCurve traZFn; MObject traXcurve = traXFn.create( transFn.findPlug("translateX") ); MObject traYcurve = traYFn.create( transFn.findPlug("translateY") ); MObject traZcurve = traZFn.create( transFn.findPlug("translateZ") ); MTimeArray traTimes; MDoubleArray traXValues; MDoubleArray traYValues; MDoubleArray traZValues; vector<Key<Vector3> > tra_keys = niKeyData->GetTranslateKeys(); for ( size_t i = 0; i < tra_keys.size(); ++i) { traTimes.append( MTime( tra_keys[i].time, MTime::kSeconds ) ); traXValues.append( tra_keys[i].data.x ); traYValues.append( tra_keys[i].data.y ); traZValues.append( tra_keys[i].data.z ); //traXFn.addKeyframe( tra_keys[i].time * 24.0, tra_keys[i].data.x ); //traYFn.addKeyframe( tra_keys[i].time * 24.0, tra_keys[i].data.y ); //traZFn.addKeyframe( tra_keys[i].time * 24.0, tra_keys[i].data.z ); } traXFn.addKeys( &traTimes, &traXValues ); traYFn.addKeys( &traTimes, &traYValues ); traZFn.addKeys( &traTimes, &traZValues ); KeyType kt = niKeyData->GetRotateType(); if ( kt != XYZ_ROTATION_KEY ) { vector<Key<Quaternion> > rot_keys = niKeyData->GetQuatRotateKeys(); MFnAnimCurve rotXFn; MFnAnimCurve rotYFn; MFnAnimCurve rotZFn; MObject rotXcurve = rotXFn.create( transFn.findPlug("rotateX") ); //rotXFn.findPlug("rotationInterpolation").setValue(3); MObject rotYcurve = rotYFn.create( transFn.findPlug("rotateY") ); //rotYFn.findPlug("rotationInterpolation").setValue(3); MObject rotZcurve = rotZFn.create( transFn.findPlug("rotateZ") ); //rotZFn.findPlug("rotationInterpolation").setValue(3); MTimeArray rotTimes; MDoubleArray rotXValues; MDoubleArray rotYValues; MDoubleArray rotZValues; MEulerRotation mPrevRot; for( size_t i = 0; i < rot_keys.size(); ++i ) { Quaternion niQuat = rot_keys[i].data; MQuaternion mQuat( niQuat.x, niQuat.y, niQuat.z, niQuat.w ); MEulerRotation mRot = mQuat.asEulerRotation(); MEulerRotation mAlt; mAlt[0] = PI + mRot[0]; mAlt[1] = PI - mRot[1]; mAlt[2] = PI + mRot[2]; for ( size_t j = 0; j < 3; ++j ) { double prev_diff = abs(mRot[j] - mPrevRot[j]); //Try adding and subtracting multiples of 2 pi radians to get //closer to the previous angle while (true) { double new_angle = mRot[j] - (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mRot[j] = new_angle; prev_diff = diff; } else { break; } } while (true) { double new_angle = mRot[j] + (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mRot[j] = new_angle; prev_diff = diff; } else { break; } } } for ( size_t j = 0; j < 3; ++j ) { double prev_diff = abs(mAlt[j] - mPrevRot[j]); //Try adding and subtracting multiples of 2 pi radians to get //closer to the previous angle while (true) { double new_angle = mAlt[j] - (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mAlt[j] = new_angle; prev_diff = diff; } else { break; } } while (true) { double new_angle = mAlt[j] + (PI * 2); double diff = abs( new_angle - mPrevRot[j] ); if ( diff < prev_diff ) { mAlt[j] = new_angle; prev_diff = diff; } else { break; } } } //Try taking advantage of the fact that: //Rotate(x,y,z) = Rotate(pi + x, pi - y, pi +z) double rot_diff = ( (abs(mRot[0] - mPrevRot[0]) + abs(mRot[1] - mPrevRot[1]) + abs(mRot[2] - mPrevRot[2]) ) / 3.0 ); double alt_diff = ( (abs(mAlt[0] - mPrevRot[0]) + abs(mAlt[1] - mPrevRot[1]) + abs(mAlt[2] - mPrevRot[2]) ) / 3.0 ); if ( alt_diff < rot_diff ) { mRot = mAlt; } mPrevRot = mRot; rotTimes.append( MTime(rot_keys[i].time, MTime::kSeconds) ); rotXValues.append( mRot[0] ); rotYValues.append( mRot[1] ); rotZValues.append( mRot[2] ); } rotXFn.addKeys( &rotTimes, &rotXValues ); rotYFn.addKeys( &rotTimes, &rotYValues ); rotZFn.addKeys( &rotTimes, &rotZValues ); } } } }
/** * Insert a new node into the hash table. */ int liqRibHT::insert( MDagPath &path, double /*lframe*/, int sample, ObjectType objType, int CountID, MMatrix *matrix, const MString instanceStr, int particleId ) { CM_TRACE_FUNC("liqRibClipPlaneData::insert("<<path.fullPathName()<<",lframe," <<sample<<","<<objType<<","<<CountID<<",matrix,"<<instanceStr<<","<<particleId<<")"); LIQDEBUGPRINTF( "-> inserting node into hash table\n" ); MFnDagNode fnDagNode( path ); MStatus returnStatus; objTypeVec.push_back( objType ); MString nodeName = fnDagNode.fullPathName( &returnStatus ); if ( objType == MRT_RibGen ) nodeName += "RIBGEN"; const char* name( nodeName.asChar() ); ulong hc = hash( name ,CountID ); RibHashVec.push_back( nodeName ); LIQDEBUGPRINTF( "-> hashed node name: %s", name ); LIQDEBUGPRINTF( " ID: %u\n", hc ); liqRibNodePtr node; /*node = find( path.node(), objType );*/ node = find( nodeName, path, objType ); liqRibNodePtr newNode; liqRibNodePtr instance; // If "node" is non-null then there's already a hash table entry at // this point // liqRibNodePtr tail; if( node ) { while( node ) { tail = node; // Break if we've already dealt with this DAG path // (and instance string - by default this is "", which // will match for most objects - allowing us to deal // with particle-instancing). // if ( path == node->path() && instanceStr == node->getInstanceStr() ) { break; } if ( path.node() == node->path().node() ) { // We have found another instance of the object we are object // looking for instance = node; } node = node->next; } if ( ( !node ) && ( instance ) ) { // We have not found a node with a matching path, but we have found // one with a matching object, so we need to insert a new instance newNode = liqRibNodePtr( new liqRibNode( instance, instanceStr ) ); } } if( !newNode ) { // We have to make a new node if ( !node) { node = liqRibNodePtr( new liqRibNode( liqRibNodePtr(), instanceStr) ); if ( tail ) { assert( !tail->next ); tail->next = node; RibNodeMap.insert( RNMAP::value_type( hc, node ) ); } else RibNodeMap.insert( RNMAP::value_type( hc, node ) ); } } else { assert( !node ); // Append new instance node onto tail of linked list node = newNode; if( tail ) { assert( !tail->next ); tail->next = node; RibNodeMap.insert( RNMAP::value_type( hc, node ) ); } else RibNodeMap.insert( RNMAP::value_type( hc, node ) ); } node->set( path, sample, objType, particleId ); // If we were given a specific matrix to use (this only // happens when we've got particle-instancing. // if( matrix != NULL ) { // Calculate the inclusive matrix for the instanced // object (as a product of the original object's // exclusive matrix - see Maya docs - and the given // matrix). // MMatrix inclusiveMatrix = path.exclusiveMatrix() * ( *matrix ); node->object( sample )->setMatrix( 0, inclusiveMatrix ); } // We can NOT support deformation blur on particle instancing, // since there's no way to guarantee that the objects are // topologically identical over the sample range. // if( instanceStr != "" ) node->motion.deformationBlur = false; LIQDEBUGPRINTF( "-> finished inserting node into hash table\n" ); return 0; }
MStatus AlembicExportCommand::doIt(const MArgList &args) { ESS_PROFILE_SCOPE("AlembicExportCommand::doIt"); MStatus status = MS::kFailure; MTime currentAnimStartTime = MAnimControl::animationStartTime(), currentAnimEndTime = MAnimControl::animationEndTime(), oldCurTime = MAnimControl::currentTime(), curMinTime = MAnimControl::minTime(), curMaxTime = MAnimControl::maxTime(); MArgParser argData(syntax(), args, &status); if (argData.isFlagSet("help")) { // TODO: implement help for this command // MGlobal::displayInfo(util::getHelpText()); return MS::kSuccess; } unsigned int jobCount = argData.numberOfFlagUses("jobArg"); MStringArray jobStrings; if (jobCount == 0) { // TODO: display dialog MGlobal::displayError("[ExocortexAlembic] No jobs specified."); MPxCommand::setResult( "Error caught in AlembicExportCommand::doIt: no job specified"); return status; } else { // get all of the jobstrings for (unsigned int i = 0; i < jobCount; i++) { MArgList jobArgList; argData.getFlagArgumentList("jobArg", i, jobArgList); jobStrings.append(jobArgList.asString(0)); } } // create a vector to store the jobs std::vector<AlembicWriteJob *> jobPtrs; double minFrame = 1000000.0; double maxFrame = -1000000.0; double maxSteps = 1; double maxSubsteps = 1; // init the curve accumulators AlembicCurveAccumulator::Initialize(); try { // for each job, check the arguments bool failure = false; for (unsigned int i = 0; i < jobStrings.length(); ++i) { double frameIn = 1.0; double frameOut = 1.0; double frameSteps = 1.0; double frameSubSteps = 1.0; MString filename; bool purepointcache = false; bool normals = true; bool uvs = true; bool facesets = true; bool bindpose = true; bool dynamictopology = false; bool globalspace = false; bool withouthierarchy = false; bool transformcache = false; bool useInitShadGrp = false; bool useOgawa = false; // Later, will need to be changed! // Each frames to export can manually be specified via the "frames" parameter. // This allow for very specific frames to be exported. // In our case (Squeeze Studio) this allow the animator to export only specific subframes. // The advantage of exporting specific subframes instead of using the "substep" parameter is that the animator don't have to // fix all the flipping occuring in a rig when trying to work with substeps. MDoubleArray frames; MStringArray objectStrings; std::vector<std::string> prefixFilters; std::set<std::string> attributes; std::vector<std::string> userPrefixFilters; std::set<std::string> userAttributes; MObjectArray objects; std::string search_str, replace_str; // process all tokens of the job MStringArray tokens; jobStrings[i].split(';', tokens); for (unsigned int j = 0; j < tokens.length(); j++) { MStringArray valuePair; tokens[j].split('=', valuePair); if (valuePair.length() != 2) { MGlobal::displayWarning( "[ExocortexAlembic] Skipping invalid token: " + tokens[j]); continue; } const MString &lowerValue = valuePair[0].toLowerCase(); if (lowerValue == "in") { frameIn = valuePair[1].asDouble(); } else if (lowerValue == "out") { frameOut = valuePair[1].asDouble(); } else if (lowerValue == "step") { frameSteps = valuePair[1].asDouble(); } else if (lowerValue == "substep") { frameSubSteps = valuePair[1].asDouble(); } else if (lowerValue == "normals") { normals = valuePair[1].asInt() != 0; } else if (lowerValue == "uvs") { uvs = valuePair[1].asInt() != 0; } else if (lowerValue == "facesets") { facesets = valuePair[1].asInt() != 0; } else if (lowerValue == "bindpose") { bindpose = valuePair[1].asInt() != 0; } else if (lowerValue == "purepointcache") { purepointcache = valuePair[1].asInt() != 0; } else if (lowerValue == "dynamictopology") { dynamictopology = valuePair[1].asInt() != 0; } else if (lowerValue == "globalspace") { globalspace = valuePair[1].asInt() != 0; } else if (lowerValue == "withouthierarchy") { withouthierarchy = valuePair[1].asInt() != 0; } else if (lowerValue == "transformcache") { transformcache = valuePair[1].asInt() != 0; } else if (lowerValue == "filename") { filename = valuePair[1]; } else if (lowerValue == "objects") { // try to find each object valuePair[1].split(',', objectStrings); } else if (lowerValue == "useinitshadgrp") { useInitShadGrp = valuePair[1].asInt() != 0; } // search/replace else if (lowerValue == "search") { search_str = valuePair[1].asChar(); } else if (lowerValue == "replace") { replace_str = valuePair[1].asChar(); } else if (lowerValue == "ogawa") { useOgawa = valuePair[1].asInt() != 0; } else if(lowerValue == "frames") { MStringArray strFrames; valuePair[1].split(',', strFrames); for(unsigned int i=0;i<strFrames.length();i++) { double frame = strFrames[i].asDouble(); frames.append(frame); } } else if (lowerValue == "attrprefixes") { splitListArg(valuePair[1], prefixFilters); } else if (lowerValue == "attrs") { splitListArg(valuePair[1], attributes); } else if (lowerValue == "userattrprefixes") { splitListArg(valuePair[1], userPrefixFilters); } else if (lowerValue == "userattrs") { splitListArg(valuePair[1], userAttributes); } else { MGlobal::displayWarning( "[ExocortexAlembic] Skipping invalid token: " + tokens[j]); continue; } } // now check the object strings for (unsigned int k = 0; k < objectStrings.length(); k++) { MSelectionList sl; MString objectString = objectStrings[k]; sl.add(objectString); MDagPath dag; for (unsigned int l = 0; l < sl.length(); l++) { sl.getDagPath(l, dag); MObject objRef = dag.node(); if (objRef.isNull()) { MGlobal::displayWarning("[ExocortexAlembic] Skipping object '" + objectStrings[k] + "', not found."); break; } // get all parents MObjectArray parents; // check if this is a camera bool isCamera = false; for (unsigned int m = 0; m < dag.childCount(); ++m) { MFnDagNode child(dag.child(m)); MFn::Type ctype = child.object().apiType(); if (ctype == MFn::kCamera) { isCamera = true; break; } } if (dag.node().apiType() == MFn::kTransform && !isCamera && !globalspace && !withouthierarchy) { MDagPath ppath = dag; while (!ppath.node().isNull() && ppath.length() > 0 && ppath.isValid()) { parents.append(ppath.node()); if (ppath.pop() != MStatus::kSuccess) { break; } } } else { parents.append(dag.node()); } // push all parents in while (parents.length() > 0) { bool found = false; for (unsigned int m = 0; m < objects.length(); m++) { if (objects[m] == parents[parents.length() - 1]) { found = true; break; } } if (!found) { objects.append(parents[parents.length() - 1]); } parents.remove(parents.length() - 1); } // check all of the shapes below if (!transformcache) { sl.getDagPath(l, dag); for (unsigned int m = 0; m < dag.childCount(); m++) { MFnDagNode child(dag.child(m)); if (child.isIntermediateObject()) { continue; } objects.append(child.object()); } } } } // check if we have incompatible subframes if (maxSubsteps > 1.0 && frameSubSteps > 1.0) { const double part = (frameSubSteps > maxSubsteps) ? (frameSubSteps / maxSubsteps) : (maxSubsteps / frameSubSteps); if (abs(part - floor(part)) > 0.001) { MString frameSubStepsStr, maxSubstepsStr; frameSubStepsStr.set(frameSubSteps); maxSubstepsStr.set(maxSubsteps); MGlobal::displayError( "[ExocortexAlembic] You cannot combine substeps " + frameSubStepsStr + " and " + maxSubstepsStr + " in one export. Aborting."); return MStatus::kInvalidParameter; } } // remember the min and max values for the frames if (frameIn < minFrame) { minFrame = frameIn; } if (frameOut > maxFrame) { maxFrame = frameOut; } if (frameSteps > maxSteps) { maxSteps = frameSteps; } if (frameSteps > 1.0) { frameSubSteps = 1.0; } if (frameSubSteps > maxSubsteps) { maxSubsteps = frameSubSteps; } // check if we have a filename if (filename.length() == 0) { MGlobal::displayError("[ExocortexAlembic] No filename specified."); for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } MPxCommand::setResult( "Error caught in AlembicExportCommand::doIt: no filename " "specified"); return MStatus::kFailure; } // construct the frames if they are not already provided if (frames.length() == 0) { const double frameIncr = frameSteps / frameSubSteps; for (double frame = frameIn; frame <= frameOut; frame += frameIncr) { frames.append(frame); } } AlembicWriteJob *job = new AlembicWriteJob(filename, objects, frames, useOgawa, prefixFilters, attributes, userPrefixFilters, userAttributes); job->SetOption("exportNormals", normals ? "1" : "0"); job->SetOption("exportUVs", uvs ? "1" : "0"); job->SetOption("exportFaceSets", facesets ? "1" : "0"); job->SetOption("exportInitShadGrp", useInitShadGrp ? "1" : "0"); job->SetOption("exportBindPose", bindpose ? "1" : "0"); job->SetOption("exportPurePointCache", purepointcache ? "1" : "0"); job->SetOption("exportDynamicTopology", dynamictopology ? "1" : "0"); job->SetOption("indexedNormals", "1"); job->SetOption("indexedUVs", "1"); job->SetOption("exportInGlobalSpace", globalspace ? "1" : "0"); job->SetOption("flattenHierarchy", withouthierarchy ? "1" : "0"); job->SetOption("transformCache", transformcache ? "1" : "0"); // check if the search/replace strings are valid! if (search_str.length() ? !replace_str.length() : replace_str.length()) // either search or // replace string is // missing or empty! { ESS_LOG_WARNING( "Missing search or replace parameter. No strings will be " "replaced."); job->replacer = SearchReplace::createReplacer(); } else { job->replacer = SearchReplace::createReplacer(search_str, replace_str); } // check if the job is satifsied if (job->PreProcess() != MStatus::kSuccess) { MGlobal::displayError("[ExocortexAlembic] Job skipped. Not satisfied."); delete (job); failure = true; break; } // push the job to our registry MGlobal::displayInfo("[ExocortexAlembic] Using WriteJob:" + jobStrings[i]); jobPtrs.push_back(job); } if (failure) { for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } return MS::kFailure; } // compute the job count unsigned int jobFrameCount = 0; for (size_t i = 0; i < jobPtrs.size(); i++) jobFrameCount += (unsigned int)jobPtrs[i]->GetNbObjects() * (unsigned int)jobPtrs[i]->GetFrames().size(); // now, let's run through all frames, and process the jobs const double frameRate = MTime(1.0, MTime::kSeconds).as(MTime::uiUnit()); const double incrSteps = maxSteps / maxSubsteps; double frame; double nextFrame = minFrame + incrSteps; /* for (double frame = minFrame; frame <= maxFrame; frame += incrSteps, nextFrame += incrSteps) { MAnimControl::setCurrentTime(MTime(frame / frameRate, MTime::kSeconds)); MAnimControl::setAnimationEndTime( MTime(nextFrame / frameRate, MTime::kSeconds)); MAnimControl::playForward(); // this way, it forces Maya to play exactly // one frame! and particles are updated! AlembicCurveAccumulator::StartRecordingFrame(); for (size_t i = 0; i < jobPtrs.size(); i++) { MStatus status = jobPtrs[i]->Process(frame); if (status != MStatus::kSuccess) { MGlobal::displayError("[ExocortexAlembic] Job aborted :" + jobPtrs[i]->GetFileName()); for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); return status; } } AlembicCurveAccumulator::StopRecordingFrame(); } */ // Collect all job frames std::vector<double> all_frames; for(size_t i=0;i<jobPtrs.size();i++) { const std::vector<double> jobFrames = jobPtrs[i]->GetFrames(); for (unsigned int j=0;j<jobFrames.size();++j) { all_frames.push_back(jobFrames[j]); } } // Force Maya to play the animation in sequence. This way particles are updated. unsigned int num_frames_to_export = all_frames.size(); all_frames.push_back(all_frames[num_frames_to_export -1] + incrSteps); for (unsigned int i=0;i<num_frames_to_export;++i) { frame = all_frames[i]; nextFrame = all_frames[i+1]; // debuging MString msg = "Exporting frame "; msg += frame; msg += ". Next is "; msg += nextFrame; MGlobal::displayInfo(msg); MAnimControl::setCurrentTime(MTime(frame/frameRate,MTime::kSeconds)); MAnimControl::setAnimationEndTime( MTime(nextFrame/frameRate,MTime::kSeconds) ); MAnimControl::playForward(); // this way, it forces Maya to play exactly one frame! and particles are updated! AlembicCurveAccumulator::StartRecordingFrame(); for(size_t i=0;i<jobPtrs.size();i++) { MStatus status = jobPtrs[i]->Process(frame); if(status != MStatus::kSuccess) { MGlobal::displayError("[ExocortexAlembic] Job aborted :"+jobPtrs[i]->GetFileName()); for(size_t k=0;k<jobPtrs.size();k++) { delete(jobPtrs[k]); } restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); return status; } } AlembicCurveAccumulator::StopRecordingFrame(); } } catch (...) { MGlobal::displayError( "[ExocortexAlembic] Jobs aborted, force closing all archives!"); for (std::vector<AlembicWriteJob *>::iterator beg = jobPtrs.begin(); beg != jobPtrs.end(); ++beg) { (*beg)->forceCloseArchive(); } restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); MPxCommand::setResult("Error caught in AlembicExportCommand::doIt"); status = MS::kFailure; } MAnimControl::stop(); AlembicCurveAccumulator::Destroy(); // restore the animation start/end time and the current time! restoreOldTime(currentAnimStartTime, currentAnimEndTime, oldCurTime, curMinTime, curMaxTime); // delete all jobs for (size_t k = 0; k < jobPtrs.size(); k++) { delete (jobPtrs[k]); } // remove all known archives deleteAllArchives(); return status; }
MStatus MayaToCorona::doIt( const MArgList& args) { MStatus stat = MStatus::kSuccess; std::unique_ptr<MayaTo::CmdArgs> cmdArgs(new MayaTo::CmdArgs); MArgDatabase argData(syntax(), args); if (argData.isFlagSet("-version", &stat)) { MStringArray res; for (auto v : getFullVersionString()) res.append(v.c_str()); setResult(res); return MS::kSuccess; } MayaTo::MayaToWorld::WorldRenderState rstate = MayaTo::getWorldPtr()->renderState; if (argData.isFlagSet("-state", &stat)) { if (rstate == MayaTo::MayaToWorld::RSTATETRANSLATING) setResult("rstatetranslating"); if (rstate == MayaTo::MayaToWorld::RSTATERENDERING) setResult("rstaterendering"); if (rstate == MayaTo::MayaToWorld::RSTATEDONE) setResult("rstatedone"); if (rstate == MayaTo::MayaToWorld::RSTATENONE) setResult("rstatenone"); if (rstate == MayaTo::MayaToWorld::RSTATESTOPPED) setResult("rstatestopped"); return MS::kSuccess; } MGlobal::displayInfo("Executing mayaToCorona..."); setLogLevel(); if (argData.isFlagSet("-canDoIPR", &stat)) { if(MayaTo::getWorldPtr()->canDoIPR()) setResult("yes"); else setResult("no"); return MS::kSuccess; } if ( argData.isFlagSet("-stopIpr", &stat)) { Logging::debug(MString("-stopIpr")); EventQueue::Event e; e.type = EventQueue::Event::IPRSTOP; theRenderEventQueue()->push(e); return MS::kSuccess; } if ( argData.isFlagSet("-pauseIpr", &stat)) { Logging::debug(MString("-pauseIpr")); Logging::debug(MString("-stopIpr")); EventQueue::Event e; e.type = EventQueue::Event::IPRPAUSE; theRenderEventQueue()->push(e); return MS::kSuccess; } if (argData.isFlagSet("-usrDataString", &stat)) { Logging::debug(MString("-usrDataString")); argData.getFlagArgument("-usrDataString", 0, cmdArgs->userDataString); } if (argData.isFlagSet("-usrDataInt", &stat)) { Logging::debug(MString("-usrDataInt")); argData.getFlagArgument("-usrDataInt", 0, cmdArgs->userDataInt); } if (argData.isFlagSet("-usrDataFloat", &stat)) { Logging::debug(MString("-usrDataFloat")); argData.getFlagArgument("-usrDataFloat", 0, cmdArgs->userDataFloat); } if (argData.isFlagSet("-usrEvent", &stat)) { Logging::debug(MString("-usrEvent")); argData.getFlagArgument("-usrEvent", 0, cmdArgs->userEvent); EventQueue::Event e; e.cmdArgsData = std::move(cmdArgs); e.type = EventQueue::Event::USER; theRenderEventQueue()->push(e); return MS::kSuccess; } // I have to request useRenderRegion here because as soon the command is finished, what happens immediatly after the command is // put into the queue, the value is set back to false. MObject drg = objectFromName("defaultRenderGlobals"); MFnDependencyNode drgfn(drg); cmdArgs->useRenderRegion = drgfn.findPlug("useRenderRegion").asBool(); cmdArgs->renderType = MayaTo::MayaToWorld::WorldRenderType::UIRENDER; if (MGlobal::mayaState() == MGlobal::kBatch) cmdArgs->renderType = MayaTo::MayaToWorld::WorldRenderType::BATCHRENDER; if ( argData.isFlagSet("-startIpr", &stat)) { Logging::debug(MString("-startIpr")); cmdArgs->renderType = MayaTo::MayaToWorld::WorldRenderType::IPRRENDER; } if (argData.isFlagSet("-width", &stat)) { argData.getFlagArgument("-width", 0, cmdArgs->width); Logging::debug(MString("width: ") + cmdArgs->width); } if (argData.isFlagSet("-height", &stat)) { argData.getFlagArgument("-height", 0, cmdArgs->height); Logging::debug(MString("height: ") + cmdArgs->height); } if ( argData.isFlagSet("-camera", &stat)) { MDagPath camera; MSelectionList selectionList; argData.getFlagArgument("-camera", 0, selectionList); stat = selectionList.getDagPath(0, camera); camera.extendToShape(); Logging::debug(MString("camera: ") + camera.fullPathName()); cmdArgs->cameraDagPath = camera; } EventQueue::Event e; e.cmdArgsData = std::move(cmdArgs); e.type = EventQueue::Event::INITRENDER; theRenderEventQueue()->push(e); // if (MGlobal::mayaState() == MGlobal::kBatch) { RenderQueueWorker::startRenderQueueWorker(); } return MStatus::kSuccess; }
MStatus CIKSolverNode::doSimpleSolver() { MStatus stat; // Get the handle and create a function set for it // MIkHandleGroup* handle_group = handleGroup(); if (NULL == handle_group) { return MS::kFailure; } MObject handle = handle_group->handle(0); MDagPath handlePath = MDagPath::getAPathTo(handle); MFnIkHandle fnHandle(handlePath, &stat); // End-Effector MDagPath endEffectorPath; fnHandle.getEffector(endEffectorPath); MFnIkEffector fnEffector(endEffectorPath); MPoint effectorPos = fnEffector.rotatePivot(MSpace::kWorld); unsigned int numJoints = endEffectorPath.length(); std::vector<MDagPath> jointsDagPaths; jointsDagPaths.reserve(numJoints); while (endEffectorPath.length() > 1) { endEffectorPath.pop(); jointsDagPaths.push_back( endEffectorPath ); } std::reverse(jointsDagPaths.begin(), jointsDagPaths.end()); static bool builtLocalSkeleton = false; if (builtLocalSkeleton == false) { for (int jointIdx = 0; jointIdx < jointsDagPaths.size(); ++jointIdx) { MFnIkJoint curJoint(jointsDagPaths[jointIdx]); m_localJointsPos.push_back( curJoint.getTranslation(MSpace::kWorld) ); } m_localJointsPos.push_back(effectorPos ); builtLocalSkeleton = true; } MPoint startJointPos = MFnIkJoint(jointsDagPaths.front()).getTranslation(MSpace::kWorld); MVector startToEndEff = m_localJointsPos.back() - m_localJointsPos.front(); double curveLength = (getPosition(1.0) - getPosition(0.0)).length(); double chainLength = startToEndEff.length(); // in local space. double stretchFactor = curveLength / chainLength; double uVal = 0.0f; MVector jointPosL = m_localJointsPos[0]; for (int jointIdx = 0; jointIdx < jointsDagPaths.size(); ++jointIdx) { MFnIkJoint curJoint(jointsDagPaths[jointIdx]); MVector curJointPosL = m_localJointsPos[jointIdx]; double dist = stretchFactor * (curJointPosL - jointPosL).length(); uVal = uVal + dist / curveLength; MVector curCurveJointPos = getPosition(uVal); curJoint.setTranslation(curCurveJointPos, MSpace::kWorld); jointPosL = curJointPosL; } MVector effectorCurvePos = getPosition(1.0); MVector curCurveJointPos = getPosition(uVal); MVector effectorVec = (effectorCurvePos - curCurveJointPos).normal(); double endJointAngle[3]; MVector effectorVecXY = MVector(effectorVec(0), effectorVec(1), 0.0); endJointAngle[2] = effectorVecXY.angle(MVector(1, 0, 0)); if ((MVector(1, 0, 0) ^ effectorVecXY) * MVector(0, 0, 1) < 0.0) { endJointAngle[2] = -endJointAngle[2]; } MVector effectorVecXZ = MVector(effectorVec(0), 0.0, effectorVec(2)); endJointAngle[1] = effectorVecXZ.angle(MVector(1, 0, 0)); if ((MVector(1, 0, 0) ^ effectorVecXZ) * MVector(0, 1, 0) < 0.0) { endJointAngle[1] = -endJointAngle[1]; } endJointAngle[0] = 0.0; MFnIkJoint curJoint(jointsDagPaths.back()); curJoint.setRotation(endJointAngle, curJoint.rotationOrder()); return MS::kSuccess; }
bool getObjectShadingGroups(const MDagPath& shapeObjectDP, MObject& shadingGroup) { // if obj is a light, simply return the mobject if (shapeObjectDP.hasFn(MFn::kLight)) shadingGroup = shapeObjectDP.node(); if (shapeObjectDP.hasFn(MFn::kMesh)) { // Find the Shading Engines Connected to the SourceNode MFnMesh fnMesh(shapeObjectDP.node()); // A ShadingGroup will have a MFnSet MObjectArray sets, comps; fnMesh.getConnectedSetsAndMembers(shapeObjectDP.instanceNumber(), sets, comps, true); // Each set is a Shading Group. Loop through them for (unsigned int i = 0; i < sets.length(); ++i) { shadingGroup = sets[i]; return true; } } if (shapeObjectDP.hasFn(MFn::kNurbsSurface)||shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle)) { MObject instObjGroupsAttr; if (shapeObjectDP.hasFn(MFn::kNurbsSurface)) { MFnNurbsSurface fnNurbs(shapeObjectDP.node()); instObjGroupsAttr = fnNurbs.attribute("instObjGroups"); } if (shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle)) { MFnParticleSystem fnPart(shapeObjectDP.node()); instObjGroupsAttr = fnPart.attribute("instObjGroups"); } MPlug instPlug(shapeObjectDP.node(), instObjGroupsAttr); // Get the instance that our node is referring to; // In other words get the Plug for instObjGroups[intanceNumber]; MPlug instPlugElem = instPlug.elementByLogicalIndex(shapeObjectDP.instanceNumber()); // Find the ShadingGroup plugs that we are connected to as Source MPlugArray SGPlugArray; instPlugElem.connectedTo(SGPlugArray, false, true); // Loop through each ShadingGroup Plug for (unsigned int i=0; i < SGPlugArray.length(); ++i) { shadingGroup = SGPlugArray[i].node(); return true; } } return false; }
bool getObjectShadingGroups(const MDagPath& shapeObjectDP, MIntArray& perFaceAssignments, MObjectArray& shadingGroups, bool needsPerFaceInfo=true) { // if obj is a light, simply return the mobject if (shapeObjectDP.node().hasFn(MFn::kLight)) { perFaceAssignments.clear(); shadingGroups.clear(); shadingGroups.append(shapeObjectDP.node()); return true; } if (shapeObjectDP.node().hasFn(MFn::kMesh)) { // Find the Shading Engines Connected to the SourceNode MFnMesh meshFn(shapeObjectDP.node()); perFaceAssignments.clear(); shadingGroups.clear(); MObjectArray comps; // this one seems to be extremly much faster if we need no per face informations. // e.g. for a sphere with 90000 faces, the non per face method needs 0.05 sec. whereas the // method with per face info needs about 20 sec. if (!needsPerFaceInfo) { meshFn.getConnectedSetsAndMembers(shapeObjectDP.instanceNumber(), shadingGroups, comps, true); return true; } meshFn.getConnectedShaders(shapeObjectDP.instanceNumber(), shadingGroups, perFaceAssignments); if (!meshFn.findPlug("displaySmoothMesh").asBool()) return true; MIntArray indices; indices = perFaceAssignments; int subdivs = 0; int multiplier = 0; if (meshFn.findPlug("displaySmoothMesh").asBool()) { MMeshSmoothOptions options; MStatus status = meshFn.getSmoothMeshDisplayOptions(options); if (status) { if (!meshFn.findPlug("useSmoothPreviewForRender", false, &status).asBool()) { int smoothLevel = meshFn.findPlug("renderSmoothLevel", false, &status).asInt(); options.setDivisions(smoothLevel); } subdivs = options.divisions(); if (subdivs > 0) multiplier = static_cast<int> (pow(4.0f, (subdivs - 1))); } } if (multiplier > 0) perFaceAssignments.clear(); for (unsigned int i = 0; i < indices.length(); i++) { int subdivisions = multiplier * meshFn.polygonVertexCount(i); int index = 0 > indices[i] ? 0 : indices[i]; // non assigned has -1, but we want 0 perFaceAssignments.append(index); // simply replicate the index for all subdiv faces for (int k = 0; k < subdivisions - 1; k++) perFaceAssignments.append(index); } return true; } if (shapeObjectDP.node().hasFn(MFn::kNurbsSurface)||shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle)) { MObject instObjGroupsAttr; if (shapeObjectDP.hasFn(MFn::kNurbsSurface)) { MFnNurbsSurface fnNurbs(shapeObjectDP.node()); instObjGroupsAttr = fnNurbs.attribute("instObjGroups"); } if (shapeObjectDP.hasFn(MFn::kParticle)||shapeObjectDP.hasFn(MFn::kNParticle)) { MFnParticleSystem fnPart(shapeObjectDP.node()); instObjGroupsAttr = fnPart.attribute("instObjGroups"); } MPlug instPlug(shapeObjectDP.node(), instObjGroupsAttr); // Get the instance that our node is referring to; // In other words get the Plug for instObjGroups[intanceNumber]; MPlug instPlugElem = instPlug.elementByLogicalIndex(shapeObjectDP.instanceNumber()); // Find the ShadingGroup plugs that we are connected to as Source MPlugArray SGPlugArray; instPlugElem.connectedTo(SGPlugArray, false, true); perFaceAssignments.clear(); shadingGroups.clear(); // Loop through each ShadingGroup Plug for (unsigned int i=0; i < SGPlugArray.length(); ++i) { shadingGroups.append(SGPlugArray[i].node()); return true; } } return false; }
MStatus meshOp::doIt( const MArgList& argList ) // // Description: // implements the MEL meshOp command. // // Arguments: // argList - the argument list that was passes to the command from MEL // // Return Value: // MS::kSuccess - command succeeded // MS::kFailure - command failed (returning this value will cause the // MEL script that is being run to terminate unless the // error is caught using a "catch" statement. // { MStatus status; bool badArgument = false; // Only one parameter is expected to be passed to this command: the mesh // operation type. Get it, validate it or stop prematurely // if (argList.length() == 1) { int operationTypeArgument = argList.asInt(0); if (operationTypeArgument < 0 || operationTypeArgument > kMeshOperationCount - 1) { badArgument = true; } else { fOperation = (MeshOperation)operationTypeArgument; } } else badArgument = true; if (badArgument) { cerr << "Expecting one parameter: the operation type." << endl; cerr << "Valid types are: " << endl; cerr << " 0 - Subdivide edge(s)." << endl; cerr << " 1 - Subdivide face(s)." << endl; cerr << " 2 - Extrude edge(s)." << endl; cerr << " 3 - Extrude face(s)." << endl; cerr << " 4 - Collapse edge(s)." << endl; cerr << " 5 - Collapse face(s)." << endl; cerr << " 6 - Duplicate face(s)." << endl; cerr << " 7 - Extract face(s)." << endl; cerr << " 8 - Split face(s)." << endl; cerr << " 8 - Chamfer vertex(s)." << endl; displayError(" Expecting one parameter: the operation type."); return MS::kFailure; } // Each mesh operation only supports one type of components // MFn::Type componentType = meshOpFty::getExpectedComponentType(fOperation); // Parse the selection list for selected components of the right type. // To simplify things, we only take the first object that we find with // selected components and operate on that object alone. // // All other objects are ignored and return warning messages indicating // this limitation. // MSelectionList selList; MGlobal::getActiveSelectionList( selList ); MItSelectionList selListIter( selList ); selListIter.setFilter( MFn::kMesh ); // The meshOperation node only accepts a component list input, so we build // a component list using MFnComponentListData. // // MIntArrays could also be passed into the node to represent the ids, // but are less storage efficient than component lists, since consecutive // components are bundled into a single entry in component lists. // MFnComponentListData compListFn; compListFn.create(); bool found = false; bool foundMultiple = false; for( ; !selListIter.isDone(); selListIter.next() ) { MDagPath dagPath; MObject component; selListIter.getDagPath( dagPath, component ); // Check for selected components of the right type // if( component.apiType() == componentType ) { if( !found ) { // The variable 'component' holds all selected components // on the selected object, thus only a single call to // MFnComponentListData::add() is needed to store the selected // components for a given object. // compListFn.add( component ); // Copy the component list created by MFnComponentListData // into our local component list MObject member. // fComponentList = compListFn.object(); // Locally store the actual ids of the selected components so // that this command can directly modify the mesh in the case // when there is no history and history is turned off. // MFnSingleIndexedComponent compFn( component ); // Ensure that this DAG path will point to the shape // of our object. Set the DAG path for the polyModifierCmd. // dagPath.extendToShape(); setMeshNode( dagPath ); found = true; } else { // Break once we have found a multiple object holding // selected components, since we are not interested in how // many multiple objects there are, only the fact that there // are multiple objects. // foundMultiple = true; break; } } } if( foundMultiple ) { displayWarning("Found more than one object with selected components."); displayWarning("Only operating on first found object."); } // Initialize the polyModifierCmd node type - mesh node already set // setModifierNodeType( meshOpNode::id ); if( found ) { // Now, pass control over to the polyModifierCmd::doModifyPoly() method // to handle the operation. // status = doModifyPoly(); if( status == MS::kSuccess ) { setResult( "meshOp command succeeded!" ); } else { displayError( "meshOp command failed!" ); } } else { displayError( "meshOp command failed: Unable to find selected components" ); status = MS::kFailure; } return status; }
MStatus closestPointOnCurveCommand::redoIt() { // DOUBLE-CHECK TO MAKE SURE THERE'S A SPECIFIED OBJECT TO EVALUATE ON: if (sList.length() == 0) { MStatus stat; MString msg = MStringResource::getString(kNoValidObject, stat); displayError(msg); return MStatus::kFailure; } // RETRIEVE THE SPECIFIED OBJECT AS A DAGPATH: MDagPath curveDagPath; sList.getDagPath(0, curveDagPath); // CHECK FOR INVALID NODE-TYPE INPUT WHEN SPECIFIED/SELECTED NODE IS *NOT* A "CURVE" NOR "CURVE TRANSFORM": if (!curveDagPath.node().hasFn(MFn::kNurbsCurve) && !(curveDagPath.node().hasFn(MFn::kTransform) && curveDagPath.hasFn(MFn::kNurbsCurve))) { MStatus stat; MString msg; // Use format to place variable string into message MString msgFmt = MStringResource::getString(kInvalidType, stat); MStringArray selectionStrings; sList.getSelectionStrings(0, selectionStrings); msg.format(msgFmt, selectionStrings[0]); displayError(msg); return MStatus::kFailure; } // WHEN COMMAND *NOT* IN "QUERY MODE" (I.E. "CREATION MODE"), CREATE AND CONNECT A "closestPointOnCurve" NODE AND RETURN ITS NODE NAME: if (!queryFlagSet) { // CREATE THE NODE: MFnDependencyNode depNodeFn; if (closestPointOnCurveNodeName == "") depNodeFn.create("closestPointOnCurve"); else depNodeFn.create("closestPointOnCurve", closestPointOnCurveNodeName); closestPointOnCurveNodeName = depNodeFn.name(); // SET THE ".inPosition" ATTRIBUTE, IF SPECIFIED IN THE COMMAND: if (inPositionFlagSet) { MPlug inPositionXPlug = depNodeFn.findPlug("inPositionX"); inPositionXPlug.setValue(inPosition.x); MPlug inPositionYPlug = depNodeFn.findPlug("inPositionY"); inPositionYPlug.setValue(inPosition.y); MPlug inPositionZPlug = depNodeFn.findPlug("inPositionZ"); inPositionZPlug.setValue(inPosition.z); } // MAKE SOME ADJUSTMENTS WHEN THE SPECIFIED NODE IS A "TRANSFORM" OF A CURVE SHAPE: unsigned instanceNumber=0; if (curveDagPath.node().hasFn(MFn::kTransform)) { // EXTEND THE DAGPATH TO ITS CURVE "SHAPE" NODE: curveDagPath.extendToShape(); // TRANSFORMS ARE *NOT* NECESSARILY THE "FIRST" INSTANCE TRANSFORM OF A CURVE SHAPE: instanceNumber = curveDagPath.instanceNumber(); } // CONNECT THE NODES: MPlug worldCurvePlug, inCurvePlug; inCurvePlug = depNodeFn.findPlug("inCurve"); depNodeFn.setObject(curveDagPath.node()); worldCurvePlug = depNodeFn.findPlug("worldSpace"); worldCurvePlug = worldCurvePlug.elementByLogicalIndex(instanceNumber); MDGModifier dgModifier; dgModifier.connect(worldCurvePlug, inCurvePlug); dgModifier.doIt(); // SET COMMAND RESULT TO BE NEW NODE'S NAME, AND RETURN: setResult(closestPointOnCurveNodeName); return MStatus::kSuccess; } // OTHERWISE, WE'RE IN THE COMMAND'S "QUERY MODE": else { // COMPUTE THE CLOSEST POSITION, NORMAL, TANGENT, PARAMETER-U AND DISTANCE, USING THE *FIRST* INSTANCE TRANSFORM WHEN CURVE IS SPECIFIED AS A "SHAPE": MPoint position; MVector normal, tangent; double paramU, distance; closestTangentUAndDistance(curveDagPath, inPosition, position, normal, tangent, paramU, distance); // WHEN NO QUERYABLE FLAG IS SPECIFIED, INDICATE AN ERROR: if (!positionFlagSet && !normalFlagSet && !tangentFlagSet && !paramUFlagSet && !distanceFlagSet) { MStatus stat; MString msg = MStringResource::getString(kNoQueryFlag, stat); displayError(msg); return MStatus::kFailure; } // WHEN JUST THE "DISTANCE" IS QUERIED, RETURN A SINGLE "FLOAT" INSTEAD OF AN ENTIRE FLOAT ARRAY FROM THE COMMAND: else if (distanceFlagSet && !(positionFlagSet || normalFlagSet || tangentFlagSet || paramUFlagSet)) setResult(distance); // WHEN JUST THE "PARAMETER-U" IS QUERIED, RETURN A SINGLE "FLOAT" INSTEAD OF AN ENTIRE FLOAT ARRAY FROM THE COMMAND: else if (paramUFlagSet && !(positionFlagSet || normalFlagSet || tangentFlagSet || distanceFlagSet)) setResult(paramU); // OTHERWISE, SET THE RETURN VALUE OF THE COMMAND'S RESULT TO A "COMPOSITE ARRAY OF FLOATS": else { // HOLDS FLOAT ARRAY RESULT: MDoubleArray floatArrayResult; // APPEND THE RESULTS OF THE CLOSEST POSITION, NORMAL, TANGENT, PARAMETER-U AND DISTANCE VALUES TO THE FLOAT ARRAY RESULT: if (positionFlagSet) { floatArrayResult.append(position.x); floatArrayResult.append(position.y); floatArrayResult.append(position.z); } if (normalFlagSet) { floatArrayResult.append(normal.x); floatArrayResult.append(normal.y); floatArrayResult.append(normal.z); } if (tangentFlagSet) { floatArrayResult.append(tangent.x); floatArrayResult.append(tangent.y); floatArrayResult.append(tangent.z); } if (paramUFlagSet) floatArrayResult.append(paramU); if (distanceFlagSet) floatArrayResult.append(distance); // FINALLY, SET THE COMMAND'S RESULT: setResult(floatArrayResult); } return MStatus::kSuccess; } }
MStatus sgCurveEditBrush_context::editCurve( MDagPath dagPathCurve, int beforeX, int beforeY, int currentX, int currentY, float radius, const MDoubleArray& dArrLength, MPointArray &points ) { MStatus status; if( radius < 0 ) return MS::kSuccess; MDagPath dagPathCam; M3dView view = M3dView::active3dView( &status ); CHECK_MSTATUS_AND_RETURN_IT( status ); view.getCamera( dagPathCam ); MPoint camPos = dagPathCam.inclusiveMatrix()[3]; MVector vCamUp = dagPathCam.inclusiveMatrix()[1]; vCamUp.normalize(); radius *= .05; MPoint nearClipBefore; MPoint farClipBefore; view.viewToWorld( beforeX, beforeY, nearClipBefore, farClipBefore ); MVector rayBefore = nearClipBefore - camPos; rayBefore.normalize(); rayBefore *= 20; MPoint posBefore = rayBefore + camPos; MPoint nearClipCurrent; MPoint farClipCurrent; view.viewToWorld( currentX, currentY, nearClipCurrent, farClipCurrent ); MVector rayCurrent = nearClipCurrent - camPos; rayCurrent.normalize(); rayCurrent *= 20; MPoint posCurrent = rayCurrent + camPos; MVector vMove = posCurrent - posBefore; MMatrix mtxCurve = dagPathCurve.inclusiveMatrix(); MFnNurbsCurve fnCurve( dagPathCurve ); fnCurve.getCVs( points ); for( int i=0; i< points.length(); i++ ) { points[i] *= mtxCurve; } for( int i=1; i< points.length(); i++ ) { MPoint cuPoint = points[i]; MVector vPoint = cuPoint - camPos; MVector projV = ( vPoint * rayBefore )/( pow( rayBefore.length(), 2 ) )* rayBefore; MVector vertical = vPoint - projV; float radiusForPoint = vertical.length() / projV.length(); if( radius < radiusForPoint ) continue; MPoint parentPoint = points[i-1]; MVector vCurveDirection = cuPoint - parentPoint; double vDirLength = vCurveDirection.length(); MVector vEditDirection = vCurveDirection + vMove/rayBefore.length()*projV.length(); double dotEdit = vCurveDirection.normal() * vEditDirection.normal(); if( dotEdit < 0 ) continue; vEditDirection = vEditDirection * dotEdit + vCurveDirection*( 1-dotEdit ); MVector vEditLength = vEditDirection / vEditDirection.length() * vCurveDirection.length(); MVector vEdit = (vEditLength - vCurveDirection) * pow((double)(1-radiusForPoint/radius), 1 ); points[i] += vEdit; for( int j=i+1; j< points.length(); j++ ) { MPoint beforePoint = points[j]; MPoint pPoint = points[j-1]; MPoint beforePPoint = pPoint - vEdit; MVector vBefore = points[j] - beforePPoint; MVector vAfter = points[j] - pPoint; MVector vCurrent = vAfter.normal() * dArrLength[j]; points[j] = vCurrent + pPoint; vEdit = points[j] - beforePoint; } } MMatrix invMtxCurve = mtxCurve.inverse(); for( int i=0; i< points.length(); i++ ) { points[i] *= invMtxCurve; } fnCurve.setCVs( points ); fnCurve.updateCurve(); return MS::kSuccess; }
// Custom parsing to support array argument. Not using MSyntax. MStatus skinClusterWeights::parseArgs( const MArgList& args ) { MStatus status = MS::kSuccess; MObject node; MDagPath dagPath; MSelectionList selList; editUsed = true; queryUsed = false; unsigned int i, nth = 0; unsigned int numArgs = args.length(); while(status == MS::kSuccess && nth < numArgs-1) { MString inputString = args.asString(nth, &status); if (status != MS::kSuccess) { MGlobal::displayError("skinClusterWeights syntax error"); return status; } if (inputString == kEditFlag || inputString == kEditFlagLong) { editUsed = true; queryUsed = false; nth++; continue; } if (inputString == kQueryFlag || inputString == kQueryFlagLong) { queryUsed = true; editUsed = false; nth++; continue; } if (inputString == kInfluenceFlag || inputString == kInfluenceFlagLong) { nth++; MStringArray stringArray = args.asStringArray(nth, &status); selList.clear(); for (i = 0; i < stringArray.length(); i++) { selList.add(stringArray[i]); } for (i = 0; i < selList.length(); i++) { status = selList.getDagPath(i, dagPath); if (status == MS::kSuccess && dagPath.hasFn(MFn::kTransform)) { influenceArray.append(dagPath); } else { MGlobal::displayError(inputString + " is not a valid influence object.\n"); return status; } } nth++; continue; } if (inputString == kSkinClusterFlag || inputString == kSkinClusterFlagLong) { nth++; MStringArray stringArray = args.asStringArray(nth, &status); selList.clear(); for (i = 0; i < stringArray.length(); i++) { selList.add(stringArray[i]); } for (i = 0; i < selList.length(); i++) { status = selList.getDependNode(i, node); if (status == MS::kSuccess && node.hasFn(MFn::kSkinClusterFilter)) { skinClusterArray.append(node); } else { MGlobal::displayError(inputString + " is not a valid skinCluster.\n"); return status; } } nth++; continue; } if (inputString == kWeightFlag || inputString == kWeightFlagLong) { nth++; weightArray = args.asDoubleArray(nth, &status); if (status != MS::kSuccess) { MGlobal::displayError("error while parsing weight array"); } nth++; continue; } if (inputString == kAssignAllToSingleFlag || inputString == kAssignAllToSingleFlagLong) { assignAllToSingle = true; nth++; continue; } MGlobal::displayError("invalid command syntax at " + inputString); return MS::kFailure; } // parse command objects // nth should equals to numArgs-1 at this point geometryArray = args.asStringArray(nth, &status); if (status != MS::kSuccess) { MGlobal::displayError("Command object invalid"); return status; } if (queryUsed) { if (assignAllToSingle) { MGlobal::displayWarning("-as/-assignAllToSingle is ignored with query flag"); } if (weightArray.length() > 0) { MGlobal::displayWarning("-w/-weights is ignored with query flag"); } } return status; }
/* emits particles with color sampled from specified shading node/shading engine */ MStatus sampleParticles::doIt( const MArgList& args ) { unsigned int i; bool shadow = 0; bool reuse = 0; for ( i = 0; i < args.length(); i++ ) if ( args.asString(i) == MString("-shadow") || args.asString(i) == MString("-s") ) shadow = 1; else if ( args.asString(i) == MString("-reuse") || args.asString(i) == MString("-r") ) reuse = 1; else break; if ( args.length() - i < 5 ) { displayError( "Usage: sampleParticles [-shadow|-reuse] particleName <shadingEngine|shadingNode.plug> resX resY scale\n" " Example: sampleParticles -shadow particle1 phong1SG 64 64 10;\n" " Example: sampleParticles particle1 file1.outColor 128 128 5;\n" ); return MS::kFailure; } if ( reuse && !shadow ) // can only reuse if shadow is turned on reuse = 0; MString particleName = args.asString( i ); MString node = args.asString( i+1 ); short resX = args.asInt( i+2 ); short resY = args.asInt( i+3 ); double scale = args.asDouble( i+4 ); if ( scale <= 0.0 ) scale = 1.0; MFloatArray uCoord, vCoord; MFloatPointArray points; MFloatVectorArray normals, tanUs, tanVs; if ( resX <= 0 ) resX = 1; if ( resY <= 0 ) resY = 1; MString command( "emit -o " ); command += particleName; char tmp[2048]; float stepU = (float) (1.0 / resX); float stepV = (float) (1.0 / resY); // stuff sample data by iterating over grid // Y is set to arch along the X axis int x, y; for ( y = 0; y < resY; y++ ) for ( x = 0; x < resX; x++ ) { uCoord.append( stepU * x ); vCoord.append( stepV * y ); float curY = (float) (sin( stepU * (x) * M_PI )*2.0); MFloatPoint curPt( (float) (stepU * x * scale), curY, (float) (stepV * y * scale )); MFloatPoint uPt( (float) (stepU * (x+1) * scale), (float) (sin( stepU * (x+1) * M_PI )*2.0), (float) (stepV * y * scale )); MFloatPoint vPt( (float) (stepU * (x) * scale), curY, (float) (stepV * (y+1) * scale )); MFloatVector du, dv, n; du = uPt-curPt; dv = vPt-curPt; n = dv^du; // normal is based on dU x dV n = n.normal(); normals.append( n ); du.normal(); dv.normal(); tanUs.append( du ); tanVs.append( dv ); points.append( curPt ); } // get current camera's world matrix MDagPath cameraPath; M3dView::active3dView().getCamera( cameraPath ); MMatrix mat = cameraPath.inclusiveMatrix(); MFloatMatrix cameraMat( mat.matrix ); MFloatVectorArray colors, transps; if ( MS::kSuccess == MRenderUtil::sampleShadingNetwork( node, points.length(), shadow, reuse, cameraMat, &points, &uCoord, &vCoord, &normals, &points, &tanUs, &tanVs, NULL, // don't need filterSize colors, transps ) ) { fprintf( stderr, "%u points sampled...\n", points.length() ); for ( i = 0; i < uCoord.length(); i++ ) { sprintf( tmp, " -pos %g %g %g -at velocity -vv %g %g %g -at rgbPP -vv %g %g %g", points[i].x, points[i].y, points[i].z, normals[i].x, normals[i].y, normals[i].z, colors[i].x, colors[i].y, colors[i].z ); command += MString( tmp ); // execute emit command once every 512 samples if ( i % 512 == 0 ) { fprintf( stderr, "%u...\n", i ); MGlobal::executeCommand( command, false, false ); command = MString( "emit -o " ); command += particleName; } } if ( i % 512 ) MGlobal::executeCommand( command, true, true ); } else { displayError( node + MString(" is not a shading engine! Specify node.attr or shading group node." ) ); } return MS::kSuccess; }
MStatus skinClusterWeights::redoIt() { MStatus status; unsigned int ptr = 0; MSelectionList selList; int geomLen = geometryArray.length(); fDagPathArray.setLength(geomLen); fComponentArray.setLength(geomLen); fInfluenceIndexArrayPtrArray = new MIntArray[geomLen]; fWeightsPtrArray = new MDoubleArray[geomLen]; for (int i = 0; i < geomLen; i++) { MDagPath dagPath; MObject component; selList.clear(); selList.add(geometryArray[i]); MStatus status = selList.getDagPath(0, dagPath, component); if (status != MS::kSuccess) { continue; } if (component.isNull()) dagPath.extendToShape(); MObject skinCluster = findSkinCluster(dagPath); if (!isSkinClusterIncluded(skinCluster)) { continue; } MFnSkinCluster skinClusterFn(skinCluster, &status); if (status != MS::kSuccess) { continue; } MIntArray influenceIndexArray; populateInfluenceIndexArray(skinClusterFn, influenceIndexArray); unsigned numInf = influenceIndexArray.length(); if (numInf == 0) continue; unsigned numCV = 0; if (dagPath.node().hasFn(MFn::kMesh)) { MItMeshVertex polyIter(dagPath, component, &status); if (status == MS::kSuccess) { numCV = polyIter.count(); } } else if (dagPath.node().hasFn(MFn::kNurbsSurface)) { MItSurfaceCV nurbsIter(dagPath, component, true, &status); if (status == MS::kSuccess) { while (!nurbsIter.isDone()) { numCV++; nurbsIter.next(); } } } else if (dagPath.node().hasFn(MFn::kNurbsCurve)) { MItCurveCV curveIter(dagPath, component, &status); if (status == MS::kSuccess) { while (!curveIter.isDone()) { numCV++; curveIter.next(); } } } unsigned numEntry = numCV * numInf; if (numEntry > 0) { MDoubleArray weights(numEntry); unsigned int numWeights = weightArray.length(); if (assignAllToSingle) { if (numInf <= numWeights) { for (unsigned j = 0; j < numEntry; j++) { weights[j] = weightArray[j % numInf]; } } else { MGlobal::displayError("Not enough weights specified\n"); return MS::kFailure; } } else { for (unsigned j = 0; j < numEntry; j++, ptr++) { if (ptr < numWeights) { weights[j] = weightArray[ptr]; } else { MGlobal::displayError("Not enough weights specified\n"); return MS::kFailure; } } } // support for undo fDagPathArray[i] = dagPath; fComponentArray[i] = component; fInfluenceIndexArrayPtrArray[i] = influenceIndexArray; MDoubleArray oldWeights; skinClusterFn.getWeights(dagPath, component, influenceIndexArray, oldWeights); fWeightsPtrArray[i] = oldWeights; skinClusterFn.setWeights(dagPath, component, influenceIndexArray, weights); } } return MS::kSuccess; }
MStatus AbcExport::doIt(const MArgList & args) { try { MStatus status; util::clearIsAnimatedCache(); MTime oldCurTime = MAnimControl::currentTime(); MArgParser argData(syntax(), args, &status); if (argData.isFlagSet("help")) { MGlobal::displayInfo(util::getHelpText()); return MS::kSuccess; } bool verbose = argData.isFlagSet("verbose"); // If skipFrame is true, when going through the playback range of the // scene, as much frames are skipped when possible. This could cause // a problem for, time dependent solutions like // particle system / hair simulation bool skipFrame = true; if (argData.isFlagSet("dontSkipUnwrittenFrames")) skipFrame = false; double startEvaluationTime = DBL_MAX; if (argData.isFlagSet("preRollStartFrame")) { double startAt = 0.0; argData.getFlagArgument("preRollStartFrame", 0, startAt); startEvaluationTime = startAt; } unsigned int jobSize = argData.numberOfFlagUses("jobArg"); if (jobSize == 0) return status; // the frame range we will be iterating over for all jobs, // includes frames which are not skipped and the startAt offset std::set<double> allFrameRange; // this will eventually hold only the animated jobs. // its a list because we will be removing jobs from it std::list < AbcWriteJobPtr > jobList; for (unsigned int jobIndex = 0; jobIndex < jobSize; jobIndex++) { JobArgs jobArgs; MArgList jobArgList; argData.getFlagArgumentList("jobArg", jobIndex, jobArgList); MString jobArgsStr = jobArgList.asString(0); MStringArray jobArgsArray; { // parse the job arguments // e.g. -perFrameCallbackMel "print \"something\"" will be splitted to // [0] -perFrameCallbackMel // [1] print "something" enum State { kArgument, // parsing an argument (not quoted) kDoubleQuotedString, // parsing a double quoted string kSingleQuotedString, // parsing a single quoted string }; State state = kArgument; MString stringBuffer; for (unsigned int charIdx = 0; charIdx < jobArgsStr.numChars(); charIdx++) { MString ch = jobArgsStr.substringW(charIdx, charIdx); switch (state) { case kArgument: if (ch == " ") { // space terminates the current argument if (stringBuffer.length() > 0) { jobArgsArray.append(stringBuffer); stringBuffer.clear(); } // goto another argument state = kArgument; } else if (ch == "\"") { if (stringBuffer.length() > 0) { // double quote is part of the argument stringBuffer += ch; } else { // goto double quoted string state = kDoubleQuotedString; } } else if (ch == "'") { if (stringBuffer.length() > 0) { // single quote is part of the argument stringBuffer += ch; } else { // goto single quoted string state = kSingleQuotedString; } } else { stringBuffer += ch; } break; case kDoubleQuotedString: // double quote terminates the current string if (ch == "\"") { jobArgsArray.append(stringBuffer); stringBuffer.clear(); state = kArgument; } else if (ch == "\\") { // escaped character MString nextCh = (++charIdx < jobArgsStr.numChars()) ? jobArgsStr.substringW(charIdx, charIdx) : "\\"; if (nextCh == "n") stringBuffer += "\n"; else if (nextCh == "t") stringBuffer += "\t"; else if (nextCh == "r") stringBuffer += "\r"; else if (nextCh == "\\") stringBuffer += "\\"; else if (nextCh == "'") stringBuffer += "'"; else if (nextCh == "\"") stringBuffer += "\""; else stringBuffer += nextCh; } else { stringBuffer += ch; } break; case kSingleQuotedString: // single quote terminates the current string if (ch == "'") { jobArgsArray.append(stringBuffer); stringBuffer.clear(); state = kArgument; } else if (ch == "\\") { // escaped character MString nextCh = (++charIdx < jobArgsStr.numChars()) ? jobArgsStr.substringW(charIdx, charIdx) : "\\"; if (nextCh == "n") stringBuffer += "\n"; else if (nextCh == "t") stringBuffer += "\t"; else if (nextCh == "r") stringBuffer += "\r"; else if (nextCh == "\\") stringBuffer += "\\"; else if (nextCh == "'") stringBuffer += "'"; else if (nextCh == "\"") stringBuffer += "\""; else stringBuffer += nextCh; } else { stringBuffer += ch; } break; } } // the rest of the argument if (stringBuffer.length() > 0) { jobArgsArray.append(stringBuffer); } } // the frame range within this job std::vector< FrameRangeArgs > frameRanges(1); frameRanges.back().startTime = oldCurTime.value(); frameRanges.back().endTime = oldCurTime.value(); frameRanges.back().strideTime = 1.0; bool hasRange = false; bool hasRoot = false; bool sampleGeo = true; // whether or not to subsample geometry std::string fileName; bool asOgawa = true; unsigned int numJobArgs = jobArgsArray.length(); for (unsigned int i = 0; i < numJobArgs; ++i) { MString arg = jobArgsArray[i]; arg.toLowerCase(); if (arg == "-f" || arg == "-file") { if (i+1 >= numJobArgs) { MGlobal::displayError("File incorrectly specified."); return MS::kFailure; } fileName = jobArgsArray[++i].asChar(); } else if (arg == "-fr" || arg == "-framerange") { if (i+2 >= numJobArgs || !jobArgsArray[i+1].isDouble() || !jobArgsArray[i+2].isDouble()) { MGlobal::displayError("Frame Range incorrectly specified."); return MS::kFailure; } // this is not the first -frameRange argument, we are going // to add one more frame range to the frame range array. if (hasRange) { frameRanges.push_back(FrameRangeArgs()); } hasRange = true; frameRanges.back().startTime = jobArgsArray[++i].asDouble(); frameRanges.back().endTime = jobArgsArray[++i].asDouble(); // make sure start frame is smaller or equal to endTime if (frameRanges.back().startTime > frameRanges.back().endTime) { std::swap(frameRanges.back().startTime, frameRanges.back().endTime); } } else if (arg == "-frs" || arg == "-framerelativesample") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble()) { MGlobal::displayError( "Frame Relative Sample incorrectly specified."); return MS::kFailure; } frameRanges.back().shutterSamples.insert( jobArgsArray[++i].asDouble()); } else if (arg == "-nn" || arg == "-nonormals") { jobArgs.noNormals = true; } else if (arg == "-pr" || arg == "-preroll") { frameRanges.back().preRoll = true; } else if (arg == "-ro" || arg == "-renderableonly") { jobArgs.excludeInvisible = true; } else if (arg == "-s" || arg == "-step") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isDouble()) { MGlobal::displayError("Step incorrectly specified."); return MS::kFailure; } frameRanges.back().strideTime = jobArgsArray[++i].asDouble(); } else if (arg == "-sl" || arg == "-selection") { jobArgs.useSelectionList = true; } else if (arg == "-sn" || arg == "-stripnamespaces") { if (i+1 >= numJobArgs || !jobArgsArray[i+1].isUnsigned()) { // the strip all namespaces case // so we pick a very LARGE number jobArgs.stripNamespace = 0xffffffff; } else { jobArgs.stripNamespace = jobArgsArray[++i].asUnsigned(); } } else if (arg == "-uv" || arg == "-uvwrite") { jobArgs.writeUVs = true; } else if (arg == "-wcs" || arg == "-writecolorsets") { jobArgs.writeColorSets = true; } else if (arg == "-wfs" || arg == "-writefacesets") { jobArgs.writeFaceSets = true; } else if (arg == "-wfg" || arg == "-wholeframegeo") { sampleGeo = false; } else if (arg == "-ws" || arg == "-worldspace") { jobArgs.worldSpace = true; } else if (arg == "-wv" || arg == "-writevisibility") { jobArgs.writeVisibility = true; } else if (arg == "-wc" || arg == "-writecreases") { jobArgs.writeCreases = true; } else if (arg == "-mfc" || arg == "-melperframecallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "melPerFrameCallback incorrectly specified."); return MS::kFailure; } jobArgs.melPerFrameCallback = jobArgsArray[++i].asChar(); } else if (arg == "-pfc" || arg == "-pythonperframecallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "pythonPerFrameCallback incorrectly specified."); return MS::kFailure; } jobArgs.pythonPerFrameCallback = jobArgsArray[++i].asChar(); } else if (arg == "-mpc" || arg == "-melpostjobcallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "melPostJobCallback incorrectly specified."); return MS::kFailure; } jobArgs.melPostCallback = jobArgsArray[++i].asChar(); } else if (arg == "-ppc" || arg == "-pythonpostjobcallback") { if (i+1 >= numJobArgs) { MGlobal::displayError( "pythonPostJobCallback incorrectly specified."); return MS::kFailure; } jobArgs.pythonPostCallback = jobArgsArray[++i].asChar(); } // geomArbParams - attribute filtering stuff else if (arg == "-atp" || arg == "-attrprefix") { if (i+1 >= numJobArgs) { MGlobal::displayError( "attrPrefix incorrectly specified."); return MS::kFailure; } jobArgs.prefixFilters.push_back(jobArgsArray[++i].asChar()); } else if (arg == "-a" || arg == "-attr") { if (i+1 >= numJobArgs) { MGlobal::displayError( "attr incorrectly specified."); return MS::kFailure; } jobArgs.attribs.insert(jobArgsArray[++i].asChar()); } // userProperties - attribute filtering stuff else if (arg == "-uatp" || arg == "-userattrprefix") { if (i+1 >= numJobArgs) { MGlobal::displayError( "userAttrPrefix incorrectly specified."); return MS::kFailure; } jobArgs.userPrefixFilters.push_back(jobArgsArray[++i].asChar()); } else if (arg == "-u" || arg == "-userattr") { if (i+1 >= numJobArgs) { MGlobal::displayError( "userAttr incorrectly specified."); return MS::kFailure; } jobArgs.userAttribs.insert(jobArgsArray[++i].asChar()); } else if (arg == "-rt" || arg == "-root") { if (i+1 >= numJobArgs) { MGlobal::displayError( "root incorrectly specified."); return MS::kFailure; } hasRoot = true; MString root = jobArgsArray[++i]; MSelectionList sel; if (sel.add(root) != MS::kSuccess) { MString warn = root; warn += " could not be select, skipping."; MGlobal::displayWarning(warn); continue; } unsigned int numRoots = sel.length(); for (unsigned int j = 0; j < numRoots; ++j) { MDagPath path; if (sel.getDagPath(j, path) != MS::kSuccess) { MString warn = path.fullPathName(); warn += " (part of "; warn += root; warn += " ) not a DAG Node, skipping."; MGlobal::displayWarning(warn); continue; } jobArgs.dagPaths.insert(path); } } else if (arg == "-ef" || arg == "-eulerfilter") { jobArgs.filterEulerRotations = true; } else if (arg == "-df" || arg == "-dataformat") { if (i+1 >= numJobArgs) { MGlobal::displayError( "dataFormat incorrectly specified."); return MS::kFailure; } MString dataFormat = jobArgsArray[++i]; dataFormat.toLowerCase(); if (dataFormat == "hdf") { asOgawa = false; } else if (dataFormat == "ogawa") { asOgawa = true; } } else { MString warn = "Ignoring unsupported flag: "; warn += jobArgsArray[i]; MGlobal::displayWarning(warn); } } // for i if (fileName == "") { MString error = "-file not specified."; MGlobal::displayError(error); return MS::kFailure; } { MString fileRule, expandName; MString alembicFileRule = "alembicCache"; MString alembicFilePath = "cache/alembic"; MString queryFileRuleCmd; queryFileRuleCmd.format("workspace -q -fre \"^1s\"", alembicFileRule); MString queryFolderCmd; queryFolderCmd.format("workspace -en `workspace -q -fre \"^1s\"`", alembicFileRule); // query the file rule for alembic cache MGlobal::executeCommand(queryFileRuleCmd, fileRule); if (fileRule.length() > 0) { // we have alembic file rule, query the folder MGlobal::executeCommand(queryFolderCmd, expandName); } else { // alembic file rule does not exist, create it MString addFileRuleCmd; addFileRuleCmd.format("workspace -fr \"^1s\" \"^2s\"", alembicFileRule, alembicFilePath); MGlobal::executeCommand(addFileRuleCmd); // save the workspace. maya may discard file rules on exit MGlobal::executeCommand("workspace -s"); // query the folder MGlobal::executeCommand(queryFolderCmd, expandName); } // resolve the expanded file rule if (expandName.length() == 0) { expandName = alembicFilePath; } // get the path to the alembic file rule MFileObject directory; directory.setRawFullName(expandName); MString directoryName = directory.resolvedFullName(); // make sure the cache folder exists if (!directory.exists()) { // create the cache folder MString createFolderCmd; createFolderCmd.format("sysFile -md \"^1s\"", directoryName); MGlobal::executeCommand(createFolderCmd); } // resolve the relative path MFileObject absoluteFile; absoluteFile.setRawFullName(fileName.c_str()); #if MAYA_API_VERSION < 201300 if (absoluteFile.resolvedFullName() != absoluteFile.expandedFullName()) { #else if (!MFileObject::isAbsolutePath(fileName.c_str())) { #endif // this is a relative path MString absoluteFileName = directoryName + "/" + fileName.c_str(); absoluteFile.setRawFullName(absoluteFileName); fileName = absoluteFile.resolvedFullName().asChar(); } else { fileName = absoluteFile.resolvedFullName().asChar(); } // check the path must exist before writing MFileObject absoluteFilePath; absoluteFilePath.setRawFullName(absoluteFile.path()); if (!absoluteFilePath.exists()) { MString error; error.format("Path ^1s does not exist!", absoluteFilePath.resolvedFullName()); MGlobal::displayError(error); return MS::kFailure; } // check the file is used by any AlembicNode in the scene MItDependencyNodes dgIter(MFn::kPluginDependNode); for (; !dgIter.isDone(); dgIter.next()) { MFnDependencyNode alembicNode(dgIter.thisNode()); if (alembicNode.typeName() != "AlembicNode") { continue; } MPlug abcFilePlug = alembicNode.findPlug("abc_File"); if (abcFilePlug.isNull()) { continue; } MFileObject alembicFile; alembicFile.setRawFullName(abcFilePlug.asString()); if (!alembicFile.exists()) { continue; } if (alembicFile.resolvedFullName() == absoluteFile.resolvedFullName()) { MString error = "Can't export to an Alembic file which is in use."; MGlobal::displayError(error); return MS::kFailure; } } std::ofstream ofs(fileName.c_str()); if (!ofs.is_open()) { MString error = MString("Can't write to file: ") + fileName.c_str(); MGlobal::displayError(error); return MS::kFailure; } ofs.close(); } // if -frameRelativeSample argument is not specified for a frame range, // we are assuming a -frameRelativeSample 0.0 for (std::vector<FrameRangeArgs>::iterator range = frameRanges.begin(); range != frameRanges.end(); ++range) { if (range->shutterSamples.empty()) range->shutterSamples.insert(0.0); } if (jobArgs.prefixFilters.empty()) { jobArgs.prefixFilters.push_back("ABC_"); } // the list of frame ranges for sampling std::vector<FrameRangeArgs> sampleRanges; std::vector<FrameRangeArgs> preRollRanges; for (std::vector<FrameRangeArgs>::const_iterator range = frameRanges.begin(); range != frameRanges.end(); ++range) { if (range->preRoll) preRollRanges.push_back(*range); else sampleRanges.push_back(*range); } // the list of frames written into the abc file std::set<double> geoSamples; std::set<double> transSamples; for (std::vector<FrameRangeArgs>::const_iterator range = sampleRanges.begin(); range != sampleRanges.end(); ++range) { for (double frame = range->startTime; frame <= range->endTime; frame += range->strideTime) { for (std::set<double>::const_iterator shutter = range->shutterSamples.begin(); shutter != range->shutterSamples.end(); ++shutter) { double curFrame = *shutter + frame; if (!sampleGeo) { double intFrame = (double)(int)( curFrame >= 0 ? curFrame + .5 : curFrame - .5); // only insert samples that are close to being an integer if (fabs(curFrame - intFrame) < 1e-4) { geoSamples.insert(curFrame); } } else { geoSamples.insert(curFrame); } transSamples.insert(curFrame); } } if (geoSamples.empty()) { geoSamples.insert(range->startTime); } if (transSamples.empty()) { transSamples.insert(range->startTime); } } bool isAcyclic = false; if (sampleRanges.empty()) { // no frame ranges or all frame ranges are pre-roll ranges hasRange = false; geoSamples.insert(frameRanges.back().startTime); transSamples.insert(frameRanges.back().startTime); } else { // check if the time range is even (cyclic) // otherwise, we will use acyclic // sub frames pattern std::vector<double> pattern( sampleRanges.begin()->shutterSamples.begin(), sampleRanges.begin()->shutterSamples.end()); std::transform(pattern.begin(), pattern.end(), pattern.begin(), std::bind2nd(std::plus<double>(), sampleRanges.begin()->startTime)); // check the frames against the pattern std::vector<double> timeSamples( transSamples.begin(), transSamples.end()); for (size_t i = 0; i < timeSamples.size(); i++) { // next pattern if (i % pattern.size() == 0 && i / pattern.size() > 0) { std::transform(pattern.begin(), pattern.end(), pattern.begin(), std::bind2nd(std::plus<double>(), sampleRanges.begin()->strideTime)); } // pattern mismatch, we use acyclic time sampling type if (timeSamples[i] != pattern[i % pattern.size()]) { isAcyclic = true; break; } } } // the list of frames to pre-roll std::set<double> preRollSamples; for (std::vector<FrameRangeArgs>::const_iterator range = preRollRanges.begin(); range != preRollRanges.end(); ++range) { for (double frame = range->startTime; frame <= range->endTime; frame += range->strideTime) { for (std::set<double>::const_iterator shutter = range->shutterSamples.begin(); shutter != range->shutterSamples.end(); ++shutter) { double curFrame = *shutter + frame; preRollSamples.insert(curFrame); } } if (preRollSamples.empty()) { preRollSamples.insert(range->startTime); } } if (jobArgs.dagPaths.size() > 1) { // check for validity of the DagPath relationships complexity : n^2 util::ShapeSet::const_iterator m, n; util::ShapeSet::const_iterator end = jobArgs.dagPaths.end(); for (m = jobArgs.dagPaths.begin(); m != end; ) { MDagPath path1 = *m; m++; for (n = m; n != end; n++) { MDagPath path2 = *n; if (util::isAncestorDescendentRelationship(path1,path2)) { MString errorMsg = path1.fullPathName(); errorMsg += " and "; errorMsg += path2.fullPathName(); errorMsg += " have an ancestor relationship."; MGlobal::displayError(errorMsg); return MS::kFailure; } } // for n } // for m } // no root is specified, and we aren't using a selection // so we'll try to translate the whole Maya scene by using all // children of the world as roots. else if (!hasRoot && !jobArgs.useSelectionList) { MSelectionList sel; #if MAYA_API_VERSION >= 201100 sel.add("|*", true); #else // older versions of Maya will not be able to find top level nodes // within namespaces sel.add("|*"); #endif unsigned int numRoots = sel.length(); for (unsigned int i = 0; i < numRoots; ++i) { MDagPath path; sel.getDagPath(i, path); jobArgs.dagPaths.insert(path); } } else if (hasRoot && jobArgs.dagPaths.empty()) { MString errorMsg = "No valid root nodes were specified."; MGlobal::displayError(errorMsg); return MS::kFailure; } else if (jobArgs.useSelectionList) { MSelectionList activeList; MGlobal::getActiveSelectionList(activeList); if (activeList.length() == 0) { MString errorMsg = "-selection specified but nothing is actively selected."; MGlobal::displayError(errorMsg); return MS::kFailure; } } AbcA::TimeSamplingPtr transTime, geoTime; if (hasRange) { if (isAcyclic) { // acyclic, uneven time sampling // e.g. [0.8, 1, 1.2], [2.8, 3, 3.2], .. not continuous // [0.8, 1, 1.2], [1.7, 2, 2.3], .. shutter different std::vector<double> samples( transSamples.begin(), transSamples.end()); std::transform(samples.begin(), samples.end(), samples.begin(), std::bind2nd(std::multiplies<double>(), util::spf())); transTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType( AbcA::TimeSamplingType::kAcyclic), samples)); } else { // cyclic, even time sampling between time periods // e.g. [0.8, 1, 1.2], [1.8, 2, 2.2], ... std::vector<double> samples; double startTime = sampleRanges[0].startTime; double strideTime = sampleRanges[0].strideTime; for (std::set<double>::const_iterator shutter = sampleRanges[0].shutterSamples.begin(); shutter != sampleRanges[0].shutterSamples.end(); ++shutter) { samples.push_back((startTime + *shutter) * util::spf()); } if (samples.size() > 1) { Alembic::Util::uint32_t numSamples = static_cast<Alembic::Util::uint32_t>(samples.size()); transTime.reset( new AbcA::TimeSampling(AbcA::TimeSamplingType( numSamples, strideTime * util::spf()), samples)); } // uniform sampling else { transTime.reset(new AbcA::TimeSampling( strideTime * util::spf(), samples[0])); } } } else { // time ranges are not specified transTime.reset(new AbcA::TimeSampling()); } if (sampleGeo || !hasRange) { geoTime = transTime; } else { // sampling geo on whole frames if (isAcyclic) { // acyclic, uneven time sampling std::vector<double> samples( geoSamples.begin(), geoSamples.end()); // one more sample for setup() if (*transSamples.begin() != *geoSamples.begin()) samples.insert(samples.begin(), *transSamples.begin()); std::transform(samples.begin(), samples.end(), samples.begin(), std::bind2nd(std::multiplies<double>(), util::spf())); geoTime.reset(new AbcA::TimeSampling(AbcA::TimeSamplingType( AbcA::TimeSamplingType::kAcyclic), samples)); } else { double geoStride = sampleRanges[0].strideTime; if (geoStride < 1.0) geoStride = 1.0; double geoStart = *geoSamples.begin() * util::spf(); geoTime.reset(new AbcA::TimeSampling( geoStride * util::spf(), geoStart)); } } AbcWriteJobPtr job(new AbcWriteJob(fileName.c_str(), asOgawa, transSamples, transTime, geoSamples, geoTime, jobArgs)); jobList.push_front(job); // make sure we add additional whole frames, if we arent skipping // the inbetween ones if (!skipFrame && !allFrameRange.empty()) { double localMin = *(transSamples.begin()); std::set<double>::iterator last = transSamples.end(); last--; double localMax = *last; double globalMin = *(allFrameRange.begin()); last = allFrameRange.end(); last--; double globalMax = *last; // if the min of our current frame range is beyond // what we know about, pad a few more frames if (localMin > globalMax) { for (double f = globalMax; f < localMin; f++) { allFrameRange.insert(f); } } // if the max of our current frame range is beyond // what we know about, pad a few more frames if (localMax < globalMin) { for (double f = localMax; f < globalMin; f++) { allFrameRange.insert(f); } } } // right now we just copy over the translation samples since // they are guaranteed to contain all the geometry samples allFrameRange.insert(transSamples.begin(), transSamples.end()); // copy over the pre-roll samples allFrameRange.insert(preRollSamples.begin(), preRollSamples.end()); } // add extra evaluation run up, if necessary if (startEvaluationTime != DBL_MAX && !allFrameRange.empty()) { double firstFrame = *allFrameRange.begin(); for (double f = startEvaluationTime; f < firstFrame; ++f) { allFrameRange.insert(f); } } std::set<double>::iterator it = allFrameRange.begin(); std::set<double>::iterator itEnd = allFrameRange.end(); MComputation computation; computation.beginComputation(); // loop through every frame in the list, if a job has that frame in it's // list of transform or shape frames, then it will write out data and // call the perFrameCallback, if that frame is also the last one it has // to work on then it will also call the postCallback. // If it doesn't have this frame, then it does nothing for (; it != itEnd; it++) { if (verbose) { double frame = *it; MString info; info = frame; MGlobal::displayInfo(info); } MGlobal::viewFrame(*it); std::list< AbcWriteJobPtr >::iterator j = jobList.begin(); std::list< AbcWriteJobPtr >::iterator jend = jobList.end(); while (j != jend) { if (computation.isInterruptRequested()) return MS::kFailure; bool lastFrame = (*j)->eval(*it); if (lastFrame) { j = jobList.erase(j); } else j++; } } computation.endComputation(); // set the time back MGlobal::viewFrame(oldCurTime); return MS::kSuccess; } catch (Alembic::Util::Exception & e) { MString theError("Alembic Exception encountered: "); theError += e.what(); MGlobal::displayError(theError); return MS::kFailure; } catch (std::exception & e) { MString theError("std::exception encountered: "); theError += e.what(); MGlobal::displayError(theError); return MS::kFailure; } }
// Load a joint void skeleton::loadJoint(MDagPath& jointDag,joint* parent) { int i; joint newJoint; joint* parentJoint = parent; if (jointDag.hasFn(MFn::kJoint)) { MFnIkJoint jointFn(jointDag); // Get parent index int idx=-1; if (parent) { idx = parent->id; } // Get joint matrix MMatrix worldMatrix = jointDag.inclusiveMatrix(); /*float translation1[3]; float rotation1[4]; float scale1[3]; extractTranMatrix(worldMatrix,translation1,rotation1,scale1); Quaternion q(rotation1[0],rotation1[1],rotation1[2],rotation1[3]); float angle; Vector3 axis; q.ToAngleAxis(angle,axis); Vector3 x,y,z; q.ToAxes(x,y,z);*/ //printMatrix(worldMatrix); // Calculate scaling factor inherited by parent // Calculate Local Matrix MMatrix localMatrix = worldMatrix; if (parent) localMatrix = worldMatrix * parent->worldMatrix.inverse(); float translation2[3]; float rotation2[4]; float scale2[3]; extractTranMatrix(worldMatrix,translation2,rotation2,scale2); //printMatrix(localMatrix); // Set joint info newJoint.name = jointFn.partialPathName(); newJoint.id = m_joints.size(); newJoint.parentIndex = idx; newJoint.jointDag = jointDag; newJoint.worldMatrix = worldMatrix; newJoint.localMatrix = localMatrix; for (int iRow = 0; iRow < 4; iRow++) for (int iCol = 0; iCol < 3; iCol++) newJoint.tran.m_mat[iRow][iCol] = (FLOAT)worldMatrix[iRow][iCol]; //printMatrix(worldMatrix); /*MQuaternion q; q = worldMatrix; newJoint.tran.q[0] = (float)q.x; newJoint.tran.q[1] = (float)q.y; newJoint.tran.q[2] = (float)q.z; newJoint.tran.q[3] = (float)q.w; newJoint.tran.t[0] = (float)worldMatrix[3][0]; newJoint.tran.t[1] = (float)worldMatrix[3][1]; newJoint.tran.t[2] = (float)worldMatrix[3][2];*/ MPlug plug = jointFn.findPlug("unRibbonEnabled"); if(!plug.isNull()) { bool enabled; plug.getValue(enabled); if(enabled) { plug = jointFn.findPlug("unRibbonVisible"); bool visible; plug.getValue(visible); plug = jointFn.findPlug("unRibbonAbove"); float above; plug.getValue(above); plug = jointFn.findPlug("unRibbonBelow"); float below; plug.getValue(below); plug = jointFn.findPlug("unRibbonEdgesPerSecond"); short edgePerSecond; plug.getValue(edgePerSecond); plug = jointFn.findPlug("unRibbonEdgeLife"); float edgeLife; plug.getValue(edgeLife); plug = jointFn.findPlug("unRibbonGravity"); float gravity; plug.getValue(gravity); plug = jointFn.findPlug("unRibbonTextureRows"); short rows; plug.getValue(rows); plug = jointFn.findPlug("unRibbonTextureCols"); short cols; plug.getValue(cols); plug = jointFn.findPlug("unRibbonTextureSlot"); short slot; plug.getValue(slot); plug = jointFn.findPlug("unRibbonVertexColor"); MObject object; plug.getValue(object); MFnNumericData data(object); float r,g,b; data.getData(r,g,b); plug = jointFn.findPlug("unRibbonVertexAlpha"); float alpha; plug.getValue(alpha); plug = jointFn.findPlug("unRibbonBlendMode"); short blendMode; plug.getValue(blendMode); plug = jointFn.findPlug("unRibbonTextureFilename"); MItDependencyGraph dgIt(plug, MFn::kFileTexture, MItDependencyGraph::kUpstream, MItDependencyGraph::kBreadthFirst, MItDependencyGraph::kNodeLevel); dgIt.disablePruningOnFilter(); MString textureName; if (!dgIt.isDone()) { MObject textureNode = dgIt.thisNode(); MPlug filenamePlug = MFnDependencyNode(textureNode).findPlug("fileTextureName"); filenamePlug.getValue(textureName); } else { char str[256]; sprintf(str,"%s ribbon system must has file-texture",newJoint.name.asChar()); MessageBox(0,str,0,0); } newJoint.hasRibbonSystem = true; newJoint.ribbon.visible = visible; newJoint.ribbon.above = above; newJoint.ribbon.below = below; newJoint.ribbon.gravity = gravity; newJoint.ribbon.edgePerSecond = edgePerSecond; newJoint.ribbon.edgeLife = edgeLife; newJoint.ribbon.rows = rows; newJoint.ribbon.cols = cols; newJoint.ribbon.slot = slot; newJoint.ribbon.color[0] = r; newJoint.ribbon.color[1] = g; newJoint.ribbon.color[2] = b; newJoint.ribbon.alpha = alpha; newJoint.ribbon.blendMode = blendMode; newJoint.ribbon.textureFilename = textureName.asChar(); } } plug = jointFn.findPlug("unParticleEnabled"); if(!plug.isNull()) { bool enabled; plug.getValue(enabled); if(enabled) { newJoint.hasParticleSystem = true; plug = jointFn.findPlug("unParticleVisible"); bool visible; plug.getValue(visible); plug = jointFn.findPlug("unParticleSpeed"); float speed; plug.getValue(speed); plug = jointFn.findPlug("unParticleVariationPercent"); float variation; plug.getValue(variation); plug = jointFn.findPlug("unParticleConeAngle"); float coneAngle; plug.getValue(coneAngle); plug = jointFn.findPlug("unParticleGravity"); float gravity; plug.getValue(gravity); plug = jointFn.findPlug("unParticleExplosiveForce"); float explosiveForce = 0.0f; if(!plug.isNull()) { plug.getValue(explosiveForce); } plug = jointFn.findPlug("unParticleLife"); float life; plug.getValue(life); plug = jointFn.findPlug("unParticleLifeVariation"); float lifeVar; if(plug.isNull()) { lifeVar = 0.0f; } else { plug.getValue(lifeVar); } plug = jointFn.findPlug("unParticleEmissionRate"); float emissionRate; plug.getValue(emissionRate); plug = jointFn.findPlug("unParticleLimitNum"); short limitNum; plug.getValue(limitNum); plug = jointFn.findPlug("unParticleInitialNum"); short initialNum = 0; if(!plug.isNull())plug.getValue(initialNum); plug = jointFn.findPlug("unParticleAttachToEmitter"); bool attachToEmitter; plug.getValue(attachToEmitter); plug = jointFn.findPlug("unParticleMoveWithEmitter"); bool moveWithEmitter = false; if(!plug.isNull())plug.getValue(moveWithEmitter); //23 plug = jointFn.findPlug("unParticleForTheSword"); bool forTheSword = false; if(!plug.isNull())plug.getValue(forTheSword); //24 plug = jointFn.findPlug("unParticleForTheSwordInitialAngle"); float forTheSwordInitialAngle = 0; if(!plug.isNull())plug.getValue(forTheSwordInitialAngle); //25 plug = jointFn.findPlug("unParticleWander"); bool wander = false; if(!plug.isNull())plug.getValue(wander); //25 plug = jointFn.findPlug("unParticleWanderRadius"); float wanderRadius = 0.0f; if(!plug.isNull())plug.getValue(wanderRadius); //25 plug = jointFn.findPlug("unParticleWanderSpeed"); float wanderSpeed = 0.0f; if(!plug.isNull())plug.getValue(wanderSpeed); plug = jointFn.findPlug("unParticleAspectRatio"); float aspectRatio; if(plug.isNull()) { aspectRatio = 1.0f; } else { plug.getValue(aspectRatio); } plug = jointFn.findPlug("unParticleInitialAngleBegin"); float angleBegin; if(plug.isNull()) { angleBegin = 0.0f; } else { plug.getValue(angleBegin); } plug = jointFn.findPlug("unParticleInitialAngleEnd"); float angleEnd; if(plug.isNull()) { angleEnd = 0.0f; } else { plug.getValue(angleEnd); } plug = jointFn.findPlug("unParticleRotationSpeed"); float rotationSpeed; if(plug.isNull()) { rotationSpeed = 0; } else { plug.getValue(rotationSpeed); } plug = jointFn.findPlug("unParticleRotationSpeedVar"); float rotationSpeedVar; if(plug.isNull()) { rotationSpeedVar = 0; } else { plug.getValue(rotationSpeedVar); } plug = jointFn.findPlug("unParticleEmitterWidth"); float width; plug.getValue(width); plug = jointFn.findPlug("unParticleEmitterLength"); float length; plug.getValue(length); plug = jointFn.findPlug("unParticleEmitterHeight"); float height = 0.0f; if(!plug.isNull()) { plug.getValue(height); } plug = jointFn.findPlug("unParticleBlendMode"); short blendMode; plug.getValue(blendMode); plug = jointFn.findPlug("unParticleTextureFilename"); MItDependencyGraph dgIt(plug, MFn::kFileTexture, MItDependencyGraph::kUpstream, MItDependencyGraph::kBreadthFirst, MItDependencyGraph::kNodeLevel); dgIt.disablePruningOnFilter(); MString textureName; if (!dgIt.isDone()) { MObject textureNode = dgIt.thisNode(); MPlug filenamePlug = MFnDependencyNode(textureNode).findPlug("fileTextureName"); filenamePlug.getValue(textureName); } else { char str[256]; sprintf(str,"%s particle system must has file-texture",newJoint.name.asChar()); MessageBox(0,str,0,0); } plug = jointFn.findPlug("unParticleTextureRows"); short rows; plug.getValue(rows); plug = jointFn.findPlug("unParticleTextureCols"); short cols; plug.getValue(cols); plug = jointFn.findPlug("unParticleTextureChangeStyle"); short changeStyle; if(plug.isNull()) { //0 - 顺序 //1 - 随机 changeStyle = 0; } else { plug.getValue(changeStyle); } plug = jointFn.findPlug("unParticleTextureChangeInterval"); short changeInterval; if(plug.isNull()) { //默认30ms换一个 changeInterval = 30; } else { plug.getValue(changeInterval); } plug = jointFn.findPlug("unParticleTailLength"); float tailLength; plug.getValue(tailLength); plug = jointFn.findPlug("unParticleTimeMiddle"); float timeMiddle; plug.getValue(timeMiddle); plug = jointFn.findPlug("unParticleColorStart"); MObject object; plug.getValue(object); MFnNumericData dataS(object); float colorStart[3]; dataS.getData(colorStart[0],colorStart[1],colorStart[2]); plug = jointFn.findPlug("unParticleColorMiddle"); plug.getValue(object); MFnNumericData dataM(object); float colorMiddle[3]; dataM.getData(colorMiddle[0],colorMiddle[1],colorMiddle[2]); plug = jointFn.findPlug("unParticleColorEnd"); plug.getValue(object); MFnNumericData dataE(object); float colorEnd[3]; dataE.getData(colorEnd[0],colorEnd[1],colorEnd[2]); plug = jointFn.findPlug("unParticleAlpha"); plug.getValue(object); MFnNumericData dataAlpha(object); float alpha[3]; dataAlpha.getData(alpha[0],alpha[1],alpha[2]); //Scale plug = jointFn.findPlug("unParticleScale"); plug.getValue(object); MFnNumericData dataScale(object); float scale[3]; dataScale.getData(scale[0],scale[1],scale[2]); //ScaleVar plug = jointFn.findPlug("unParticleScaleVar"); float scaleVar[3] = {0.0f,0.0f,0.0f}; if(!plug.isNull()) { plug.getValue(object); MFnNumericData dataScaleVar(object); dataScaleVar.getData(scaleVar[0],scaleVar[1],scaleVar[2]); } //FixedSize plug = jointFn.findPlug("unParticleFixedSize"); bool fixedSize = false; if(!plug.isNull()) { plug.getValue(fixedSize); } //HeadLifeSpan plug = jointFn.findPlug("unParticleHeadLifeSpan"); plug.getValue(object); MFnNumericData dataHeadLifeSpan(object); short headLifeSpan[3]; dataHeadLifeSpan.getData(headLifeSpan[0],headLifeSpan[1],headLifeSpan[2]); plug = jointFn.findPlug("unParticleHeadDecay"); plug.getValue(object); MFnNumericData dataHeadDecay(object); short headDecay[3]; dataHeadDecay.getData(headDecay[0],headDecay[1],headDecay[2]); plug = jointFn.findPlug("unParticleTailLifeSpan"); plug.getValue(object); MFnNumericData dataTailLifeSpan(object); short tailLifeSpan[3]; dataTailLifeSpan.getData(tailLifeSpan[0],tailLifeSpan[1],tailLifeSpan[2]); plug = jointFn.findPlug("unParticleTailDecay"); plug.getValue(object); MFnNumericData dataTailDecay(object); short tailDecay[3]; dataTailDecay.getData(tailDecay[0],tailDecay[1],tailDecay[2]); plug = jointFn.findPlug("unParticleHead"); bool head; plug.getValue(head); plug = jointFn.findPlug("unParticleTail"); bool tail; plug.getValue(tail); plug = jointFn.findPlug("unParticleUnShaded"); bool unshaded; plug.getValue(unshaded); plug = jointFn.findPlug("unParticleUnFogged"); bool unfogged; plug.getValue(unfogged); plug = jointFn.findPlug("unParticleBlockByY0"); bool blockByY0 = false; if(!plug.isNull()) plug.getValue(blockByY0); newJoint.particle.visible = visible; newJoint.particle.speed = speed; newJoint.particle.variation = variation / 100.0f; newJoint.particle.coneAngle = coneAngle; newJoint.particle.gravity = gravity; newJoint.particle.explosiveForce = explosiveForce; newJoint.particle.life = life; newJoint.particle.lifeVar = lifeVar; newJoint.particle.emissionRate = emissionRate; newJoint.particle.initialNum = initialNum; newJoint.particle.limitNum = limitNum; newJoint.particle.attachToEmitter = attachToEmitter; newJoint.particle.moveWithEmitter = moveWithEmitter; newJoint.particle.forTheSword = forTheSword; newJoint.particle.forTheSwordInitialAngle = forTheSwordInitialAngle; newJoint.particle.wander = wander; newJoint.particle.wanderRadius = wanderRadius; newJoint.particle.wanderSpeed = wanderSpeed; newJoint.particle.aspectRatio = aspectRatio; newJoint.particle.initialAngleBegin = angleBegin; newJoint.particle.initialAngleEnd = angleEnd; newJoint.particle.rotationSpeed = rotationSpeed; newJoint.particle.rotationSpeedVar = rotationSpeedVar; newJoint.particle.width = width; newJoint.particle.length = length; newJoint.particle.height = height; newJoint.particle.blendMode = blendMode; newJoint.particle.textureFilename = textureName.asChar(); newJoint.particle.textureRows = rows; newJoint.particle.textureCols = cols; newJoint.particle.changeStyle = changeStyle; newJoint.particle.changeInterval = changeInterval; newJoint.particle.tailLength = tailLength; newJoint.particle.timeMiddle = timeMiddle; newJoint.particle.colorStart[0] = colorStart[0]; newJoint.particle.colorStart[1] = colorStart[1]; newJoint.particle.colorStart[2] = colorStart[2]; newJoint.particle.colorMiddle[0] = colorMiddle[0]; newJoint.particle.colorMiddle[1] = colorMiddle[1]; newJoint.particle.colorMiddle[2] = colorMiddle[2]; newJoint.particle.colorEnd[0] = colorEnd[0]; newJoint.particle.colorEnd[1] = colorEnd[1]; newJoint.particle.colorEnd[2] = colorEnd[2]; newJoint.particle.alpha[0] = alpha[0]; newJoint.particle.alpha[1] = alpha[1]; newJoint.particle.alpha[2] = alpha[2]; newJoint.particle.scale[0] = scale[0]; newJoint.particle.scale[1] = scale[1]; newJoint.particle.scale[2] = scale[2]; newJoint.particle.scaleVar[0] = scaleVar[0]; newJoint.particle.scaleVar[1] = scaleVar[1]; newJoint.particle.scaleVar[2] = scaleVar[2]; newJoint.particle.fixedSize = fixedSize; newJoint.particle.headLifeSpan[0] = headLifeSpan[0]; newJoint.particle.headLifeSpan[1] = headLifeSpan[1]; newJoint.particle.headLifeSpan[2] = headLifeSpan[2]; newJoint.particle.headDecay[0] = headDecay[0]; newJoint.particle.headDecay[1] = headDecay[1]; newJoint.particle.headDecay[2] = headDecay[2]; newJoint.particle.tailLifeSpan[0] = tailLifeSpan[0]; newJoint.particle.tailLifeSpan[1] = tailLifeSpan[1]; newJoint.particle.tailLifeSpan[2] = tailLifeSpan[2]; newJoint.particle.tailDecay[0] = tailDecay[0]; newJoint.particle.tailDecay[1] = tailDecay[1]; newJoint.particle.tailDecay[2] = tailDecay[2]; newJoint.particle.head = head; newJoint.particle.tail = tail; newJoint.particle.unshaded = unshaded; newJoint.particle.unfogged = unfogged; newJoint.particle.blockByY0 = blockByY0; } } m_joints.push_back(newJoint); // Get pointer to newly created joint parentJoint = &newJoint; } // Load children joints for (i=0; i<jointDag.childCount();i++) { MObject child; child = jointDag.child(i); MDagPath childDag = jointDag; childDag.push(child); loadJoint(childDag,parentJoint); } }
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; }
MStatus unCreateParticleSystem::doIt( const MArgList& args ) { bool create = true; MSelectionList activeList; MStatus stat = MGlobal::getActiveSelectionList(activeList); if (MS::kSuccess != stat) { MessageBox(0,"please select one joint first!",0,0); return MS::kFailure; } if(activeList.length() != 1) { MessageBox(0,"please select ONLY one joint!",0,0); return MS::kFailure; } MItSelectionList iter(activeList); MDagPath dagPath; for ( ; !iter.isDone(); iter.next()) { stat = iter.getDagPath(dagPath); break; } if(!stat) { MessageBox(0,"can't getDagPath!",0,0); return MS::kFailure; } if(!dagPath.hasFn(MFn::kJoint)) { MessageBox(0,"muse select joint node!",0,0); return MS::kFailure; } MFnIkJoint joint(dagPath); if(args.length()) create = args.asBool(0); if(!create) { if(!joint.hasAttribute("unParticleEnabled")) { MessageBox(0,"no particle system exists!",0,0); return MS::kFailure; } removeParticleAttributes(joint); return MS::kSuccess; } if(joint.hasAttribute("unParticleEnabled")) { MessageBox(0,"particle system already exists!",0,0); return MS::kSuccess; } if(joint.hasAttribute("unRibbonEnabled")) { if(MessageBox(0,"will delete ribbon system and attach a particle system to the joint,continue?",0,MB_YESNO) == IDNO)return MS::kFailure; removeRibbonAttributes(joint); } MFnNumericAttribute attr; unParticleEnabled = attr.create("unParticleEnabled","Enabled",MFnNumericData::kBoolean,true); attr.setStorable(true); unParticleVisible = attr.create("unParticleVisible","Visible",MFnNumericData::kBoolean,true); attr.setStorable(true); attr.setKeyable(true); unParticleSpeed = attr.create("unParticleSpeed","Speed",MFnNumericData::kFloat,40.0f); attr.setStorable(true); attr.setMin(-1000.0f); attr.setMax(1000.0f); attr.setKeyable(true); unParticleVariation = attr.create("unParticleVariationPercent","VariationPercent",MFnNumericData::kFloat,2.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(100.0f); attr.setKeyable(true); unParticleConeAngle = attr.create("unParticleConeAngle","ConeAngle",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(180.0f); attr.setKeyable(true); unParticleGravity = attr.create("unParticleGravity","Gravity",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(-1000.0f); attr.setMax(1000.0f); attr.setKeyable(true); unParticleExplosiveForce = attr.create("unParticleExplosiveForce","ExplosiveForce",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(-100.0f); attr.setMax(100.0f); attr.setKeyable(true); unParticleLife = attr.create("unParticleLife","Life",MFnNumericData::kFloat,1.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(1000.0f); unParticleLifeVariation = attr.create("unParticleLifeVariation","LifeVar",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(-16.0f); attr.setMax(16.0f); unParticleEmissionRate = attr.create("unParticleEmissionRate","EmissionRate",MFnNumericData::kFloat,50.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(1000.0f); attr.setKeyable(true); //版本号17加入,初始粒子数 unParticleInitialNum = attr.create("unParticleInitialNum","InitialNum",MFnNumericData ::kShort,0); attr.setStorable(true); attr.setMin(0); attr.setMax(512); //版本号11加入,最大粒子数 unParticleLimitNum = attr.create("unParticleLimitNum","LimitNum",MFnNumericData ::kShort,32); attr.setStorable(true); attr.setMin(1); attr.setMax(512); //版本号13加入,粒子全部跟随发射点 unParticleAttachToEmitter = attr.create("unParticleAttachToEmitter","AttachToEmitter",MFnNumericData::kBoolean,false); attr.setStorable(true); //版本号18加入,粒子跟随发射点移动 unParticleMoveWithEmitter = attr.create("unParticleMoveWithEmitter","MoveWithEmitter",MFnNumericData::kBoolean,false); attr.setStorable(true); //版本号23加入,粒子指向速度方向 unParticleForTheSword = attr.create("unParticleForTheSword","ForTheSword",MFnNumericData::kBoolean,false); attr.setStorable(true); //版本号24加入,粒子指向速度方向,提供一个角度供初始化 unParticleForTheSwordInitialAngle = attr.create("unParticleForTheSwordInitialAngle","ForTheSwordInitialAngle",MFnNumericData::kFloat,0); attr.setStorable(true); attr.setMin(-180.0f); attr.setMax(180.0f); //版本号25,Wander unParticleWander = attr.create("unParticleWander","Wander",MFnNumericData::kBoolean,false); attr.setStorable(true); //版本号25,WanderRadius unParticleWanderRadius = attr.create("unParticleWanderRadius","WanderRadius",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(1024.0f); //版本号25,WanderSpeed unParticleWanderSpeed = attr.create("unParticleWanderSpeed","WanderSpeed",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(16.0f); unParticleAspectRatio = attr.create("unParticleAspectRatio","AspectRatio",MFnNumericData::kFloat,1.0f); attr.setStorable(true); attr.setMin(0.0625f); attr.setMax(16.0f); unParticleInitialAngleBegin = attr.create("unParticleInitialAngleBegin","InitialAngleBegin",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(-180.0f); attr.setMax(180.0f); unParticleInitialAngleEnd = attr.create("unParticleInitialAngleEnd","InitialAngleEnd",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(-180.0f); attr.setMax(180.0f); unParticleRotationSpeed = attr.create("unParticleRotationSpeed","RotationSpeed",MFnNumericData::kFloat,0); attr.setStorable(true); attr.setMin(-64.0f); //原来默认为16,鲍振伟要求改大 attr.setMax(64.0f); unParticleRotationSpeedVar = attr.create("unParticleRotationSpeedVar","RotationSpeedVar",MFnNumericData::kFloat,0); attr.setStorable(true); attr.setMin(0); attr.setMax(64); unParticleEmitterWidth = attr.create("unParticleEmitterWidth","EmitterWidth",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(1000.0f); attr.setKeyable(true); unParticleEmitterLength = attr.create("unParticleEmitterLength","EmitterLength",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(1000.0f); attr.setKeyable(true); unParticleEmitterHeight = attr.create("unParticleEmitterHeight","EmitterHeight",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(1000.0f); attr.setKeyable(true); MFnEnumAttribute eAttr; unParticleBlendMode = eAttr.create("unParticleBlendMode","BlendMode",3); eAttr.setStorable(true); eAttr.addField("Opaque",0); eAttr.addField("Transparent",1); eAttr.addField("AlphaBlend",2); eAttr.addField("Additive",3); eAttr.addField("AdditiveAlpha",4); eAttr.addField("Modulate",5); /*unParticleBlendModeSrc = eAttr.create("unParticleBlendModeSrc","BlendModeSrc",3); eAttr.setStorable(true); eAttr.addField("SBF_ONE",0); eAttr.addField("SBF_ZERO",1); eAttr.addField("SBF_DEST_COLOR",2); eAttr.addField("SBF_SOURCE_COLOR",3); eAttr.addField("SBF_ONE_MINUS_DEST_COLOR",4); eAttr.addField("SBF_ONE_MINUS_SOURCE_COLOR",5); eAttr.addField("SBF_DEST_ALPHA",6); eAttr.addField("SBF_SOURCE_ALPHA",7); eAttr.addField("SBF_ONE_MINUS_DEST_ALPHA",8); eAttr.addField("SBF_ONE_MINUS_SOURCE_ALPHA",9); unParticleBlendModeDst = eAttr.create("unParticleBlendModeDst","BlendModeDst",0); eAttr.setStorable(true); eAttr.addField("SBF_ONE",0); eAttr.addField("SBF_ZERO",1); eAttr.addField("SBF_DEST_COLOR",2); eAttr.addField("SBF_SOURCE_COLOR",3); eAttr.addField("SBF_ONE_MINUS_DEST_COLOR",4); eAttr.addField("SBF_ONE_MINUS_SOURCE_COLOR",5); eAttr.addField("SBF_DEST_ALPHA",6); eAttr.addField("SBF_SOURCE_ALPHA",7); eAttr.addField("SBF_ONE_MINUS_DEST_ALPHA",8); eAttr.addField("SBF_ONE_MINUS_SOURCE_ALPHA",9);*/ unParticleTextureFilename = attr.createColor("unParticleTextureFilename","TextureFilename"); attr.setStorable(true); unParticleTextureRows = attr.create("unParticleTextureRows","TextureRows",MFnNumericData::kShort,1); attr.setStorable(true); attr.setMin(1); attr.setMax(16); unParticleTextureCols = attr.create("unParticleTextureCols","TextureCols",MFnNumericData::kShort,1); attr.setStorable(true); attr.setMin(1); attr.setMax(16); unParticleTextureChangeStyle = eAttr.create("unParticleTextureChangeStyle","TextureChangeStyle",0); eAttr.setStorable(true); eAttr.addField("Sequence",0); eAttr.addField("Random",1); unParticleTextureChangeInterval = attr.create("unParticleTextureChangeInterval","TextureChangeInterval",MFnNumericData::kShort,30); attr.setStorable(true); attr.setMin(1); attr.setMax(5000); unParticleTailLength = attr.create("unParticleTailLength","TailLength",MFnNumericData::kFloat,1.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(10.0f); unParticleTimeMiddle = attr.create("unParticleTimeMiddle","TimeMiddle",MFnNumericData::kFloat,0.3f); attr.setStorable(true); attr.setMin(0.05f); attr.setMax(0.95f); unParticleColorStart = attr.createColor("unParticleColorStart","ColorStart"); attr.setStorable(true); attr.setDefault(1.0f,1.0f,1.0f); unParticleColorMiddle = attr.createColor("unParticleColorMiddle","ColorMiddle"); attr.setStorable(true); attr.setDefault(1.0f,1.0f,1.0f); unParticleColorEnd = attr.createColor("unParticleColorEnd","ColorEnd"); attr.setStorable(true); attr.setDefault(1.0f,1.0f,1.0f); unParticleAlpha = attr.create("unParticleAlpha","Alpha",MFnNumericData::k3Float); attr.setStorable(true); attr.setDefault(1.0f,1.0f,0.0f); attr.setMin(0.0f,0.0f,0.0f); attr.setMax(1.0f,1.0f,1.0f); unParticleScale = attr.create("unParticleScale","Scale",MFnNumericData::k3Float); attr.setStorable(true); attr.setDefault(10.0f,10.0f,10.0f); attr.setMin(0.001f,0.001f,0.001f); attr.setMax(1500.0f,1500.0f,1500.0f); //原来是500,鲍振伟要求改大 unParticleScaleVar = attr.create("unParticleScaleVar","ScaleVar",MFnNumericData::k3Float); attr.setStorable(true); attr.setDefault(0.0f,0.0f,0.0f); attr.setMin(0.0f,0.0f,0.0f); attr.setMax(500.0f,500.0f,500.0f);//原来是100,鲍振伟要求改大 unParticleFixedSize = attr.create("unParticleFixedSize","FixedSize",MFnNumericData::kBoolean,false); attr.setStorable(true); unParticleHeadLifeSpan = attr.create("unParticleHeadLifeSpan","HeadLifeSpan",MFnNumericData::k3Short); attr.setStorable(true); attr.setDefault(0,0,1); attr.setMin(0,0,1); attr.setMax(255,255,255); unParticleHeadDecay = attr.create("unParticleHeadDecay","HeadDecay",MFnNumericData::k3Short); attr.setStorable(true); attr.setDefault(0,0,1); attr.setMin(0,0,1); attr.setMax(255,255,255); unParticleTailLifeSpan = attr.create("unParticleTailLifeSpan","TailLifeSpan",MFnNumericData::k3Short); attr.setStorable(true); attr.setDefault(0,0,1); attr.setMin(0,0,1); attr.setMax(255,255,255); unParticleTailDecay = attr.create("unParticleTailDecay","TailDecay",MFnNumericData::k3Short); attr.setStorable(true); attr.setDefault(0,0,1); attr.setMin(0,0,1); attr.setMax(255,255,255); unParticleHead = attr.create("unParticleHead","Head",MFnNumericData::kBoolean,true); attr.setStorable(true); unParticleTail = attr.create("unParticleTail","Tail",MFnNumericData::kBoolean,false); attr.setStorable(true); unParticleUnShaded = attr.create("unParticleUnShaded","UnShaded",MFnNumericData::kBoolean,true); attr.setStorable(true); unParticleUnFogged = attr.create("unParticleUnFogged","UnFogged",MFnNumericData::kBoolean,true); attr.setStorable(true); unParticleBlockByY0 = attr.create("unParticleBlockByY0","blockByY0",MFnNumericData::kBoolean,false); attr.setStorable(true); addParticleAttributes(joint); return MS::kSuccess; }
IECore::ObjectPtr FromMayaLocatorConverter::doConversion( const MDagPath &dagPath, IECore::ConstCompoundObjectPtr operands ) const { MStatus st; bool hasLocator = dagPath.hasFn( MFn::kLocator, &st ); if (!st || !hasLocator) { throw Exception( "Could not find locator!" ); } MObject locatorObj = dagPath.node(); if ( !locatorObj.hasFn( MFn::kLocator ) ) { throw Exception( "Not a locator!" ); } MFnDagNode fnLocator( locatorObj ); CoordinateSystemPtr result = new CoordinateSystem; result->setName( IECore::convert<std::string>( fnLocator.name() ) ); /// obtain local position and scale from locator Imath::V3f position(0), scale(0); MPlug positionPlug = fnLocator.findPlug( "localPositionX", &st ); if ( !st ) throw Exception("Could not find 'localPositionX' plug!"); positionPlug.getValue(position[0]); positionPlug = fnLocator.findPlug( "localPositionY", &st ); if ( !st ) throw Exception("Could not find 'localPositionY' plug!"); positionPlug.getValue(position[1]); positionPlug = fnLocator.findPlug( "localPositionZ", &st ); if ( !st ) throw Exception("Could not find 'localPositionZ' plug!"); positionPlug.getValue(position[2]); MPlug scalePlug = fnLocator.findPlug( "localScaleX", &st ); if ( !st ) throw Exception("Could not find 'localScaleX' plug!"); scalePlug.getValue(scale[0]); scalePlug = fnLocator.findPlug( "localScaleY", &st ); if ( !st ) throw Exception("Could not find 'localScaleY' plug!"); scalePlug.getValue(scale[1]); scalePlug = fnLocator.findPlug( "localScaleZ", &st ); if ( !st ) throw Exception("Could not find 'localScaleZ' plug!"); scalePlug.getValue(scale[2]); Imath::M44f scaleM,translateM; scaleM.scale(scale); translateM.translate(position); result->setTransform( new MatrixTransform( scaleM * translateM ) ); return result; }
MStatus unCreateRibbonSystem::doIt( const MArgList& args ) { bool create = true; MSelectionList activeList; MStatus stat = MGlobal::getActiveSelectionList(activeList); if (MS::kSuccess != stat) { MessageBox(0,"please select one joint first!",0,0); return MS::kFailure; } if(activeList.length() != 1) { MessageBox(0,"please select ONLY one joint!",0,0); return MS::kFailure; } MItSelectionList iter(activeList); MDagPath dagPath; for ( ; !iter.isDone(); iter.next()) { stat = iter.getDagPath(dagPath); break; } if(!stat) { MessageBox(0,"can't getDagPath!",0,0); return MS::kFailure; } if(!dagPath.hasFn(MFn::kJoint)) { MessageBox(0,"muse select joint node!",0,0); return MS::kFailure; } MFnIkJoint joint(dagPath); if(args.length()) create = args.asBool(0); if(!create) { if(!joint.hasAttribute("unRibbonEnabled")) { MessageBox(0,"no ribbon system exists!",0,0); return MS::kFailure; } removeRibbonAttributes(joint); return MS::kSuccess; } if(joint.hasAttribute("unRibbonEnabled")) { MessageBox(0,"ribbon system already exists!",0,0); return MS::kSuccess; } if(joint.hasAttribute("unParticleEnabled")) { if(MessageBox(0,"will delete particle system and attach a ribbon system to the joint,continue?",0,MB_YESNO) == IDNO)return MS::kFailure; removeParticleAttributes(joint); } MFnNumericAttribute attr; unRibbonEnabled = attr.create("unRibbonEnabled","enabled",MFnNumericData::kBoolean,true); attr.setStorable(true); unRibbonVisible = attr.create("unRibbonVisible","visible",MFnNumericData::kBoolean,true); attr.setStorable(true); attr.setKeyable(true); unRibbonAbove = attr.create("unRibbonAbove","above",MFnNumericData::kFloat,20.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(5000.0f); attr.setKeyable(true); unRibbonBelow = attr.create("unRibbonBelow","below",MFnNumericData::kFloat,20.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(5000.0f); attr.setKeyable(true); unRibbonEdgesPerSecond = attr.create("unRibbonEdgesPerSecond","EdgePerSec",MFnNumericData::kShort,10); attr.setStorable(true); attr.setMin(0); attr.setMax(100); unRibbonEdgeLife = attr.create("unRibbonEdgeLife","EdgeLife",MFnNumericData::kFloat,2.0f); attr.setStorable(true); attr.setMin(0.001f); attr.setMax(100.0f); unRibbonGravity = attr.create("unRibbonGravity","Gravity",MFnNumericData::kFloat,0.0f); attr.setStorable(true); attr.setMin(-1000.0f); attr.setMax(1000.0f); unRibbonTextureRows = attr.create("unRibbonTextureRows","TextureRows",MFnNumericData::kShort,1); attr.setStorable(true); attr.setMin(1); attr.setMax(16); unRibbonTextureCols = attr.create("unRibbonTextureCols","TextureCols",MFnNumericData::kShort,1); attr.setStorable(true); attr.setMin(1); attr.setMax(16); unRibbonTextureSlot = attr.create("unRibbonTextureSlot","TextureSlot",MFnNumericData::kShort,0); attr.setStorable(true); attr.setMin(0); attr.setMax(255); attr.setKeyable(true); unRibbonVertexColor = attr.create("unRibbonVertexColor","VertexColor",MFnNumericData::k3Float); attr.setStorable(true); attr.setDefault(1.0f,0.0f,0.0f); attr.setUsedAsColor(true); attr.setKeyable(true); unRibbonVertexAlpha = attr.create("unRibbonVertexAlpha","VertexAlpha",MFnNumericData::kFloat,1.0f); attr.setStorable(true); attr.setMin(0.0f); attr.setMax(1.0f); attr.setKeyable(true); MFnEnumAttribute eAttr; unRibbonBlendMode = eAttr.create("unRibbonBlendMode","BlendMode",3); eAttr.setStorable(true); eAttr.addField("Opaque",0); eAttr.addField("Transparent",1); eAttr.addField("AlphaBlend",2); eAttr.addField("Additive",3); eAttr.addField("AdditiveAlpha",4); eAttr.addField("Modulate",5); { MFnEnumAttribute eAttr; unRibbonWanderMode = eAttr.create("unRibbonWanderMode","WanderMode",0); eAttr.setStorable(true); eAttr.addField("0",0); eAttr.addField("1",1); } /*unRibbonBlendModeSrc = eAttr.create("unRibbonBlendModeSrc","BlendModeSrc",3); eAttr.setStorable(true); eAttr.addField("SBF_ONE",0); eAttr.addField("SBF_ZERO",1); eAttr.addField("SBF_DEST_COLOR",2); eAttr.addField("SBF_SOURCE_COLOR",3); eAttr.addField("SBF_ONE_MINUS_DEST_COLOR",4); eAttr.addField("SBF_ONE_MINUS_SOURCE_COLOR",5); eAttr.addField("SBF_DEST_ALPHA",6); eAttr.addField("SBF_SOURCE_ALPHA",7); eAttr.addField("SBF_ONE_MINUS_DEST_ALPHA",8); eAttr.addField("SBF_ONE_MINUS_SOURCE_ALPHA",9); unRibbonBlendModeDst = eAttr.create("unRibbonBlendModeDst","BlendModeDst",0); eAttr.setStorable(true); eAttr.addField("SBF_ONE",0); eAttr.addField("SBF_ZERO",1); eAttr.addField("SBF_DEST_COLOR",2); eAttr.addField("SBF_SOURCE_COLOR",3); eAttr.addField("SBF_ONE_MINUS_DEST_COLOR",4); eAttr.addField("SBF_ONE_MINUS_SOURCE_COLOR",5); eAttr.addField("SBF_DEST_ALPHA",6); eAttr.addField("SBF_SOURCE_ALPHA",7); eAttr.addField("SBF_ONE_MINUS_DEST_ALPHA",8); eAttr.addField("SBF_ONE_MINUS_SOURCE_ALPHA",9);*/ unRibbonTextureFilename = attr.createColor("unRibbonTextureFilename","TextureFilename"); attr.setStorable(true); addRibbonAttributes(joint); return MS::kSuccess; }
// // Check if the selected nodes exist in the scene->MayaObject lists. // void mtco_MayaScene::mobjectListToMayaObjectList(std::vector<MObject>& mObjectList, std::vector<MayaObject *>& mtapObjectList) { std::vector<MObject>::iterator moIter, moIterFound; std::vector<MayaObject *>::iterator mIter; std::vector<MObject> cleanMObjectList; std::vector<MObject> foundMObjectList; for( moIter = mObjectList.begin(); moIter != mObjectList.end(); moIter++) { bool found = false; MSelectionList select; MString objName = getObjectName(*moIter); logger.debug(MString("Object to modify:") + objName); select.add(objName); MDagPath dp; select.getDagPath(0, dp); //dp.extendToShape(); MObject dagObj = dp.node(); if( (*moIter).hasFn(MFn::kCamera)) { for( mIter = this->camList.begin(); mIter != camList.end(); mIter++) { MayaObject *mo = *mIter; if( dagObj == mo->mobject) { mtapObjectList.push_back(mo); foundMObjectList.push_back(*moIter); found = true; break; } } if( found ) continue; } for( mIter = this->objectList.begin(); mIter != objectList.end(); mIter++) { MayaObject *mo = *mIter; if( dagObj == mo->mobject) { mtapObjectList.push_back(mo); foundMObjectList.push_back(*moIter); found = true; break; } } if( found ) continue; for( mIter = this->lightList.begin(); mIter != lightList.end(); mIter++) { MayaObject *mo = *mIter; if( dagObj == mo->mobject) { mtapObjectList.push_back(mo); foundMObjectList.push_back(*moIter); found = true; break; } } if( found ) continue; } for( moIter = mObjectList.begin(); moIter != mObjectList.end(); moIter++) { bool found = false; for( moIterFound = foundMObjectList.begin(); moIterFound != foundMObjectList.end(); moIterFound++) { if( *moIter == *moIterFound) { found = true; continue; } } if(!found) cleanMObjectList.push_back(*moIter); } mObjectList = cleanMObjectList; }
ConstObjectPtr LiveScene::readAttribute( const Name &name, double time ) const { if ( !m_isRoot && m_dagPath.length() == 0 ) { throw Exception( "IECoreMaya::LiveScene::readAttribute: Dag path no longer exists!" ); } tbb::mutex::scoped_lock l( s_mutex ); if ( !m_isRoot ) { if( name == SceneInterface::visibilityName ) { bool visible = true; MStatus st; MFnDagNode dagFn( m_dagPath ); MPlug visibilityPlug = dagFn.findPlug( MPxTransform::visibility, &st ); if( st ) { visible = visibilityPlug.asBool(); } if( visible ) { MDagPath childDag; // find an object that's either a SceneShape, or has a cortex converter and check its visibility: unsigned int childCount = 0; m_dagPath.numberOfShapesDirectlyBelow(childCount); for ( unsigned int c = 0; c < childCount; c++ ) { MDagPath d = m_dagPath; if( d.extendToShapeDirectlyBelow( c ) ) { MFnDagNode fnChildDag(d); if( fnChildDag.typeId() == SceneShape::id ) { childDag = d; break; } if ( fnChildDag.isIntermediateObject() ) { continue; } FromMayaShapeConverterPtr shapeConverter = FromMayaShapeConverter::create( d ); if( shapeConverter ) { childDag = d; break; } FromMayaDagNodeConverterPtr dagConverter = FromMayaDagNodeConverter::create( d ); if( dagConverter ) { childDag = d; break; } } } if( childDag.isValid() ) { MFnDagNode dagFn( childDag ); MPlug visibilityPlug = dagFn.findPlug( MPxSurfaceShape::visibility, &st ); if( st ) { visible = visibilityPlug.asBool(); } } } return new BoolData( visible ); } } else if( name == SceneInterface::visibilityName ) { return new BoolData( true ); } std::vector< CustomAttributeReader > &attributeReaders = customAttributeReaders(); for ( std::vector< CustomAttributeReader >::const_reverse_iterator it = attributeReaders.rbegin(); it != attributeReaders.rend(); ++it ) { ConstObjectPtr attr = it->m_read( m_dagPath, name ); if( !attr ) { continue; } return attr; } if( strstr( name.c_str(), "user:"******"ieAttr_" + name.string().substr(5) ).c_str(), false, &st ); if( st ) { FromMayaConverterPtr plugConverter = FromMayaPlugConverter::create( attrPlug ); if( !plugConverter ) { return IECore::NullObject::defaultNullObject(); } return plugConverter->convert(); } } return IECore::NullObject::defaultNullObject(); }
// Get shading engine // void CScriptedShapeTranslator::GetShapeInstanceShader(MDagPath& dagPath, MFnDependencyNode &shadingEngineNode) { // Get instance shadingEngine shadingEngineNode.setObject(MObject::kNullObj); // First try the usual way MPlug shadingGroupPlug = GetNodeShadingGroup(dagPath.node(), (dagPath.isInstanced() ? dagPath.instanceNumber() : 0)); if (!shadingGroupPlug.isNull()) { shadingEngineNode.setObject(shadingGroupPlug.node()); return; } char buffer[64]; // Check connection from any shadingEngine on shape MStringArray connections; MGlobal::executeCommand("listConnections -s 1 -d 0 -c 1 -type shadingEngine "+dagPath.fullPathName(), connections); MSelectionList sl; if (connections.length() == 0) { // Check for direct surface shader connection MGlobal::executeCommand("listConnections -s 1 -d 0 -c 1 "+dagPath.fullPathName(), connections); for (unsigned int cidx=0; cidx<connections.length(); cidx+=2) { MString srcNode = connections[cidx+1]; // Get node classification, if can find arnold/shader/surface -> got it MStringArray rv; MGlobal::executeCommand("getClassification `nodeType "+srcNode+"`", rv); if (rv.length() > 0 && rv[0].indexW("arnold/shader/surface") != -1) { connections.clear(); MGlobal::executeCommand("listConnections -s 0 -d 1 -c 1 -type shadingEngine "+srcNode, connections); if (connections.length() == 2) { sl.add(connections[1]); } break; } } } else if (connections.length() == 2) { // Single connection, use same shader for all instances sl.add(connections[1]); } else if (connections.length() > 2) { // Many connections, expects the destination plug in shape to be an array // Use instance number as logical index, if this fails, use first shadingEngine in list bool found = false; sprintf(buffer, "[%d]", dagPath.instanceNumber()); MString iidx = buffer; for (unsigned int cidx = 0; cidx < connections.length(); cidx += 2) { MString conn = connections[cidx]; if (conn.length() < iidx.length()) { continue; } if (conn.substring(conn.length() - iidx.length(), conn.length() - 1) != iidx) { continue; } sl.add(connections[cidx+1]); found = true; break; } if (!found) { MGlobal::displayWarning("[mtoaScriptedTranslators] Instance shader plug not found, use first found shadingEngine \"" + connections[1] + "\""); sl.add(connections[1]); } } if (sl.length() == 1) { MObject shadingEngineObj; if (sl.getDependNode(0, shadingEngineObj) == MS::kSuccess && shadingEngineObj.apiType() == MFn::kShadingEngine) { shadingEngineNode.setObject(shadingEngineObj); } else { if (shadingEngineObj != MObject::kNullObj) { MFnDependencyNode dn(shadingEngineObj); MGlobal::displayWarning("[mtoaScriptedTranslators] Not a shading engine \"" + dn.name() + "\""); } } } }
MStatus meshInfo5::doIt( const MArgList& args ) { MStatus stat = MS::kSuccess; MSelectionList selection; MGlobal::getActiveSelectionList( selection ); MDagPath dagPath; MObject component; unsigned int i, nVerts; int fIndex, vIndex, fvIndex; MVector fNormal, vNormal, fvNormal; MString txt; MItSelectionList iter( selection ); for ( ; !iter.isDone(); iter.next() ) { iter.getDagPath( dagPath, component ); MFnMesh meshFn( dagPath ); // This handles whole mesh selections and mesh-face component selections MItMeshPolygon faceIter( dagPath, component, &stat ); if( stat == MS::kSuccess ) { txt += MString( "Object: " ) + dagPath.fullPathName() + "\n"; for( ; !faceIter.isDone(); faceIter.next() ) { nVerts = faceIter.polygonVertexCount(); for( i=0; i < nVerts; i++ ) { fvIndex = i; fIndex = faceIter.index(); vIndex = faceIter.vertexIndex( i ); faceIter.getNormal( fNormal ); meshFn.getVertexNormal( vIndex, vNormal ); faceIter.getNormal( fvIndex, fvNormal ); addData( txt, fIndex, vIndex, fvIndex, fNormal, vNormal, fvNormal ); } } } else { // This handles mesh-vertex component selections MItMeshVertex vertIter( dagPath, component, &stat ); if( stat == MS::kSuccess ) { txt += MString( "Object: " ) + dagPath.fullPathName() + "\n"; MIntArray faceIds; MIntArray vertIds; for( ; !vertIter.isDone(); vertIter.next() ) { vIndex = vertIter.index(); vertIter.getNormal( vNormal ); vertIter.getConnectedFaces( faceIds ); for( i=0; i < faceIds.length(); i++ ) { fIndex = faceIds[i]; meshFn.getPolygonNormal( fIndex, fNormal ); meshFn.getFaceVertexNormal( fIndex, vIndex, fvNormal ); meshFn.getPolygonVertices( fIndex, vertIds ); for( fvIndex=0; fvIndex < int(vertIds.length()); fvIndex++ ) { if( vertIds[fvIndex] == vIndex ) break; } addData( txt, fIndex, vIndex, fvIndex, fNormal, vNormal, fvNormal ); } } } } } MGlobal::displayInfo( txt ); return MS::kSuccess; }