예제 #1
0
// static
bool OBJLoader::parseOBJ( QString objFilename, std::shared_ptr< OBJData > pOBJData )
{
	// attempt to read the file
	QFile inputFile( objFilename );
	if( !( inputFile.open( QIODevice::ReadOnly ) ) )
	{
		return false;
	}

	int lineNumber = 0;
	QString line = "";	
	OBJGroup* pCurrentGroup = pOBJData->getGroupByName( "" ); // default group name is the empty string

	QTextStream inputTextStream( &inputFile );

	QString delim( " " );

	line = inputTextStream.readLine();
	while( !( line.isNull() ) )
	{
		if( line != "" )
		{
			QStringList tokens = line.split( delim, QString::SkipEmptyParts );

			if( tokens.size() > 0 )
			{
				QString commandToken = tokens[ 0 ];

				if( commandToken == "mtllib" )
				{
					QString mtlRelativeFilename = tokens[ 1 ];
					QFileInfo objFileInfo( objFilename );
					QDir objDir = objFileInfo.dir();
					QString mtlAbsoluteFilename = objDir.absolutePath() + "/" + mtlRelativeFilename;
					parseMTL( mtlAbsoluteFilename, pOBJData );
				}
				else if( commandToken == "g" )
				{
					QString newGroupName;

					if( tokens.size() < 2 )
					{
						fprintf( stderr, "Warning: group has no name, defaulting to ""\nline: %d\n%s",
							lineNumber, qPrintable( line ) );

						newGroupName = "";
					}
					else
					{
						newGroupName = tokens[ 1 ];
					}

					if( newGroupName != pCurrentGroup->name() )
					{
						if( pOBJData->containsGroup( newGroupName ) )
						{
							pCurrentGroup = pOBJData->getGroupByName( newGroupName );
						}
						else
						{
							pCurrentGroup = pOBJData->addGroup( newGroupName );
						}						
					}
				}
				else if( commandToken == "v" )
				{
					// TODO: error checking on all of these and tear down pOBJData
					OBJLoader::parsePosition( lineNumber, line, tokens, pOBJData );
				}
				else if( commandToken == "vt" )
				{
					OBJLoader::parseTextureCoordinate( lineNumber, line, tokens, pOBJData );
				}
				else if( commandToken == "vn" )
				{
					OBJLoader::parseNormal( lineNumber, line, tokens, pOBJData );
				}
				else if( commandToken == "usemtl" )
				{
					pCurrentGroup->addMaterial( tokens[ 1 ] );
				}
				else if( commandToken == "f" || commandToken == "fo" )
				{
					OBJLoader::parseFace( lineNumber, line,
						tokens, pCurrentGroup );
				}
			}
		}

		++lineNumber;
		line = inputTextStream.readLine();
	}

	return true;
}
예제 #2
0
파일: OBJLoader.cpp 프로젝트: jiawen/libcgt
// static
bool OBJLoader::parseFace( int lineNumber, const std::string& line,
                          const std::vector< std::string >& tokens,
                          OBJGroup& currentGroup )
{
    // TODO: support negative indices.
    if( tokens.size() < 4 )
    {
        fprintf( stderr,
                "Incorrect number of tokens at line number: %d\n, %s\n",
                lineNumber, line.c_str() );
        return false;
    }
    // first check line consistency - each vertex in the face
    // should have the same number of attributes
    bool faceIsValid;
    bool faceHasTextureCoordinates;
    bool faceHasNormals;

    faceIsValid = OBJLoader::faceHasConsistentAttributes( tokens,
        &faceHasTextureCoordinates, &faceHasNormals );

    if( !faceIsValid )
    {
        fprintf( stderr, "Face attributes inconsistent at line number: %d\n%s\n",
                lineNumber, line.c_str() );
        return false;
    }

    // ensure that all faces in a group are consistent:
    // they either all have texture coordinates or they don't
    // they either all have normals or they don't
    //
    // check how many faces the current group has
    // if the group has no faces, then the first face sets the group attributes

    if( currentGroup.numFaces() == 0 )
    {
        currentGroup.setHasTextureCoordinates( faceHasTextureCoordinates );
        currentGroup.setHasNormals( faceHasNormals );
    }

    bool faceIsConsistentWithGroup =
        ( currentGroup.hasTextureCoordinates() == faceHasTextureCoordinates )
        && ( currentGroup.hasNormals() == faceHasNormals );

    if( !faceIsConsistentWithGroup )
    {
        // TODO: boolToString()
        fprintf( stderr,
                "Face attributes inconsistent with group: %s at line: %d\n%s\n",
                currentGroup.name().c_str(), lineNumber, line.c_str() );
        fprintf( stderr, "group.hasTextureCoordinates() = %d\n",
                currentGroup.hasTextureCoordinates() );
        fprintf( stderr, "face.hasTextureCoordinates() = %d\n",
                faceHasTextureCoordinates );
        fprintf( stderr, "group.hasNormals() = %d\n",
                currentGroup.hasNormals() );
        fprintf( stderr, "face.hasNormals() = %d\n", faceHasNormals );

        return false;
    }

    OBJFace face( faceHasTextureCoordinates, faceHasNormals );

    // Process each vertex.
    for( int i = 1; i < tokens.size(); ++i )
    {
        int vertexPositionIndex;
        int vertexTextureCoordinateIndex;
        int vertexNormalIndex;

        OBJLoader::getVertexAttributes( tokens[ i ],
            &vertexPositionIndex, &vertexTextureCoordinateIndex,
            &vertexNormalIndex );

        face.positionIndices().push_back( vertexPositionIndex - 1 );

        if( faceHasTextureCoordinates )
        {
            face.textureCoordinateIndices().push_back(
                vertexTextureCoordinateIndex - 1 );
        }
        if( faceHasNormals )
        {
            face.normalIndices().push_back( vertexNormalIndex - 1 );
        }
    }

    currentGroup.addFace( face );
    return true;
}