Sfoglia il codice sorgente

[3298060] OBJ: Add support for p and l elements

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1070 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 14 anni fa
parent
commit
df63b4b3ed

+ 5 - 4
code/ObjFileData.h

@@ -64,7 +64,7 @@ struct Face
 	typedef std::vector<unsigned int> IndexArray;
 
 	//!	Primitive type
-	int m_PrimitiveType;
+	aiPrimitiveType m_PrimitiveType;
 	//!	Vertex indices
 	IndexArray *m_pVertices;
 	//!	Normal indices
@@ -80,8 +80,9 @@ struct Face
 	//!	\param	pTexCoords	Pointer to assigned texture indexbuffer
 	Face( std::vector<unsigned int> *pVertices, 
 			std::vector<unsigned int> *pNormals, 
-			std::vector<unsigned int> *pTexCoords) : 
-		m_PrimitiveType( 2 ), 
+			std::vector<unsigned int> *pTexCoords,
+			aiPrimitiveType pt = aiPrimitiveType_POLYGON) : 
+		m_PrimitiveType( pt ), 
 		m_pVertices( pVertices ), 
 		m_pNormals( pNormals ),
 		m_pTexturCoords( pTexCoords ), 
@@ -195,7 +196,7 @@ struct Material
 //!	\brief	Data structure to store a mesh
 struct Mesh
 {
-	static const unsigned int NoMaterial = 999999999;
+	static const unsigned int NoMaterial = ~0u;
 
 	///	Array with pointer to all stored faces
 	std::vector<Face*> m_Faces;

+ 90 - 31
code/ObjFileImporter.cpp

@@ -251,7 +251,23 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
 	// Create faces
 	ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
 	ai_assert( NULL != pObjMesh );
-	pMesh->mNumFaces = static_cast<unsigned int>( pObjMesh->m_Faces.size() );
+
+	pMesh->mNumFaces = 0;
+	for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
+	{
+		ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+		if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+			pMesh->mNumFaces += inp->m_pVertices->size() - 1;
+		}
+		else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+			pMesh->mNumFaces += inp->m_pVertices->size();
+		}
+		else {
+			++pMesh->mNumFaces;
+		}
+	}
+
+	unsigned int uiIdxCount = 0u;
 	if ( pMesh->mNumFaces > 0 )
 	{
 		pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
@@ -260,31 +276,40 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
 			pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
 		}
 
+		unsigned int outIndex = 0;
+
 		// Copy all data from all stored meshes
 		for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
 		{
-			aiFace *pFace = &pMesh->mFaces[ index ];
-			const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
-			pFace->mNumIndices = (unsigned int) uiNumIndices;
-			if (pFace->mNumIndices > 0)
-			{
-				pFace->mIndices = new unsigned int[ uiNumIndices ];
-				ObjFile::Face::IndexArray *pIndexArray = pObjMesh->m_Faces[ index ]->m_pVertices;
-				ai_assert ( NULL != pIndexArray );
-				for ( size_t a=0; a<pFace->mNumIndices; a++ )
-				{
-					pFace->mIndices[ a ] = pIndexArray->at( a );
+			ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+			if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
+				for(size_t i = 0; i < inp->m_pVertices->size() - 1; ++i) {
+					aiFace& f = pMesh->mFaces[ outIndex++ ];
+					uiIdxCount += f.mNumIndices = 2;
+					f.mIndices = new unsigned int[2];
 				}
+				continue;
 			}
-			else
-			{
-				pFace->mIndices = NULL;
+			else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
+				for(size_t i = 0; i < inp->m_pVertices->size(); ++i) {
+					aiFace& f = pMesh->mFaces[ outIndex++ ];
+					uiIdxCount += f.mNumIndices = 1;
+					f.mIndices = new unsigned int[1];
+				}
+				continue;
+			}
+
+			aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
+			const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size();
+			uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
+			if (pFace->mNumIndices > 0) {
+				pFace->mIndices = new unsigned int[ uiNumIndices ];			
 			}
 		}
 	}
 
 	// Create mesh vertices
-	createVertexArray(pModel, pData, uiMeshIndex, pMesh);
+	createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -292,7 +317,8 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
 void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, 
 										const ObjFile::Object* pCurrentObject, 
 										unsigned int uiMeshIndex,
-										aiMesh* pMesh)
+										aiMesh* pMesh,
+										unsigned int uiIdxCount)
 {
 	// Checking preconditions
 	ai_assert( NULL != pCurrentObject );
@@ -307,7 +333,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 		return;
 
 	// Copy vertices of this mesh instance
-	pMesh->mNumVertices = (unsigned int) pObjMesh->m_uiNumIndices;
+	pMesh->mNumVertices = uiIdxCount;
 	pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
 	
 	// Allocate buffer for normal vectors
@@ -318,21 +344,18 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 	if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
 	{
 		pMesh->mNumUVComponents[ 0 ] = 2;
-		pMesh->mTextureCoords[ 0 ]   = new aiVector3D[ pMesh->mNumVertices ];
+		pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ];
 	}
 	
 	// Copy vertices, normals and textures into aiMesh instance
-	unsigned int newIndex = 0;
+	unsigned int newIndex = 0, outIndex = 0;
 	for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ )
 	{
-		// Get destination face
-		aiFace *pDestFace = &pMesh->mFaces[ index ];
-		
 		// Get source face
 		ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; 
 
 		// Copy all index arrays
-		for ( size_t vertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
+		for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ )
 		{
 			const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex );
 			if (vertex >= pModel->m_Vertices.size()) {
@@ -359,19 +382,55 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
 				{
 					const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex );
 					ai_assert( tex < pModel->m_TextureCoord.size() );
-					for ( size_t i=0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++ )
+					for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ )
 					{
-						if ( pMesh->mNumUVComponents[ i ] > 0 )
-						{
-							aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
-							pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
-						}
+						aiVector2D coord2d = pModel->m_TextureCoord[ tex ];
+						pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 );
 					}
 				}
 			}
 
 			ai_assert( pMesh->mNumVertices > newIndex );
-			pDestFace->mIndices[ vertexIndex ] = newIndex;
+
+			// Get destination face
+			aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
+
+			const bool last = vertexIndex == pSourceFace->m_pVertices->size() - 1;
+			if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
+				pDestFace->mIndices[ outVertexIndex++ ] = newIndex;
+			}
+
+			if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) {
+				outIndex++;
+				outVertexIndex = 0;
+			}
+			else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) {
+				outVertexIndex = 0;
+
+				if(!last) {
+					outIndex++;
+				}
+
+				if (vertexIndex) {
+					if(!last) {
+						pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
+						if ( !pSourceFace->m_pNormals->empty() && !pModel->m_Normals.empty()) {
+							pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
+						}
+						if ( !pModel->m_TextureCoord.empty() ) {
+							for ( size_t i=0; i < pMesh->GetNumUVChannels(); i++ ) {
+								pMesh->mTextureCoords[ i ][ newIndex+1 ] = pMesh->mTextureCoords[ i ][ newIndex ];
+							}
+						}
+						++newIndex;
+					}
+
+					pDestFace[-1].mIndices[1] = newIndex;
+				}
+			}
+			else if (last) {
+				outIndex++;
+			}
 			++newIndex;
 		}
 	}	

+ 1 - 1
code/ObjFileImporter.h

@@ -96,7 +96,7 @@ private:
 	
 	//!	\brief	Creates vertices from model.
 	void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
-		unsigned int uiMeshIndex, aiMesh* pMesh);
+		unsigned int uiMeshIndex, aiMesh* pMesh,unsigned int uiIdxCount);
 
 	//!	\brief	Object counter helper method.
 	void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes);

+ 23 - 15
code/ObjFileParser.cpp

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ObjFileMtlImporter.h"
 #include "ObjTools.h"
 #include "ObjFileData.h"
-#include "fast_atof.h"
+#include "ParsingUtils.h"
 #include "../include/aiTypes.h"
 #include "DefaultIOSystem.h"
 
@@ -55,7 +55,6 @@ namespace Assimp
 
 // -------------------------------------------------------------------
 const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; 
-// fix: changed that to our standard default name
 
 // -------------------------------------------------------------------
 //	Constructor with loaded data and directories.
@@ -82,7 +81,7 @@ ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModel
 }
 
 // -------------------------------------------------------------------
-//	Destrcutor.
+//	Destructor
 ObjFileParser::~ObjFileParser()
 {
 	delete m_pModel->m_pDefaultMaterial;
@@ -133,9 +132,12 @@ void ObjFileParser::parseFile()
 			}
 			break;
 
-		case 'f': // Parse a face
+		case 'p': // Parse a face, line or point statement
+		case 'l':
+		case 'f':
 			{
-				getFace();
+				getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l' 
+					? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
 			}
 			break;
 
@@ -255,7 +257,7 @@ void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array )
 
 // -------------------------------------------------------------------
 //	Get values for a new face instance
-void ObjFileParser::getFace()
+void ObjFileParser::getFace(aiPrimitiveType type)
 {
 	copyNextLine(m_buffer, BUFFERSIZE);
 	if (m_DataIt == m_DataItEnd)
@@ -272,23 +274,24 @@ void ObjFileParser::getFace()
 	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
 	bool hasNormal = false;
 
-	bool vt = (!m_pModel->m_TextureCoord.empty());
-	bool vn = (!m_pModel->m_Normals.empty());
+	const bool vt = (!m_pModel->m_TextureCoord.empty());
+	const bool vn = (!m_pModel->m_Normals.empty());
 	int iStep = 0, iPos = 0;
 	while (pPtr != pEnd)
 	{
 		iStep = 1;
-		if (*pPtr == '\0')
-			break;
 
-		if (*pPtr=='\r' || *pPtr=='\n')
+		if (IsLineEnd(*pPtr))
 			break;
 
 		if (*pPtr=='/' )
 		{
+			if (type == aiPrimitiveType_POINT) {
+				DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
+			}
 			if (iPos == 0)
 			{
-				//if there are no texturecoordinates in the obj file but normals
+				//if there are no texture coordinates in the file, but normals
 				if (!vt && vn) {
 					iPos = 1;
 					iStep++;
@@ -330,11 +333,16 @@ void ObjFileParser::getFace()
 				}
 			}
 		}
-		for ( int i=0; i<iStep; i++ )
-			++pPtr;
+		pPtr += iStep;
+	}
+
+	if (pIndices->empty()) {
+		DefaultLogger::get()->error("Obj: Ignoring empty face");
+		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+		return;
 	}
 
-	ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID );
+	ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
 	
 	// Set active material, if one set
 	if (NULL != m_pModel->m_pCurrentMaterial) 

+ 1 - 1
code/ObjFileParser.h

@@ -90,7 +90,7 @@ private:
 	///	Stores the following 3d vector.
 	void getVector2(std::vector<aiVector2D> &point2d_array);
 	///	Stores the following face.
-	void getFace();
+	void getFace(aiPrimitiveType type);
 	void getMaterialDesc();
 	///	Gets a comment.
 	void getComment();

+ 22 - 0
test/models/OBJ/testline.obj

@@ -0,0 +1,22 @@
+# Vertex list
+
+v -0.5 -0.5 0.5
+v -0.5 -0.5 -0.5
+v -0.5 0.5 -0.5
+v -0.5 0.5 0.5
+v 0.5 -0.5 0.5
+v 0.5 -0.5 -0.5
+v 0.5 0.5 -0.5
+v 0.5 0.5 0.5
+
+# Point/Line/Face list
+
+usemtl Default
+l 4 3 2 1
+l 2 6 5 1
+l 3 7 6 2
+l 8 7 3 4
+l 5 8 4 1
+l 6 7 8 5
+
+# End of file

+ 36 - 0
test/models/OBJ/testmixed.obj

@@ -0,0 +1,36 @@
+# Vertex list
+
+v -0.5 -0.5 0.5
+v -0.5 -0.5 -0.5
+v -0.5 0.5 -0.5
+v -0.5 0.5 0.5
+v 0.5 -0.5 0.5
+v 0.5 -0.5 -0.5
+v 0.5 0.5 -0.5
+v 0.5 0.5 0.5
+
+# Point/Line/Face list
+
+usemtl Default
+l 4 3 2 1
+l 2 6 5 1
+l 3 7 6 2
+l 8 7 3 4
+l 5 8 4 1
+l 6 7 8 5
+
+usemtl Default
+p 4 3 2 1
+p 2 6 5 1
+f 3 7 6 2
+p 3 7 6 2
+p 8 7 3 4
+p 5 8 4 1
+p 6 7 8 5
+f 4 3 2 1
+f 2 6 5 1
+f 8 7 3 4
+f 5 8 4 1
+f 6 7 8 5
+
+# End of file

+ 22 - 0
test/models/OBJ/testpoints.obj

@@ -0,0 +1,22 @@
+# Vertex list
+
+v -0.5 -0.5 0.5
+v -0.5 -0.5 -0.5
+v -0.5 0.5 -0.5
+v -0.5 0.5 0.5
+v 0.5 -0.5 0.5
+v 0.5 -0.5 -0.5
+v 0.5 0.5 -0.5
+v 0.5 0.5 0.5
+
+# Point/Line/Face list
+
+usemtl Default
+p 4 3 2 1
+p 2 6 5 1
+p 3 7 6 2
+p 8 7 3 4
+p 5 8 4 1
+p 6 7 8 5
+
+# End of file