void ParameterisedHolderModificationCmd::restoreClassParameterStates( const IECore::CompoundData *classes, IECore::Parameter *parameter, const std::string &parentParameterPath ) { std::string parameterPath = parentParameterPath; if( parentParameterPath.size() ) { parameterPath += "."; } parameterPath += parameter->name(); if( parameter->isInstanceOf( "ClassParameter" ) ) { const CompoundData *c = classes->member<const CompoundData>( parameterPath ); if( c ) { ClassParameterHandler::setClass( parameter, c->member<const IECore::StringData>( "className" )->readable().c_str(), c->member<const IECore::IntData>( "classVersion" )->readable(), c->member<const IECore::StringData>( "searchPathEnvVar" )->readable().c_str() ); } } else if( parameter->isInstanceOf( "ClassVectorParameter" ) ) { const CompoundData *c = classes->member<const CompoundData>( parameterPath ); if( c ) { IECore::ConstStringVectorDataPtr parameterNames = c->member<const IECore::StringVectorData>( "parameterNames" ); IECore::ConstStringVectorDataPtr classNames = c->member<const IECore::StringVectorData>( "classNames" ); IECore::ConstIntVectorDataPtr classVersions = c->member<const IECore::IntVectorData>( "classVersions" ); MStringArray mParameterNames; MStringArray mClassNames; MIntArray mClassVersions; int numClasses = parameterNames->readable().size(); for( int i=0; i<numClasses; i++ ) { mParameterNames.append( parameterNames->readable()[i].c_str() ); mClassNames.append( classNames->readable()[i].c_str() ); mClassVersions.append( classVersions->readable()[i] ); } ClassVectorParameterHandler::setClasses( parameter, mParameterNames, mClassNames, mClassVersions ); } } if( parameter->isInstanceOf( IECore::CompoundParameter::staticTypeId() ) ) { CompoundParameter *compoundParameter = static_cast<CompoundParameter *>( parameter ); const CompoundParameter::ParameterVector &childParameters = compoundParameter->orderedParameters(); for( CompoundParameter::ParameterVector::const_iterator it = childParameters.begin(); it!=childParameters.end(); it++ ) { restoreClassParameterStates( classes, it->get(), parameterPath ); } } }
void ToMayaMeshConverter::addUVSet( MFnMesh &fnMesh, const MIntArray &polygonCounts, IECore::ConstMeshPrimitivePtr mesh, const std::string &sPrimVarName, const std::string &tPrimVarName, const std::string &stIdPrimVarName, MString *uvSetName ) const { IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( sPrimVarName ); bool haveS = sIt != mesh->variables.end(); IECore::PrimitiveVariableMap::const_iterator tIt = mesh->variables.find( tPrimVarName ); bool haveT = tIt != mesh->variables.end(); IECore::PrimitiveVariableMap::const_iterator stIdIt = mesh->variables.find( stIdPrimVarName ); bool haveSTId = stIdIt != mesh->variables.end(); if ( haveS && haveT ) { if ( sIt->second.interpolation != IECore::PrimitiveVariable::FaceVarying ) { IECore::msg( IECore::Msg::Warning,"ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported interpolation (expected FaceVarying).") % sPrimVarName ); return; } if ( tIt->second.interpolation != IECore::PrimitiveVariable::FaceVarying ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported interpolation (expected FaceVarying).") % tPrimVarName); return; } if ( !sIt->second.data ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has no data." ) % sPrimVarName ); } if ( !tIt->second.data ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has no data." ) % tPrimVarName ); } /// \todo Employ some M*Array converters to simplify this int numUVs = mesh->variableSize( IECore::PrimitiveVariable::FaceVarying ); IECore::ConstFloatVectorDataPtr u = IECore::runTimeCast<const IECore::FloatVectorData>(sIt->second.data); if ( !u ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % sPrimVarName % sIt->second.data->typeName() ); return; } assert( (int)u->readable().size() == numUVs ); IECore::ConstFloatVectorDataPtr v = IECore::runTimeCast<const IECore::FloatVectorData>(tIt->second.data); if ( !v ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % tPrimVarName % tIt->second.data->typeName() ); return; } assert( (int)v->readable().size() == numUVs ); const std::vector<float> &uAll = u->readable(); const std::vector<float> &vAll = v->readable(); if ( uvSetName ) { bool setExists = false; MStringArray existingSets; fnMesh.getUVSetNames( existingSets ); for ( unsigned i=0; i < existingSets.length(); ++i ) { if ( *uvSetName == existingSets[i] ) { fnMesh.clearUVs( uvSetName ); setExists = true; break; } } if ( !setExists ) { MDagPath dag; MStatus s = fnMesh.getPath( dag ); if ( s ) { fnMesh.createUVSetWithName( *uvSetName ); } else { fnMesh.createUVSetDataMeshWithName( *uvSetName ); } } } MIntArray uvIds; uvIds.setLength( numUVs ); MFloatArray uArray; MFloatArray vArray; if( haveSTId ) { // Get compressed uv values by matching them with their uvId. IECore::ConstIntVectorDataPtr uvId = IECore::runTimeCast<const IECore::IntVectorData>(stIdIt->second.data); if ( !uvId ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"%s\" has unsupported type \"%s\"." ) % stIdPrimVarName % stIdIt->second.data->typeName() ); return; } const std::vector<int> &uvIdData = uvId->readable(); assert( (int)uvIdData.size() == numUVs ); int highestId = 0; for ( int i = 0; i < numUVs; i++) { uvIds[i] = uvIdData[i]; if( uvIdData[i] > highestId ) { highestId = uvIdData[i]; } } // u and v arrays need only be as long as the number of unique uvIds uArray.setLength( highestId + 1 ); vArray.setLength( highestId + 1 ); for ( int i = 0; i < numUVs; i++ ) { uArray[ uvIds[i] ] = uAll[i]; // FromMayaMeshConverter does the opposite of this vArray[ uvIds[i] ] = 1 - vAll[i]; } } else { // If for some reason we cannot find the uv indices, set the UVs using the old way // the performances in maya won't be good (for weigth painting in particular) uArray.setLength( numUVs ); vArray.setLength( numUVs ); for ( int i = 0; i < numUVs; i++) { uArray[i] = u->readable()[i]; // FromMayaMeshConverter does the opposite of this vArray[i] = 1 - v->readable()[i]; } for ( int i = 0; i < numUVs; i++) { uvIds[i] = i; } } MStatus s = fnMesh.setUVs( uArray, vArray, uvSetName ); if ( !s ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to set UVs." ); return; } s = fnMesh.assignUVs( polygonCounts, uvIds, uvSetName ); if ( !s ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to assign UVs." ); return; } } else if ( haveS ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "Primitive variable \"%s\" found, but not \"%s\"." ) % sPrimVarName % tPrimVarName ); } else if ( haveT ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "Primitive variable \"%s\" found, but not \"%s\"." ) % tPrimVarName % sPrimVarName ); } else { assert( !uvSetName ); } }
bool ToMayaMeshConverter::doConversion( IECore::ConstObjectPtr from, MObject &to, IECore::ConstCompoundObjectPtr operands ) const { MStatus s; IECore::ConstMeshPrimitivePtr mesh = IECore::runTimeCast<const IECore::MeshPrimitive>( from ); assert( mesh ); if ( !mesh->arePrimitiveVariablesValid() ) { return false; } MFloatPointArray vertexArray; MIntArray polygonCounts; MIntArray polygonConnects; MFnMesh fnMesh; int numVertices = 0; IECore::PrimitiveVariableMap::const_iterator it = mesh->variables.find("P"); if ( it != mesh->variables.end() ) { /// \todo Employ some M*Array converters to simplify this IECore::ConstV3fVectorDataPtr p = IECore::runTimeCast<const IECore::V3fVectorData>(it->second.data); if (p) { numVertices = p->readable().size(); vertexArray.setLength( numVertices ); for (int i = 0; i < numVertices; i++) { vertexArray[i] = IECore::convert<MFloatPoint, Imath::V3f>( p->readable()[i] ); } } else { IECore::ConstV3dVectorDataPtr p = IECore::runTimeCast<const IECore::V3dVectorData>(it->second.data); if (p) { numVertices = p->readable().size(); vertexArray.setLength( numVertices ); for (int i = 0; i < numVertices; i++) { vertexArray[i] = IECore::convert<MFloatPoint, Imath::V3d>( p->readable()[i] ); } } else { // "P" is not convertible to an array of "points" return false; } } } IECore::ConstIntVectorDataPtr verticesPerFace = mesh->verticesPerFace(); assert( verticesPerFace ); int numPolygons = verticesPerFace->readable().size(); polygonCounts.setLength( numPolygons ); for (int i = 0; i < numPolygons; i++) { polygonCounts[i] = verticesPerFace->readable()[i]; } IECore::ConstIntVectorDataPtr vertexIds = mesh->vertexIds(); assert( vertexIds ); int numPolygonConnects = vertexIds->readable().size(); polygonConnects.setLength( numPolygonConnects ); for (int i = 0; i < numPolygonConnects; i++) { polygonConnects[i] = vertexIds->readable()[i]; } MObject mObj = fnMesh.create( numVertices, numPolygons, vertexArray, polygonCounts, polygonConnects, to, &s ); if (!s) { return false; } it = mesh->variables.find("N"); if ( it != mesh->variables.end() ) { if (it->second.interpolation == IECore::PrimitiveVariable::FaceVarying ) { /// \todo Employ some M*Array converters to simplify this MVectorArray vertexNormalsArray; IECore::ConstV3fVectorDataPtr n = IECore::runTimeCast<const IECore::V3fVectorData>(it->second.data); if (n) { int numVertexNormals = n->readable().size(); vertexNormalsArray.setLength( numVertexNormals ); for (int i = 0; i < numVertexNormals; i++) { vertexNormalsArray[i] = IECore::convert<MVector, Imath::V3f>( n->readable()[i] ); } } else { IECore::ConstV3dVectorDataPtr n = IECore::runTimeCast<const IECore::V3dVectorData>(it->second.data); if (n) { int numVertexNormals = n->readable().size(); vertexNormalsArray.setLength( numVertexNormals ); for (int i = 0; i < numVertexNormals; i++) { vertexNormalsArray[i] = IECore::convert<MVector, Imath::V3d>( n->readable()[i] ); } } else { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", boost::format( "PrimitiveVariable \"N\" has unsupported type \"%s\"." ) % it->second.data->typeName() ); } } if ( vertexNormalsArray.length() ) { MStatus status; MItMeshPolygon itPolygon( mObj, &status ); if( status != MS::kSuccess ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Failed to create mesh iterator" ); } unsigned v = 0; MIntArray vertexIds; MIntArray faceIds; for ( ; !itPolygon.isDone(); itPolygon.next() ) { for ( v=0; v < itPolygon.polygonVertexCount(); ++v ) { faceIds.append( itPolygon.index() ); vertexIds.append( itPolygon.vertexIndex( v ) ); } } if( !fnMesh.setFaceVertexNormals( vertexNormalsArray, faceIds, vertexIds ) ) { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "Setting normals failed" ); } } } else { IECore::msg( IECore::Msg::Warning, "ToMayaMeshConverter::doConversion", "PrimitiveVariable \"N\" has unsupported interpolation (expected FaceVarying)." ); } } bool haveDefaultUVs = false; IECore::PrimitiveVariableMap::const_iterator sIt = mesh->variables.find( "s" ); IECore::RefCountedPtr sDataRef = ( sIt == mesh->variables.end() ) ? 0 : static_cast<IECore::RefCountedPtr>( sIt->second.data ); /// Add named UV sets std::set< std::string > uvSets; for ( it = mesh->variables.begin(); it != mesh->variables.end(); ++it ) { const std::string &sName = it->first; size_t suffixOffset = sName.rfind( "_s" ); if ( ( suffixOffset != std::string::npos) && ( suffixOffset == sName.length() - 2 ) ) { std::string uvSetNameStr = sName.substr( 0, suffixOffset ); if ( uvSetNameStr.size() ) { MString uvSetName = uvSetNameStr.c_str(); std::string tName = uvSetNameStr + "_t"; std::string stIdName = uvSetNameStr + "Indices"; addUVSet( fnMesh, polygonCounts, mesh, sName, tName, stIdName, &uvSetName ); uvSets.insert( uvSetNameStr ); if ( sDataRef == static_cast<IECore::RefCountedPtr>( it->second.data ) ) { haveDefaultUVs = true; } } } } /// Add default UV set if it isn't just a reference to a named set if ( !haveDefaultUVs ) { addUVSet( fnMesh, polygonCounts, mesh, "s", "t", "stIndices" ); } // We do the search again, but looking for primvars ending "_t", so we can catch cases where either "UVSETNAME_s" or "UVSETNAME_t" is present, but not both, taking care // not to attempt adding any duplicate sets for ( it = mesh->variables.begin(); it != mesh->variables.end(); ++it ) { const std::string &tName = it->first; size_t suffixOffset = tName.rfind( "_t" ); if ( ( suffixOffset != std::string::npos) && ( suffixOffset == tName.length() - 2 ) ) { std::string uvSetNameStr = tName.substr( 0, suffixOffset ); if ( uvSetNameStr.size() && uvSets.find( uvSetNameStr ) == uvSets.end() ) { MString uvSetName = uvSetNameStr.c_str(); std::string sName = uvSetNameStr + "_s"; std::string stIdName = uvSetNameStr + "Indices"; addUVSet( fnMesh, polygonCounts, mesh, sName, tName, stIdName, &uvSetName ); uvSets.insert( uvSetNameStr ); } } } /// If we're making a mesh node (rather than a mesh data) then make sure it belongs /// to the default shading group and add the ieMeshInterpolation attribute. MObject oMesh = fnMesh.object(); if( oMesh.apiType()==MFn::kMesh ) { assignDefaultShadingGroup( oMesh ); setMeshInterpolationAttribute( oMesh, mesh->interpolation() ); } /// \todo Other primvars, e.g. vertex color ("Cs") return true; }