// --------------------------------------------------------
void GeometryPolygonExporter::exportPolygonSources (
    MFnMesh& fnMesh,
    const String& meshId,
    MStringArray& uvSetNames,
    MStringArray& colorSetNames,
    Sources* polygonSources,
    Sources* vertexSources,
    const bool hasFaceVertexNorms )
{
    // Initialize the members
    mMeshId = meshId;
    mUvSetNames = uvSetNames;
    mPolygonSources = polygonSources;
    mVertexSources = vertexSources;
    mHasFaceVertexNormals = hasFaceVertexNorms;
    mColorSetNames = colorSetNames;

    // If triangulation is requested, verify that it is
    // feasible by checking with all the mesh polygons
    if ( ExportOptions::exportTriangles() )
    {
        triangulated = true;

        for ( MItMeshPolygon polyIt ( fnMesh.object() ); triangulated && !polyIt.isDone(); polyIt.next() )
        {
            triangulated = polyIt.hasValidTriangulation();
        }
    }

    // If we have a hole in a polygon, we can't write a <polylist>.
    // Either we write <polygons> with holes or we write triangles.
    // Get hole information from the mesh node.
    // The format for the holes information is explained in the MFnMesh documentation.
    MStatus status;
    fnMesh.getHoles ( mHoleInfoArray, mHoleVertexArray, &status );
    holeCount = ( status != MStatus::kSuccess ) ? 0 : ( mHoleInfoArray.length() / 3 );

    // Find how many shaders are used by this instance of the mesh.
    // Each instance may apply a number of different materials to different faces.
    // We can use the getConnectedShaders member function of MFnMesh to find out
    // this shader information for each instance.
    mShaders.clear();
    mShaderIndices.clear();
    fnMesh.getConnectedShaders ( 0, mShaders, mShaderIndices );

    // Find the polygons that correspond to each materials and export them.
    uint realShaderCount = ( uint ) mShaders.length();
    uint numShaders = ( uint ) std::max ( ( size_t ) 1, ( size_t ) mShaders.length() );

    for ( uint shaderPosition=0; shaderPosition<numShaders; ++shaderPosition )
    {
        // Set the current shader position
        mShaderPosition = shaderPosition;

        // Export the polygons of the current shader
        exportShaderPolygons ( fnMesh );
    }
}
// --------------------------------------------------------
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);
            }
        }
    }
}
// ----------------------------------------
bool GeometryPolygonExporter::getPolygonVertexCount(
    MItMeshPolygon &meshPolygonsIter,
    unsigned long &numVertices )
{
    bool addVertexCount = false;

    // Establish the number of vertexes in the polygon.
    // We don't need the vertex count list for triangulation
    if ( triangulated ) return addVertexCount;

    // The number of vertices
    numVertices = 0;

    // Retrieve the vertices and increment polygon count
    // Get the number of vertices in the current mesh's polygon
    unsigned long polygonVertexCount = meshPolygonsIter.polygonVertexCount();
    if ( polygonVertexCount >= 3 )
    {
#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
        MIntArray vertexIndices;
        vertexIndices.setLength ( polygonVertexCount );
        for ( int pv = 0; pv < polygonVertexCount; ++pv )
        {
            vertexIndices[pv] = pv;
        }

        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

        addVertexCount = true;
    }

    return addVertexCount;
}
// ----------------------------------------
void GeometryPolygonExporter::writeShaderPolygons(
    COLLADASW::PrimitivesBase* primitivesBasePoly,
    const uint exportType,
    MFnMesh &fnMesh )
{
    // Number of polygons (could also be triangles)
    uint numPolygons = 0;

    // Generate the polygon set inputs.
    Sources polygonSetInputs;
    getVerticesInputAttributes( polygonSetInputs );

    // Iterate through all polygons of the current mesh and create them to export
    MItMeshPolygon meshPolygonsIter ( fnMesh.object() );
    for ( meshPolygonsIter.reset(); !meshPolygonsIter.isDone(); meshPolygonsIter.next() )
    {
        // Is this polygon shaded by this shader?
        uint realShaderCount = ( uint ) mShaders.length();
        int polyIndex = meshPolygonsIter.index();
        if ( mShaderPosition < realShaderCount &&
                ( uint ) mShaderIndices[polyIndex] != mShaderPosition ) continue;
        if ( mShaderPosition >= realShaderCount &&
                ( mShaderIndices[polyIndex] >= 0 &&
                  mShaderIndices[polyIndex] < ( int ) realShaderCount ) ) continue;

        // Create a polygon to store the vertex indexes to export
        PolygonSource polygon ( polygonSetInputs );

        // Create the polygon with the initialization data
        MIntArray vertexIndices;
        uint numPolygons = 0, numVertices = 0;
        initializePolygonSource ( fnMesh, meshPolygonsIter, polygon, vertexIndices, numPolygons, numVertices );

        // If we have polygons to export, push it into the polygon list
        if ( numPolygons > 0 )
        {
            writeElementVertexIndices ( primitivesBasePoly, &polygon, fnMesh, meshPolygonsIter, exportType, vertexIndices, numPolygons, numVertices );
        }
    }

    primitivesBasePoly->finish();
}
Exemplo n.º 5
0
int AttributeIndex<GDVAT_TEXCOORDS_0>(MItMeshPolygon &polyIt, unsigned int polyVertNum, const char* pAttributeName)
{
	MStatus result;
	int index;

	result = polyIt.getUVIndex(polyVertNum, index, &MString(pAttributeName));

	if( result == MS::kFailure )
		return -1;

	return index;	
}
// ----------------------------------------
bool GeometryPolygonExporter::verifyPolygonsForHoles(
    const MFnMesh &fnMesh )
{
    // If we want to export triangles, holes aren't of note.
    if ( triangulated ) return false;

    // Iterate through all polygons of the current mesh and
    // verify their polygons for holes.
    MItMeshPolygon meshPolygonsIter ( fnMesh.object() );
    for ( meshPolygonsIter.reset(); !meshPolygonsIter.isDone(); meshPolygonsIter.next() )
    {
        // Is this polygon shaded by this shader?
        int polyIndex = meshPolygonsIter.index();
        uint realShaderCount = ( uint ) mShaders.length();
        if ( mShaderPosition < realShaderCount &&
                ( uint ) mShaderIndices[polyIndex] != mShaderPosition ) continue;
        if ( mShaderPosition >= realShaderCount &&
                ( mShaderIndices[polyIndex] >= 0 &&
                  mShaderIndices[polyIndex] < ( int ) realShaderCount ) ) continue;

        // 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 )
        {
            return true;
        }
    }

    return false;
}
Exemplo n.º 7
0
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void GetMeshMatrix( MItMeshPolygon &pIt, int nMeshFaceIndex, MMatrix &geoMatrix  )
{
	if ( nMeshFaceIndex < static_cast< int >( pIt.count() ) )
	{
		MPointArray facePoints;

		int nOldIndex;
		pIt.setIndex( nMeshFaceIndex, nOldIndex );

		pIt.getPoints( facePoints, MSpace::kWorld );

		// Calculate cheezy coordinate system, if any edges are 0 length then all hell breaks loose
		MVector x = ( facePoints[ 2 ] - facePoints[ 0 ] ).normal();
		MVector z = ( facePoints[ 1 ] - facePoints[ 0 ] ).normal();
		MVector y = ( z ^ x ).normal();
		z = x ^ y;

		memcpy( const_cast< double * >( geoMatrix[ 0 ] ), &x[ 0 ], 3 * sizeof( double ) );
		memcpy( const_cast< double * >( geoMatrix[ 1 ] ), &y[ 0 ], 3 * sizeof( double ) );
		memcpy( const_cast< double * >( geoMatrix[ 2 ] ), &z[ 0 ], 3 * sizeof( double ) );

		MPoint center = pIt.center( MSpace::kWorld );

		memcpy( const_cast< double * >( geoMatrix[ 3] ), &center[ 0 ], 3 * sizeof( double ) );

		pIt.setIndex( nOldIndex, nMeshFaceIndex );
	}
	else
	{
		merr << "Mesh face index " << nMeshFaceIndex << " out of range, only " << pIt.count() << " faces on mesh" << std::endl;
	}
}
// ----------------------------------------
void GeometryPolygonExporter::writeVertexCountList(
    COLLADASW::PrimitivesBase* primitivesBase,
    const MFnMesh &fnMesh )
{
    // Iterate through all polygons of the current mesh.
    // Check their polygons for holes and retrieve the vertexCountList.
    MItMeshPolygon meshPolygonsIter ( fnMesh.object() );
    for ( meshPolygonsIter.reset(); !meshPolygonsIter.isDone(); meshPolygonsIter.next() )
    {
        // Is this polygon shaded by this shader?
        int polyIndex = meshPolygonsIter.index();
        uint realShaderCount = ( uint ) mShaders.length();
        if ( mShaderPosition < realShaderCount &&
                ( uint ) mShaderIndices[polyIndex] != mShaderPosition ) continue;
        if ( mShaderPosition >= realShaderCount &&
                ( mShaderIndices[polyIndex] >= 0 &&
                  mShaderIndices[polyIndex] < ( int ) realShaderCount ) ) continue;

        // Get the polygon count
        unsigned long vertexCount;
        if ( getPolygonVertexCount ( meshPolygonsIter, vertexCount ) )
            primitivesBase->appendValues( vertexCount );
    }
}
// ----------------------------------------
uint GeometryPolygonExporter::getShaderPolygonsCount(
    const MFnMesh &fnMesh )
{
    uint numPolygons = 0;

    // Iterate through all polygons of the current mesh.
    // Check their polygons for holes and retrieve the vertexCountList.
    MItMeshPolygon meshPolygonsIter ( fnMesh.object() );
    for ( meshPolygonsIter.reset(); !meshPolygonsIter.isDone(); meshPolygonsIter.next() )
    {
        // Is this polygon shaded by this shader?
        int polyIndex = meshPolygonsIter.index();
        uint realShaderCount = ( uint ) mShaders.length();
        if ( mShaderPosition < realShaderCount &&
                ( uint ) mShaderIndices[polyIndex] != mShaderPosition ) continue;
        if ( mShaderPosition >= realShaderCount &&
                ( mShaderIndices[polyIndex] >= 0 &&
                  mShaderIndices[polyIndex] < ( int ) realShaderCount ) ) continue;

        // Get the polygon count
        uint numMeshPolygons = 0, numVertices = 0;

        // 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 ) numMeshPolygons = (uint) numTriangles;
        }
        else if ( polygonVertexCount >= 3 )
        {
            numMeshPolygons = 1;
        }

        numPolygons += numMeshPolygons;
    }

    return numPolygons;
}
// ----------------------------------------
bool GeometryPolygonExporter::verifyTriangulation ( MFnMesh &fnMesh )
{
    // Iterate through all polygons of the current mesh
    MItMeshPolygon meshPolygonsIter ( fnMesh.object() );
    for ( meshPolygonsIter.reset(); !meshPolygonsIter.isDone(); meshPolygonsIter.next() )
    {
        // Is this polygon shaded by this shader?
        uint realShaderCount = ( uint ) mShaders.length();
        int polyIndex = meshPolygonsIter.index();
        if ( mShaderPosition < realShaderCount &&
                ( uint ) mShaderIndices[polyIndex] != mShaderPosition ) continue;
        if ( mShaderPosition >= realShaderCount &&
                ( mShaderIndices[polyIndex] >= 0 &&
                  mShaderIndices[polyIndex] < ( int ) realShaderCount ) ) continue;

        // Get the number of vertices in the current mesh's polygon
        if ( meshPolygonsIter.polygonVertexCount() != 3) return false;
    }

    // All polygons are triangles
    return true;
}
Exemplo n.º 11
0
/** 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 );
}
Exemplo n.º 12
0
/*
 *  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;
}
Exemplo n.º 14
0
//-------------------------------------------------------------------------------------------------------------------------------------------
void	visualizeMeshNode::drawShadedTriangles(MItMeshPolygon& polyIter, MItMeshVertex& vertIter, M3dView::DisplayStyle style, meshStatus meshStat)
//-------------------------------------------------------------------------------------------------------------------------------------------
{

				//alles zeichnen
				glPushAttrib(GL_ALL_ATTRIB_BITS);
				
				
				glEnable(GL_POLYGON_OFFSET_FILL);
				
				
				glEnable(GL_BLEND);
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				//glDepthMask(GL_FALSE);
				
				glPolygonMode(GL_BACK, GL_FILL);
				glShadeModel(GL_SMOOTH);
				
				
				
				//Dass muss ausßerhalb der displayList bleiben, weil dieser Wert nicht precompiliert werden darf
				float param1 = 0.45, param2 = 0.55;

				// im DebugMode werden die Params anhand der NodeParameter gesetzt

				if(style == M3dView::kWireFrame)
				{

						param1 = 0.45; param2 = 0.55;

				}
				else
				{
					switch(meshStat)
					{
					case kNone:
						{
							param1 = -0.5; param2 = -0.6;

							break;
						}
					case kHilited:
						{
							param1 = 0.45; param2 = 0.55;
							
							break;
						}
					}
				}


				#ifdef DEBUG
				MPlug tmpPlug(thisMObject(), pOffset1Obj);
				tmpPlug.getValue(param1);
				
				tmpPlug.setAttribute(pOffset2Obj);
				tmpPlug.getValue(param2);
				#endif

				glPolygonOffset( param1, param2 );
				
				//jedes Poly zeichnen
				
				uint numPolys = polyIter.count();
				uint i, x , l;
				MPoint	point;
				MColor	tmpCol;
				MPointArray triPoints;
				MIntArray	triVtx;
				//glColor4f(0.0f, 0.0f, 1.0f, 0.2);
				
				for(i = 0; i < numPolys; i++, polyIter.next())
				{
					

					polyIter.getTriangles(triPoints, triVtx);
					
					
					l = triVtx.length();
					
					
					glBegin(GL_TRIANGLES);
					
					for(x = 0; x < l ; x+=3)
					{
						//view.setDrawColor( getCalColor(vtxColor, MColor(1.0,0.0,0.0), vtxWeightArray[ polyVtx[x] ] ) );
						//view.setDrawColor( vtxColor *  vtxWeightArray[ polyVtx[x] ]);
						//glColor4f(0.0f, 0.0f, 1.0f, vtxWeightArray[ polyVtx[x] ]);
						
						tmpCol = getCalColor(vtxColor, vtxColor2 ,  vtxWeightArray[ triVtx[x] ]);
						glColor4f(tmpCol.r, tmpCol.g,tmpCol.b, vtxWeightArray[ triVtx[x] ]);
						glVertex3d(triPoints[x].x, triPoints[x].y, triPoints[x].z);
						
			
						tmpCol = getCalColor(vtxColor, vtxColor2 ,  vtxWeightArray[ triVtx[x+1] ]);
						glColor4f(tmpCol.r, tmpCol.g,tmpCol.b, vtxWeightArray[ triVtx[x+1] ]);
						glVertex3d(triPoints[x+1].x, triPoints[x+1].y, triPoints[x+1].z);

						tmpCol = getCalColor(vtxColor, vtxColor2 ,  vtxWeightArray[ triVtx[x+2] ]);
						glColor4f(tmpCol.r, tmpCol.g,tmpCol.b, vtxWeightArray[ triVtx[x+2] ]);
						glVertex3d(triPoints[x+2].x, triPoints[x+2].y, triPoints[x+2].z);

					}
					
					glEnd();
					
				}
				
				
			//	glDisable(GL_POLYGON_OFFSET_FILL);

				glPopAttrib();


}
// --------------------------------------------------------
void GeometryPolygonExporter::writeVertexIndices (
    COLLADASW::PrimitivesBase* primitivesBasePoly,
    PolygonSource *polygon,
    const int vertexIndex,
    const MIntArray &normalIndices,
    const int iteratorVertexIndex,
    MItMeshPolygon &meshPolygonsIter,
    MFnMesh &fnMesh,
    const int polyIndex )
{
    // Dump the indices
    size_t numAttributes = polygon->getVertexAttributes().size();

    // Output each vertex attribute we need
    for ( size_t kk=0; kk<numAttributes; ++kk )
    {
        const SourceInput& vertexAttributes = polygon->getVertexAttributes()[kk];
        COLLADASW::InputSemantic::Semantics type = vertexAttributes.getType();
        switch ( vertexAttributes.getType() )
        {
        case COLLADASW::InputSemantic::VERTEX:
        case COLLADASW::InputSemantic::POSITION:
            primitivesBasePoly->appendValues ( vertexIndex );
            break;
        case COLLADASW::InputSemantic::NORMAL:
        case COLLADASW::InputSemantic::TANGENT:
        case COLLADASW::InputSemantic::BINORMAL:
        {
            if (mHasFaceVertexNormals)
            {
                // The tangent and the binormal can use the index of the normal
                int currentVertexIndex = normalIndices [iteratorVertexIndex];
                primitivesBasePoly->appendValues ( currentVertexIndex );
            }
            else
            {
                // Assert, if we don't have initialized the normal indices,
                // but want to read them out here!
                MGlobal::displayError("No face vertex normals to proceed!");
                COLLADABU_ASSERT ( mHasFaceVertexNormals );
                return;
            }
        }
        break;
        case COLLADASW::InputSemantic::TEXTANGENT:
        case COLLADASW::InputSemantic::TEXBINORMAL:
        {
            // The texture binormal can use the index of the texture tangent.
            unsigned int texTangentIndex2 = meshPolygonsIter.tangentIndex ( iteratorVertexIndex );
            primitivesBasePoly->appendValues ( texTangentIndex2 );
        }
        break;
        case COLLADASW::InputSemantic::TEXCOORD:
        {
            int uvIndex = 0;
            int idx = vertexAttributes.getIdx();
            meshPolygonsIter.getUVIndex ( iteratorVertexIndex, uvIndex, &mUvSetNames[idx] );
            primitivesBasePoly->appendValues ( uvIndex );
        }
        break;
        case COLLADASW::InputSemantic::COLOR:
        {
            MString& colorSetName = mColorSetNames[vertexAttributes.getIdx()];
            int colorIndex = 0;
            {
#if MAYA_API_VERSION >= 700
                fnMesh.getColorIndex ( polyIndex, iteratorVertexIndex, colorIndex, &colorSetName );
#else
                fnMesh.getFaceVertexColorIndex ( polyIndex, iteratorVertexIndex, colorIndex );
#endif
            }
            primitivesBasePoly->appendValues ( colorIndex );
        }
        break;
        case COLLADASW::InputSemantic::UNKNOWN:
        case COLLADASW::InputSemantic::UV:
//            case COLLADASW::EXTRA:
        default:
            break; // Not exported/supported
        }
    }
}
// --------------------------------------------------------
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
    }
}
/** 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 );
}
// --------------------------------------------------------
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();
    }
}