// -------------------------------------------------------- void GeometryPolygonExporter::initializePolygonSource( const MFnMesh &fnMesh, MItMeshPolygon &meshPolygonsIter, PolygonSource &polygon, MIntArray &vertexIndices, uint &numPolygons, uint &numVertices ) { // Collect data in order to handle triangle-only export option // Retrieve the vertex indices and establish the number of polygons (in case of // triangulation more than one is possible) and the number of vertexes in the polygon. retrieveVertexIndices ( vertexIndices, meshPolygonsIter, numPolygons, numVertices ); // Iterate through the polygons (normally just one polygon, // just in case of triangulation it could be more than one) for ( uint polygonPosition=0; polygonPosition<numPolygons; ++polygonPosition ) { // Put the current face in the list of faces polygon.getFaceVertexCounts().push_back ( numVertices ); // Get the index of the current polygon int polyIndex = meshPolygonsIter.index(); // Iterate through the vertexes of the current polygon for ( uint vertexPosition=0; vertexPosition<numVertices; vertexPosition++ ) { // Handle front face vs back face by walking the vertexes backward on the back-face int iteratorVertexIndex = vertexIndices[polygonPosition * numVertices + vertexPosition]; int vertexIndex = meshPolygonsIter.vertexIndex ( iteratorVertexIndex ); // Look for holes in this polygon // ASSUMPTION: Holes are automatically removed by triangulation. // ASSUMPTION: The iterator gives the hole vertices at the end of the enumeration. // ASSUMPTION: Hole vertices are never used as surface vertices or repeated between holes or inside a hole. if ( meshPolygonsIter.isHoled() && !triangulated ) { handleHoledPolygon(polygon, polyIndex, vertexIndex, numVertices, iteratorVertexIndex); } } } }
/** Create a RIB compatible representation of a Maya polygon mesh. */ liqRibMeshData::liqRibMeshData( MObject mesh ) : numFaces( 0 ), numPoints ( 0 ), numNormals ( 0 ), nverts(), verts(), vertexParam(NULL), normalParam(NULL) { CM_TRACE_FUNC("liqRibMeshData::liqRibMeshData("<<MFnDagNode(mesh).fullPathName().asChar()<<")"); unsigned int i; unsigned int j; areaLight = false; LIQDEBUGPRINTF( "-> creating mesh\n" ); MFnMesh fnMesh( mesh ); objDagPath = fnMesh.dagPath(); MStatus astatus; name = fnMesh.name(); areaLight =( liquidGetPlugValue( fnMesh, "areaIntensity", areaIntensity, astatus ) == MS::kSuccess )? true : false ; if ( areaLight ) { MDagPath meshDagPath; meshDagPath = fnMesh.dagPath(); MTransformationMatrix worldMatrix = meshDagPath.inclusiveMatrix(); MMatrix worldMatrixM = worldMatrix.asMatrix(); worldMatrixM.get( transformationMatrix ); } numPoints = fnMesh.numVertices(); numNormals = fnMesh.numNormals(); // UV sets ------------------- // //const unsigned numSTs( fnMesh.numUVs() ); const unsigned numUVSets( fnMesh.numUVSets() ); MString currentUVSetName; MStringArray extraUVSetNames; fnMesh.getCurrentUVSetName( currentUVSetName ); { MStringArray UVSetNames; fnMesh.getUVSetNames( UVSetNames ); for ( unsigned i( 0 ); i<numUVSets; i++ ) if ( UVSetNames[i] != currentUVSetName ) extraUVSetNames.append( UVSetNames[i] ); } numFaces = fnMesh.numPolygons(); const unsigned numFaceVertices( fnMesh.numFaceVertices() ); if ( numPoints < 1 ) { // MGlobal::displayInfo( MString( "fnMesh: " ) + fnMesh.name() ); // cerr << "Liquid : Could not export degenerate mesh '"<< fnMesh.fullPathName( &astatus ).asChar() << "'" << endl << flush; return; } unsigned face = 0; unsigned faceVertex = 0; unsigned count; unsigned vertex; unsigned normal; float S; float T; MPoint point; liqTokenPointer pointsPointerPair; liqTokenPointer normalsPointerPair; liqTokenPointer pFaceVertexSPointer; liqTokenPointer pFaceVertexTPointer; // Allocate memory and tokens numFaces = numFaces; nverts = shared_array< liqInt >( new liqInt[ numFaces ] ); verts = shared_array< liqInt >( new liqInt[ numFaceVertices ] ); pointsPointerPair.set( "P", rPoint, numPoints ); pointsPointerPair.setDetailType( rVertex ); if ( numNormals == numPoints ) { normalsPointerPair.set( "N", rNormal, numPoints ); normalsPointerPair.setDetailType( rVertex ); } else { normalsPointerPair.set( "N", rNormal, numFaceVertices ); normalsPointerPair.setDetailType( rFaceVarying ); } // uv std::vector<liqTokenPointer> UVSetsArray; UVSetsArray.reserve( 1 + extraUVSetNames.length() ); liqTokenPointer currentUVSetUPtr; liqTokenPointer currentUVSetVPtr; liqTokenPointer currentUVSetNamePtr; liqTokenPointer extraUVSetsUPtr; liqTokenPointer extraUVSetsVPtr; liqTokenPointer extraUVSetsNamePtr; if(liqglo.liqglo_outputMeshAsRMSArrays) { currentUVSetUPtr.set( "s", rFloat, numFaceVertices ); currentUVSetUPtr.setDetailType( rFaceVarying ); currentUVSetVPtr.set( "t", rFloat, numFaceVertices ); currentUVSetVPtr.setDetailType( rFaceVarying ); currentUVSetNamePtr.set( "currentUVSet", rString, 1 ); currentUVSetNamePtr.setDetailType( rConstant ); if( numUVSets > 1 ) { extraUVSetsUPtr.set( "u_uvSet", rFloat, numFaceVertices, numUVSets-1 ); extraUVSetsUPtr.setDetailType( rFaceVarying ); extraUVSetsVPtr.set( "v_uvSet", rFloat, numFaceVertices, numUVSets-1 ); extraUVSetsVPtr.setDetailType( rFaceVarying ); extraUVSetsNamePtr.set( "extraUVSets", rString, numUVSets-1 ); extraUVSetsNamePtr.setDetailType( rConstant ); } } else { if ( numUVSets > 0 ) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( "st", rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( rFaceVarying ); UVSetsArray.push_back( pFaceVertexPointerPair ); for ( unsigned j( 0 ); j<extraUVSetNames.length(); j++) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( extraUVSetNames[j].asChar(), rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( rFaceVarying ); UVSetsArray.push_back( pFaceVertexPointerPair ); } if( liqglo.liqglo_outputMeshUVs ) { // Match MTOR, which also outputs face-varying STs as well for some reason - Paul // not anymore - Philippe pFaceVertexSPointer.set( "u", rFloat, numFaceVertices ); pFaceVertexSPointer.setDetailType( rFaceVarying ); pFaceVertexTPointer.set( "v", rFloat, numFaceVertices ); pFaceVertexTPointer.setDetailType( rFaceVarying ); } } } vertexParam = pointsPointerPair.getTokenFloatArray(); normalParam = normalsPointerPair.getTokenFloatArray(); // Read the mesh from Maya MFloatVectorArray normals; fnMesh.getNormals( normals ); for ( MItMeshPolygon polyIt ( mesh ); polyIt.isDone() == false; polyIt.next() ) { count = polyIt.polygonVertexCount(); nverts[face] = count; for( i=0; i<count; i++ ) // boucle sur les vertex de la face { vertex = polyIt.vertexIndex( i ); verts[faceVertex] = vertex; point = polyIt.point( i, MSpace::kObject ); pointsPointerPair.setTokenFloat( vertex, point.x, point.y, point.z ); normal = polyIt.normalIndex( i ); if( numNormals == numPoints ) normalsPointerPair.setTokenFloat( vertex, normals[normal].x, normals[normal].y, normals[normal].z ); else normalsPointerPair.setTokenFloat( faceVertex, normals[normal].x, normals[normal].y, normals[normal].z ); if( liqglo.liqglo_outputMeshAsRMSArrays ) { for( j=0; j<numUVSets; j++ ) { if(j==0) { MString uvSetName = currentUVSetName; // set uvSet name currentUVSetNamePtr.setTokenString( 0, currentUVSetName.asChar() ); // set uv values fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); currentUVSetUPtr.setTokenFloat( faceVertex, S ); currentUVSetVPtr.setTokenFloat( faceVertex, 1-T ); } else { MString uvSetName = extraUVSetNames[j-1]; // set uvSet name extraUVSetsNamePtr.setTokenString( j-1, extraUVSetNames[j-1].asChar() ); // set uv values fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); extraUVSetsUPtr.setTokenFloat( (numFaceVertices*(j-1)) + faceVertex, S ); extraUVSetsVPtr.setTokenFloat( (numFaceVertices*(j-1)) + faceVertex, 1-T ); } } } else { if ( numUVSets ) { for( j=0; j<numUVSets; j++ ) { MString uvSetName; if(j==0) { uvSetName = currentUVSetName; } else { uvSetName = extraUVSetNames[j-1]; } fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); UVSetsArray[j].setTokenFloat( faceVertex, 0, S ); UVSetsArray[j].setTokenFloat( faceVertex, 1, 1-T ); //printf("V%d %s : %f %f => %f %f \n", i, uvSetName.asChar(), S, T, S, 1-T); if( liqglo.liqglo_outputMeshUVs && j==0) { // Match MTOR, which always outputs face-varying STs as well for some reason - Paul pFaceVertexSPointer.setTokenFloat( faceVertex, S ); pFaceVertexTPointer.setTokenFloat( faceVertex, 1-T ); } } } } // printf( "[%d] faceVertex = %d vertex = %d\n", i, faceVertex, vertex ); ++faceVertex; } ++face; } // Add tokens to array and clean up after tokenPointerArray.push_back( pointsPointerPair ); tokenPointerArray.push_back( normalsPointerPair ); if(liqglo.liqglo_outputMeshAsRMSArrays) { tokenPointerArray.push_back( currentUVSetNamePtr ); tokenPointerArray.push_back( currentUVSetUPtr ); tokenPointerArray.push_back( currentUVSetVPtr ); if( numUVSets > 1 ) { tokenPointerArray.push_back( extraUVSetsNamePtr ); tokenPointerArray.push_back( extraUVSetsUPtr ); tokenPointerArray.push_back( extraUVSetsVPtr ); } } else { if( UVSetsArray.size() ) tokenPointerArray.insert( tokenPointerArray.end(), UVSetsArray.begin(), UVSetsArray.end() ); if( liqglo.liqglo_outputMeshUVs ) { tokenPointerArray.push_back( pFaceVertexSPointer ); tokenPointerArray.push_back( pFaceVertexTPointer ); } } addAdditionalSurfaceParameters( mesh ); }
/* * get maya poly mesh data */ bool liqRibMeshData::getMayaData( MObject mesh, bool useNormals ) { bool ret = true; // LIQDEBUGPRINTF( "-> mesh getMayaData (useNormals = %s )\n", ( ( useNormals )? "Yes" : "No" ) ); MFnMesh fnMesh( mesh ); objDagPath = fnMesh.dagPath(); MStatus astatus; name = fnMesh.name(); longName = fnMesh.fullPathName(); numPoints = fnMesh.numVertices(); numFaces = fnMesh.numPolygons(); if ( useNormals ) numNormals = fnMesh.numNormals(); if ( numPoints < 1 ) { liquidMessage( "Could not export degenerate mesh " + longName, messageInfo ); return false; } // UV sets ------------------- // //const unsigned numSTs( fnMesh.numUVs() ); const unsigned numUVSets( fnMesh.numUVSets() ); MString currentUVSetName; fnMesh.getCurrentUVSetName( currentUVSetName ); MStringArray extraUVSetNames; MStringArray UVSetNames; fnMesh.getUVSetNames( UVSetNames ); for ( unsigned i( 0 ); i < numUVSets ; i++ ) if ( UVSetNames[i] != currentUVSetName ) extraUVSetNames.append( UVSetNames[i] ); const unsigned numFaceVertices( fnMesh.numFaceVertices() ); unsigned face ( 0 ); unsigned faceVertex ( 0 ); unsigned count; unsigned vertex; unsigned normal; float S; float T; MPoint point; liqTokenPointer pointsPointerPair; liqTokenPointer normalsPointerPair; liqTokenPointer pFaceVertexSPointer; liqTokenPointer pFaceVertexTPointer; // Allocate memory and tokens nverts = shared_array< RtInt >( new RtInt[ numFaces ] ); verts = shared_array< RtInt >( new RtInt[ numFaceVertices ] ); pointsPointerPair.set( "P", rPoint, numPoints ); pointsPointerPair.setDetailType( rVertex ); if ( useNormals ) { if ( numNormals == numPoints ) { normalsPointerPair.set( "N", rNormal, numPoints ); normalsPointerPair.setDetailType( rVertex ); } else { normalsPointerPair.set( "N", rNormal, numFaceVertices ); normalsPointerPair.setDetailType( rFaceVarying ); } } // uv std::vector<liqTokenPointer> UVSetsArray; UVSetsArray.reserve( 1 + extraUVSetNames.length() ); liqTokenPointer currentUVSetUPtr; liqTokenPointer currentUVSetVPtr; liqTokenPointer currentUVSetNamePtr; liqTokenPointer extraUVSetsUPtr; liqTokenPointer extraUVSetsVPtr; liqTokenPointer extraUVSetsNamePtr; if ( liqglo_outputMeshAsRMSArrays ) { currentUVSetUPtr.set( "s", rFloat, numFaceVertices ); currentUVSetUPtr.setDetailType( rFaceVarying ); currentUVSetVPtr.set( "t", rFloat, numFaceVertices ); currentUVSetVPtr.setDetailType( rFaceVarying ); currentUVSetNamePtr.set( "currentUVSet", rString, 1 ); currentUVSetNamePtr.setDetailType( rConstant ); if ( numUVSets > 1 ) { extraUVSetsUPtr.set( "u_uvSet", rFloat, numFaceVertices, numUVSets-1 ); extraUVSetsUPtr.setDetailType( rFaceVarying ); extraUVSetsVPtr.set( "v_uvSet", rFloat, numFaceVertices, numUVSets-1 ); extraUVSetsVPtr.setDetailType( rFaceVarying ); extraUVSetsNamePtr.set( "extraUVSets", rString, numUVSets-1 ); extraUVSetsNamePtr.setDetailType( rConstant ); } } else { if ( numUVSets > 0 ) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( "st", rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( rFaceVarying ); UVSetsArray.push_back( pFaceVertexPointerPair ); for ( unsigned j( 0 ); j < extraUVSetNames.length() ; j++ ) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( extraUVSetNames[j].asChar(), rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( rFaceVarying ); UVSetsArray.push_back( pFaceVertexPointerPair ); } if ( liqglo_outputMeshUVs ) { // Match MTOR, which also outputs face-varying STs as well for some reason - Paul // not anymore - Philippe pFaceVertexSPointer.set( "u", rFloat, numFaceVertices ); pFaceVertexSPointer.setDetailType( rFaceVarying ); pFaceVertexTPointer.set( "v", rFloat, numFaceVertices ); pFaceVertexTPointer.setDetailType( rFaceVarying ); } } } vertexParam = pointsPointerPair.getTokenFloatArray(); MFloatVectorArray normals; // Read the mesh normals from Maya if ( useNormals ) { normalParam = normalsPointerPair.getTokenFloatArray(); fnMesh.getNormals( normals ); } for ( MItMeshPolygon polyIt ( mesh ); polyIt.isDone() == false ; polyIt.next() ) { count = polyIt.polygonVertexCount(); nverts[face] = count; unsigned j, i = count; // printf("poly count = %d\n", count ); while ( i ) { --i; vertex = polyIt.vertexIndex( i ); verts[faceVertex] = vertex; point = polyIt.point( i, MSpace::kObject ); pointsPointerPair.setTokenFloat( vertex, point.x, point.y, point.z ); if ( useNormals ) { normal = polyIt.normalIndex( i ); if ( numNormals == numPoints ) normalsPointerPair.setTokenFloat( vertex, normals[normal].x, normals[normal].y, normals[normal].z ); else normalsPointerPair.setTokenFloat( faceVertex, normals[normal].x, normals[normal].y, normals[normal].z ); } if ( liqglo_outputMeshAsRMSArrays ) { for ( j = 0 ; j < numUVSets ; j++ ) { if ( j == 0) { MString uvSetName = currentUVSetName; // set uvSet name currentUVSetNamePtr.setTokenString( 0, currentUVSetName.asChar() ); // set uv values fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); currentUVSetUPtr.setTokenFloat( faceVertex, S ); currentUVSetVPtr.setTokenFloat( faceVertex, 1-T ); } else { MString uvSetName = extraUVSetNames[j-1]; // set uvSet name extraUVSetsNamePtr.setTokenString( j-1, extraUVSetNames[j-1].asChar() ); // set uv values fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); extraUVSetsUPtr.setTokenFloat( (numFaceVertices*(j-1)) + faceVertex, S ); extraUVSetsVPtr.setTokenFloat( (numFaceVertices*(j-1)) + faceVertex, 1-T ); } } } else { if ( numUVSets ) { for( j = 0; j < numUVSets; j++ ) { MString uvSetName = ( j == 0 )? currentUVSetName: extraUVSetNames[ j - 1 ] ; fnMesh.getPolygonUV( face, i, S, T, &uvSetName ); UVSetsArray[j].setTokenFloat( faceVertex, 0, S ); UVSetsArray[j].setTokenFloat( faceVertex, 1, 1 - T ); //printf("V%d %s : %f %f => %f %f \n", i, uvSetName.asChar(), S, T, S, 1-T); if ( liqglo_outputMeshUVs && j==0) { // Match MTOR, which always outputs face-varying STs as well for some reason - Paul pFaceVertexSPointer.setTokenFloat( faceVertex, S ); pFaceVertexTPointer.setTokenFloat( faceVertex, 1 - T ); } } } } ++faceVertex; } ++face; } // Add tokens to array and clean up after tokenPointerArray.push_back( pointsPointerPair ); if ( useNormals ) tokenPointerArray.push_back( normalsPointerPair ); if ( liqglo_outputMeshAsRMSArrays ) { tokenPointerArray.push_back( currentUVSetNamePtr ); tokenPointerArray.push_back( currentUVSetUPtr ); tokenPointerArray.push_back( currentUVSetVPtr ); if ( numUVSets > 1 ) { tokenPointerArray.push_back( extraUVSetsNamePtr ); tokenPointerArray.push_back( extraUVSetsUPtr ); tokenPointerArray.push_back( extraUVSetsVPtr ); } } else { if ( UVSetsArray.size() ) tokenPointerArray.insert( tokenPointerArray.end(), UVSetsArray.begin(), UVSetsArray.end() ); if ( liqglo_outputMeshUVs ) { tokenPointerArray.push_back( pFaceVertexSPointer ); tokenPointerArray.push_back( pFaceVertexTPointer ); } } return ret; }
MStatus liqAttachPrefAttribute::redoIt() { MFnTypedAttribute tAttr; MStatus status; for ( unsigned i( 0 ); i < objectNames.length(); i++ ) { MSelectionList nodeList; nodeList.add( objectNames[i] ); MObject depNodeObj; nodeList.getDependNode( 0, depNodeObj ); MDagPath dagNode; nodeList.getDagPath( 0, dagNode ); MFnDependencyNode depNode( depNodeObj ); MObject prefAttr; MString attrName, varName; // make sure the renderer description is up to date liqglo.liquidRenderer.setRenderer(); // build the name of the attribute varName = ( ( exportN && depNodeObj.hasFn( MFn::kMesh ) )? "N":"P" ); attrName = "rman"; attrName += varName; attrName += ( ( liqglo.liquidRenderer.requires__PREF )? "__":"" ); attrName += varName + "ref"; // create the attribute prefAttr = tAttr.create( attrName, attrName, MFnData::kPointArray ); if ( depNodeObj.hasFn( MFn::kNurbsSurface ) ) { MFnNurbsSurface nodeFn( depNodeObj ); MPointArray nodePArray; MItSurfaceCV cvs( dagNode, MObject::kNullObj, liqglo.liquidRenderer.requires_SWAPPED_UVS == false, &status ); while( !cvs.isDone() ) { while( !cvs.isRowDone() ) { MPoint pt = (worldSpace)? cvs.position( MSpace::kWorld ) : cvs.position( MSpace::kObject ); nodePArray.append( pt ); cvs.next(); } cvs.nextRow(); } nodeFn.addAttribute( prefAttr ); MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else if ( depNodeObj.hasFn( MFn::kNurbsCurve ) ) { // Carsten: added support for PREF on nurbs curves // MFnNurbsCurve nodeFn( depNodeObj ); MPointArray nodePArray; nodeFn.getCVs( nodePArray ); nodeFn.addAttribute( prefAttr ); MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else if ( depNodeObj.hasFn( MFn::kMesh ) ) { MFnMesh nodeFn( depNodeObj ); // Moritz: modified this line to dim nodePArray -- otherwise // nodePArray.set() in the wile loop below throws an exception // which was why __Pref didn't work MPointArray nodePArray( MFnMesh( depNodeObj ).numVertices() ); unsigned count; nodeFn.addAttribute( prefAttr ); if ( exportN ) { // export Nref unsigned vertex; unsigned normal; unsigned face = 0; unsigned faceVertex = 0; unsigned int numNormals = nodeFn.numNormals(); unsigned int numPoints = nodeFn.numVertices(); MFloatVectorArray normals; MVectorArray normalAttArray; nodeFn.getNormals( normals ); if ( numNormals > numPoints ) { // if we get more than 1 normal per vertex, // force the arraysize to the full facevarying size unsigned faceVaryingCount( 0 ); for ( unsigned pOn( 0 ); pOn < nodeFn.numPolygons(); pOn++ ) faceVaryingCount += nodeFn.polygonVertexCount( pOn ); normalAttArray.setLength( faceVaryingCount ); } else normalAttArray.setLength(normals.length()); for ( MItMeshPolygon polyIt ( depNodeObj ); polyIt.isDone() == false; polyIt.next() ) { count = polyIt.polygonVertexCount(); while ( count > 0 ) { --count; normal = polyIt.normalIndex( count ); vertex = polyIt.vertexIndex( count ); if( numNormals == numPoints ) normalAttArray.set(normals[normal], vertex); else normalAttArray.set(normals[normal], faceVertex); ++faceVertex; } ++face; } MFnVectorArrayData pArrayData; MObject prefDefault = pArrayData.create( normalAttArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } else { // TODO: do we need to account for the altMeshExport algo that's // used in liquidRibMeshData? // Moritz: no, it's basically the same as the algo below for ( MItMeshPolygon polyIt( dagNode, MObject::kNullObj ); !polyIt.isDone(); polyIt.next()) { count = polyIt.polygonVertexCount(); while ( count > 0 ) { --count; unsigned vertexIndex = polyIt.vertexIndex( count ); MPoint nodePoint = (worldSpace)? polyIt.point( count, MSpace::kWorld ) : polyIt.point( count, MSpace::kObject ); // Moritz: this returns MS::kFailure but seems to work?! nodePArray.set( nodePoint, vertexIndex ); } } MFnPointArrayData pArrayData; MObject prefDefault = pArrayData.create( nodePArray ); MPlug nodePlug( depNodeObj, prefAttr ); nodePlug.setValue( prefDefault ); } } else cerr << "Neither a Nurbs nor a Mesh !!" << endl; } return MS::kSuccess; }
// -------------------------------------------------------- void GeometryPolygonExporter::retrieveVertexIndices ( MIntArray &vertexIndices, MItMeshPolygon &meshPolygonsIter, uint &numPolygons, uint &numVertices ) { // Get the number of vertices in the current mesh's polygon int polygonVertexCount = meshPolygonsIter.polygonVertexCount(); if ( triangulated && polygonVertexCount > 3 ) { int numTriangles; meshPolygonsIter.numTriangles ( numTriangles ); if ( numTriangles > 0 ) { numVertices = 3; MPointArray vertexPositions; MIntArray meshVertexIndices; meshPolygonsIter.getTriangles ( vertexPositions, meshVertexIndices ); vertexIndices.setLength ( meshVertexIndices.length() ); numPolygons = meshVertexIndices.length() / numVertices; // Map the vertex indices to iterator vertex indices so that we can // get information from the iterator about normals and such. uint meshVertexIndexCount = meshVertexIndices.length(); for ( uint mvi = 0; mvi < meshVertexIndexCount; ++mvi ) { int meshVertexIndex = meshVertexIndices[mvi]; int polygonVertexCount = meshPolygonsIter.polygonVertexCount(); int iteratorVertexIndex = 0; for ( int pv = 0; pv < polygonVertexCount; ++pv ) { if ( ( int ) meshPolygonsIter.vertexIndex ( pv ) == meshVertexIndex ) { iteratorVertexIndex = pv; } } vertexIndices[mvi] = iteratorVertexIndex; } } else numPolygons = 0; } else if ( polygonVertexCount >= 3 ) { numPolygons = 1; vertexIndices.setLength ( polygonVertexCount ); for ( int pv = 0; pv < polygonVertexCount; ++pv ) { vertexIndices[pv] = pv; } #ifdef VALIDATE_DATA // Skip over any duplicate vertices in this face. // Very rarely, a cunning user manages to corrupt // a face entry on the mesh and somehow configure // a face to include the same vertex multiple times. // This will cause the read-back of this data to // reject the face, and can crash other COLLADA // consumers, so better to lose the data here for ( uint n = 0; n < vertexIndices.length() - 1; ++n ) { for ( uint m = n + 1; m < vertexIndices.length(); ) { if ( vertexIndices[n] == vertexIndices[m] ) { vertexIndices.remove ( m ); } else ++m; } } // Get the number of vertices of the current polygon. numVertices = vertexIndices->length(); #else // Get the number of vertices of the current polygon. numVertices = polygonVertexCount; #endif } }
// -------------------------------------------------------- void GeometryPolygonExporter::writeElementVertexIndices( COLLADASW::PrimitivesBase* primitivesBasePoly, PolygonSource* polygon, MFnMesh &fnMesh, MItMeshPolygon &meshPolygonsIter, const uint exportType, const MIntArray &vertexIndices, const uint numPolygons, const uint numVertices ) { // Add the open tags for the polygons if ( exportType == PolygonSource::POLYGONS ) { if ( polygon->isHoled() ) { ( ( COLLADASW::Polygons* ) primitivesBasePoly )->openPolylistHoleElement(); } } // The face index uint currentFaceIndex = 0; // Check if the current face is a normal polygon or a hole and open the corresponding tag. if ( exportType == PolygonSource::POLYGONS ) { openPolygonOrHoleElement ( primitivesBasePoly, polygon, currentFaceIndex ); } // Get the index of the current polygon int polyIndex = meshPolygonsIter.index(); // Buffer the face normal indices MIntArray normalIndices; if ( mHasFaceVertexNormals ) { fnMesh.getFaceNormalIds ( polyIndex, normalIndices ); } // Iterate through the polygons (normally just one polygon, // just in case of triangulation it could be more than one) for ( uint polygonPosition=0; polygonPosition<numPolygons; ++polygonPosition ) { // Initialize the data for polygons with holes size_t numFaceVertices = polygon->getFaceVertexCounts().size(); uint currentFaceIndex = 0; uint faceVertexCounts = polygon->getFaceVertexCounts()[currentFaceIndex]; // Iterate through the vertexes of the current polygon for ( uint vertexPosition=0; vertexPosition<numVertices; ++vertexPosition ) { // Handle front face vs back face by walking the vertexes backward on the back-face uint vertexIndexPosition = polygonPosition * numVertices + vertexPosition; int iteratorVertexIndex = vertexIndices[vertexIndexPosition]; int vertexIndex = meshPolygonsIter.vertexIndex ( iteratorVertexIndex ); // If we write a holed polygon and the actual vertex position is the last // position of the current face, then go to the next face in the list. if ( exportType == PolygonSource::POLYGONS && polygon->isHoled() && vertexPosition == faceVertexCounts ) { // Increment, cause we have found the next face ++currentFaceIndex; // Close the tag for the last face ( ( COLLADASW::Polygons* ) primitivesBasePoly )->closeElement(); // Get the vertex count of the current face uint currentFaceVertexCount = polygon->getFaceVertexCounts()[currentFaceIndex]; // Add the vertex count of the current face to the sum of face vertexes faceVertexCounts += currentFaceVertexCount; // Check if the current face is a normal polygon or a hole and open the corresponding tag. openPolygonOrHoleElement ( primitivesBasePoly, polygon, currentFaceIndex ); } // Write the vertex indices writeVertexIndices ( primitivesBasePoly, polygon, vertexIndex, normalIndices, iteratorVertexIndex, meshPolygonsIter, fnMesh, polyIndex ); } } // Add the tags for the polygons if ( exportType == PolygonSource::POLYGONS ) { if ( polygon->isHoled() ) ( ( COLLADASW::Polygons* ) primitivesBasePoly )->closeElement(); ( ( COLLADASW::Polygons* ) primitivesBasePoly )->closeElement(); } }
/** Create a RIB compatible subdivision surface representation using a Maya polygon mesh. */ liqRibSubdivisionData::liqRibSubdivisionData( MObject mesh ) : numFaces( 0 ), numPoints ( 0 ), nverts(), verts(), vertexParam( NULL ), interpolateBoundary( 0 ), uvDetail( rFaceVarying ), trueFacevarying( false ) { CM_TRACE_FUNC("liqRibSubdivisionData::liqRibSubdivisionData("<<MFnDagNode(mesh).fullPathName()<<")"); LIQDEBUGPRINTF( "-> creating subdivision surface\n" ); MFnMesh fnMesh( mesh ); name = fnMesh.name(); longName = fnMesh.fullPathName(); checkExtraTags( mesh ); numPoints = fnMesh.numVertices(); // UV sets ----------------- // const unsigned numSTs = fnMesh.numUVs(); const unsigned numUVSets = fnMesh.numUVSets(); MString currentUVSetName; MStringArray extraUVSetNames; fnMesh.getCurrentUVSetName( currentUVSetName ); MStringArray UVSetNames; fnMesh.getUVSetNames( UVSetNames ); for ( unsigned i( 0 ); i < numUVSets; i++ ) if( UVSetNames[i] != currentUVSetName ) extraUVSetNames.append( UVSetNames[i] ); numFaces = fnMesh.numPolygons(); const unsigned numFaceVertices( fnMesh.numFaceVertices() ); unsigned face( 0 ); unsigned faceVertex( 0 ); unsigned count; unsigned vertex; float S; float T; MPoint point; liqTokenPointer pointsPointerPair; liqTokenPointer pFaceVertexSPointer; liqTokenPointer pFaceVertexTPointer; // Allocate memory and tokens nverts = shared_array< RtInt >( new RtInt[ numFaces ] ); verts = shared_array< RtInt >( new RtInt[ numFaceVertices ] ); pointsPointerPair.set( "P", rPoint, numPoints ); pointsPointerPair.setDetailType( rVertex ); std::vector<liqTokenPointer> UVSetsArray; UVSetsArray.reserve( 1 + extraUVSetNames.length() ); if( numSTs > 0 ) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( "st", rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( uvDetail ); UVSetsArray.push_back( pFaceVertexPointerPair ); for ( unsigned j( 0 ); j<extraUVSetNames.length(); j++) { liqTokenPointer pFaceVertexPointerPair; pFaceVertexPointerPair.set( extraUVSetNames[j].asChar(), rFloat, numFaceVertices, 2 ); pFaceVertexPointerPair.setDetailType( uvDetail ); UVSetsArray.push_back( pFaceVertexPointerPair ); } if( liqglo.liqglo_outputMeshUVs ) { // Match MTOR, which also outputs face-varying STs as well for some reason - Paul // not anymore - Philippe pFaceVertexSPointer.set( "u", rFloat, numFaceVertices ); pFaceVertexSPointer.setDetailType( uvDetail ); pFaceVertexTPointer.set( "v", rFloat, numFaceVertices ); pFaceVertexTPointer.setDetailType( uvDetail ); } } vertexParam = pointsPointerPair.getTokenFloatArray(); // Read the mesh from Maya for ( MItMeshPolygon polyIt ( mesh ); polyIt.isDone() == false; polyIt.next() ) { count = polyIt.polygonVertexCount(); nverts[face] = count; unsigned i = count; while( i ) { --i; vertex = polyIt.vertexIndex( i ); verts[faceVertex] = vertex; point = polyIt.point( i, MSpace::kObject ); pointsPointerPair.setTokenFloat( vertex, point.x, point.y, point.z ); if( UVSetsArray.size() ) { fnMesh.getPolygonUV( face, i, S, T ); UVSetsArray[0].setTokenFloat( faceVertex, 0, S ); UVSetsArray[0].setTokenFloat( faceVertex, 1, 1 - T ); for ( unsigned j( 1 ); j<=extraUVSetNames.length(); j++ ) { fnMesh.getPolygonUV( face, i, S, T, &extraUVSetNames[j] ); UVSetsArray[j].setTokenFloat( faceVertex, 0, S ); UVSetsArray[j].setTokenFloat( faceVertex, 1, 1 - T ); } if( liqglo.liqglo_outputMeshUVs ) { // Match MTOR, which always outputs face-varying STs as well for some reason - Paul pFaceVertexSPointer.setTokenFloat( faceVertex, S ); pFaceVertexTPointer.setTokenFloat( faceVertex, 1 - T ); } } ++faceVertex; } ++face; } // Add tokens to array and clean up after tokenPointerArray.push_back( pointsPointerPair ); if( UVSetsArray.size() ) tokenPointerArray.insert( tokenPointerArray.end(), UVSetsArray.begin(), UVSetsArray.end() ); if( liqglo.liqglo_outputMeshUVs ) { assert( !pFaceVertexSPointer ); tokenPointerArray.push_back( pFaceVertexSPointer ); assert( !pFaceVertexTPointer ); tokenPointerArray.push_back( pFaceVertexTPointer ); } addAdditionalSurfaceParameters( mesh ); }