Bladeren bron

bugfix: Obj-importer is now able to deal with 3d-texture coordinates.

Signed-off-by: Kim Kulling <[email protected]>
Kim Kulling 11 jaren geleden
bovenliggende
commit
fbaf89492d
5 gewijzigde bestanden met toevoegingen van 79 en 52 verwijderingen
  1. 1 1
      code/ObjFileData.h
  2. 24 24
      code/ObjFileImporter.cpp
  3. 45 19
      code/ObjFileParser.cpp
  4. 8 7
      code/ObjFileParser.h
  5. 1 1
      code/ObjTools.h

+ 1 - 1
code/ObjFileData.h

@@ -290,7 +290,7 @@ struct Model
 	//!	Active group
 	std::string m_strActiveGroup;
 	//!	Vector with generated texture coordinates
-	std::vector<aiVector2D> m_TextureCoord;
+	std::vector<aiVector3D> m_TextureCoord;
 	//!	Current mesh instance
 	Mesh *m_pCurrentMesh;
 	//!	Vector with stored meshes

+ 24 - 24
code/ObjFileImporter.cpp

@@ -60,6 +60,7 @@ static const aiImporterDesc desc = {
 	"obj"
 };
 
+static const unsigned int ObjMinSize = 16;
 
 namespace Assimp	{
 
@@ -80,12 +81,8 @@ ObjFileImporter::ObjFileImporter() :
 //	Destructor.
 ObjFileImporter::~ObjFileImporter()
 {
-	// Release root object instance
-	if (NULL != m_pRootObject)
-	{
-		delete m_pRootObject;
-		m_pRootObject = NULL;
-	}
+	delete m_pRootObject;
+	m_pRootObject = NULL;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -118,12 +115,13 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
 	// Read file into memory
 	const std::string mode = "rb";
 	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
-	if (NULL == file.get())
-		throw DeadlyImportError( "Failed to open file " + pFile + ".");
+    if( !file.get() ) {
+        throw DeadlyImportError( "Failed to open file " + pFile + "." );
+    }
 
 	// Get the file-size and validate it, throwing an exception when fails
 	size_t fileSize = file->FileSize();
-	if( fileSize < 16) {
+    if( fileSize < ObjMinSize ) {
 		throw DeadlyImportError( "OBJ-file is too small.");
     }
 
@@ -154,10 +152,10 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
 
 // ------------------------------------------------------------------------------------------------
 //	Create the data from parsed obj-file
-void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene)
-{
-	if (0L == pModel)
-		return;
+void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene) {
+    if( 0L == pModel ) {
+        return;
+    }
 		
 	// Create the root node of the scene
 	pScene->mRootNode = new aiNode;
@@ -200,8 +198,9 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
 									 std::vector<aiMesh*> &MeshArray )
 {
 	ai_assert( NULL != pModel );
-	if ( NULL == pObject )
-		return NULL;
+    if( NULL == pObject ) {
+        return NULL;
+    }
 	
 	// Store older mesh size to be able to computes mesh offsets for new mesh instances
 	const size_t oldMeshSize = MeshArray.size();
@@ -210,8 +209,9 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
 	pNode->mName = pObject->m_strObjName;
 	
 	// If we have a parent node, store it
-	if (pParent != NULL)
-		appendChildToParentNode(pParent, pNode);
+    if( pParent != NULL ) {
+        appendChildToParentNode( pParent, pNode );
+    }
 
 	for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
 	{
@@ -265,8 +265,9 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
 {
 	// Checking preconditions
 	ai_assert( NULL != pModel );
-	if (NULL == pData)
-		return;
+    if( NULL == pData ) {
+        return;
+    }
 
 	// Create faces
 	ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
@@ -284,8 +285,7 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
 		else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
 			pMesh->mNumFaces += inp->m_pVertices->size();
 			pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
-		}
-		else {
+		} else {
 			++pMesh->mNumFaces;
 			if (inp->m_pVertices->size() > 3) {
 				pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
@@ -409,10 +409,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 				ai_assert( tex < pModel->m_TextureCoord.size() );
 					
 				if ( tex >= pModel->m_TextureCoord.size() )
-					throw DeadlyImportError("OBJ: texture coord index out of range");
+					throw DeadlyImportError("OBJ: texture coordinate index out of range");
 
-				aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
-				pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
+				const aiVector3D &coord3d = pModel->m_TextureCoord[ tex ];
+                pMesh->mTextureCoords[ 0 ][ newIndex ] = aiVector3D( coord3d.x, coord3d.y, coord3d.z );
 			}
 
 			ai_assert( pMesh->mNumVertices > newIndex );

+ 45 - 19
code/ObjFileParser.cpp

@@ -108,19 +108,14 @@ void ObjFileParser::parseFile()
 		case 'v': // Parse a vertex texture coordinate
 			{
 				++m_DataIt;
-				if (*m_DataIt == ' ' || *m_DataIt == '\t')
-				{
-					// Read in vertex definition
+				if (*m_DataIt == ' ' || *m_DataIt == '\t') {
+					// read in vertex definition
 					getVector3(m_pModel->m_Vertices);
-				}
-				else if (*m_DataIt == 't')
-				{
-					// Read in texture coordinate (2D)
-					++m_DataIt;
-					getVector2(m_pModel->m_TextureCoord);
-				}
-				else if (*m_DataIt == 'n')
-				{
+				} else if (*m_DataIt == 't') {
+					// read in texture coordinate ( 2D or 3D )
+                    ++m_DataIt;
+                    getVector( m_pModel->m_TextureCoord );
+				} else if (*m_DataIt == 'n') {
 					// Read in normal vector definition
 					++m_DataIt;
 					getVector3( m_pModel->m_Normals );
@@ -235,10 +230,43 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
 	pBuffer[ index ] = '\0';
 }
 
+// -------------------------------------------------------------------
+void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
+    size_t numComponents( 0 );
+    DataArrayIt tmp( m_DataIt );
+    while( !IsLineEnd( *tmp ) ) {
+        if( *tmp == ' ' ) {
+            ++numComponents;
+        }
+        tmp++;
+    }
+    float x, y, z;
+    if( 2 == numComponents ) {
+        copyNextWord( m_buffer, BUFFERSIZE );
+        x = ( float ) fast_atof( m_buffer );
+
+        copyNextWord( m_buffer, BUFFERSIZE );
+        y = ( float ) fast_atof( m_buffer );
+        z = 0.0;
+    } else if( 3 == numComponents ) {
+        copyNextWord( m_buffer, BUFFERSIZE );
+        x = ( float ) fast_atof( m_buffer );
+
+        copyNextWord( m_buffer, BUFFERSIZE );
+        y = ( float ) fast_atof( m_buffer );
+
+        copyNextWord( m_buffer, BUFFERSIZE );
+        z = ( float ) fast_atof( m_buffer );
+    } else {
+        ai_assert( !"Invalid number of components" );
+    }
+    point3d_array.push_back( aiVector3D( x, y, z ) );
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+}
+
 // -------------------------------------------------------------------
 //	Get values for a new 3D vector instance
-void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array)
-{
+void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) {
 	float x, y, z;
 	copyNextWord(m_buffer, BUFFERSIZE);
 	x = (float) fast_atof(m_buffer);	
@@ -246,18 +274,16 @@ void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array)
 	copyNextWord(m_buffer, BUFFERSIZE);
 	y = (float) fast_atof(m_buffer);
 
-	copyNextWord(m_buffer, BUFFERSIZE);
-	z = (float) fast_atof(m_buffer);
+    copyNextWord( m_buffer, BUFFERSIZE );
+    z = ( float ) fast_atof( m_buffer );
 
 	point3d_array.push_back( aiVector3D( x, y, z ) );
-	//skipLine();
 	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 
 // -------------------------------------------------------------------
 //	Get values for a new 2D vector instance
-void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array )
-{
+void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
 	float x, y;
 	copyNextWord(m_buffer, BUFFERSIZE);
 	x = (float) fast_atof(m_buffer);	

+ 8 - 7
code/ObjFileParser.h

@@ -37,8 +37,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ----------------------------------------------------------------------
 */
-
-
 #ifndef OBJ_FILEPARSER_H_INC
 #define OBJ_FILEPARSER_H_INC
 
@@ -79,26 +77,29 @@ public:
 	ObjFile::Model *GetModel() const;
 
 private:
-	///	Parse the loadedfile
+	///	Parse the loaded file
 	void parseFile();
 	///	Method to copy the new delimited word in the current line.
 	void copyNextWord(char *pBuffer, size_t length);
 	///	Method to copy the new line.
 	void copyNextLine(char *pBuffer, size_t length);
-	///	Stores the following 3d vector.
+    /// Stores the vector 
+    void getVector( std::vector<aiVector3D> &point3d_array );
+    ///	Stores the following 3d vector.
 	void getVector3( std::vector<aiVector3D> &point3d_array );
 	///	Stores the following 3d vector.
 	void getVector2(std::vector<aiVector2D> &point2d_array);
-	///	Stores the following face.
+    ///	Stores the following face.
 	void getFace(aiPrimitiveType type);
-	void getMaterialDesc();
+	/// Reads the material description.
+    void getMaterialDesc();
 	///	Gets a comment.
 	void getComment();
 	/// Gets a a material library.
 	void getMaterialLib();
 	/// Creates a new material.
 	void getNewMaterial();
-	/// Gets the groupname from file.
+	/// Gets the group name from file.
 	void getGroupName();
 	/// Gets the group number from file.
 	void getGroupNumber();

+ 1 - 1
code/ObjTools.h

@@ -107,7 +107,7 @@ inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
 	return pBuffer;
 }
 
-/**	@brief	Returns ponter a next token
+/**	@brief	Returns pointer a next token
  *	@param	pBuffer	Pointer to data buffer
  *	@param	pEnd	Pointer to end of buffer
  *	@return	Pointer to next token