Bläddra i källkod

- Feature : First buggy prototype of the M3-loader for starcraft models.
- Bugfix : Fix some typo's in the obj-loader.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1085 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

kimmi 14 år sedan
förälder
incheckning
ab71ca60c3
4 ändrade filer med 297 tillägg och 28 borttagningar
  1. 6 0
      code/ImporterRegistry.cpp
  2. 260 1
      code/M3Importer.cpp
  3. 26 23
      code/M3Importer.h
  4. 5 4
      code/ObjFileParser.cpp

+ 6 - 0
code/ImporterRegistry.cpp

@@ -160,6 +160,9 @@ corresponding preprocessor flag to selectively disable formats.
 #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER
 #	include "IFCLoader.h"
 #endif
+#ifndef ASSIMP_BUILD_NO_M3_IMPORTER
+#   include "M3Importer.h"
+#endif 
 
 namespace Assimp {
 
@@ -279,6 +282,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
 #if (!defined ASSIMP_BUILD_NO_IFC_IMPORTER)
 	out.push_back( new IFCImporter() );
 #endif
+#if ( !defined ASSIMP_BUILD_NO_M3_IMPORTER )
+	out.push_back( new M3::M3Importer() );
+#endif
 }
 
 }

+ 260 - 1
code/M3Importer.cpp

@@ -39,7 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include "AssimpPCH.h"
+#ifndef ASSIMP_BUILD_NO_M3_IMPORTER
+
 #include "M3Importer.h"
+#include <sstream>
 
 namespace Assimp {
 namespace M3 {
@@ -76,16 +79,272 @@ bool M3Importer::CanRead( const std::string &rFile, IOSystem* /*pIOHandler*/, bo
 // ------------------------------------------------------------------------------------------------
 void M3Importer::GetExtensionList(std::set<std::string>& extensions)
 {
-
+	extensions.insert("m3");
 }
 
 // ------------------------------------------------------------------------------------------------
 void M3Importer::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
 {
+	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 + ".");
+
+	// Get the file-size and validate it, throwing an exception when it fails
+	size_t filesize = file->FileSize();
+	if( filesize  < 1 )
+		throw DeadlyImportError( "M3-file is too small.");
+
+	m_Buffer.resize( filesize );
+	size_t readsize = file->Read( &m_Buffer[ 0 ], sizeof( unsigned char ), filesize );
+	ai_assert( readsize == filesize );
+
+	m_pHead = (MD33*)( &m_Buffer[ 0 ] );
+	m_pRefs = (ReferenceEntry*)( &m_Buffer[ 0 ] + m_pHead->ofsRefs );
+
+	MODL20* pMODL20( NULL );
+	MODL23* pMODL23( NULL );
+
+	VertexExt* pVerts1( NULL );
+	Vertex* pVerts2( NULL );
+
+	DIV *pViews( NULL );
+	Region* regions( NULL );
+	uint16* faces( NULL );
+
+	uint32 nVertices = 0;
+	uint32 nFaces = 0;
+
+	bool ok = true;
+	switch( m_pRefs[ m_pHead->MODL.ref ].type )
+	{
+	case 20:
+		pMODL20 = GetEntries<MODL20>( m_pHead->MODL );
+		if ( ( pMODL20->flags & 0x20000) != 0 ) // Has vertices
+		{
+			if( (pMODL20->flags & 0x40000) != 0 ) // Has extra 4 byte
+			{
+				pVerts1 = GetEntries<VertexExt>( pMODL20->vertexData );
+				nVertices = pMODL20->vertexData.nEntries/sizeof(VertexExt);
+			}
+			else
+			{
+				pVerts2 = GetEntries<Vertex>(pMODL20->vertexData);
+				nVertices = pMODL20->vertexData.nEntries/sizeof(Vertex);
+			}
+		}
+		pViews = GetEntries<DIV>( pMODL20->views );
+		break;
+
+	case 23:
+		pMODL23 = GetEntries<MODL23>(m_pHead->MODL );
+		if( (pMODL23->flags & 0x20000) != 0 ) // Has vertices
+		{
+			if( (pMODL23->flags & 0x40000) != 0 ) // Has extra 4 byte
+			{
+				pVerts1 = GetEntries<VertexExt>(pMODL23->vertexData);
+				nVertices = pMODL23->vertexData.nEntries/sizeof(VertexExt);
+			}
+			else
+			{
+				pVerts2 = GetEntries<Vertex>(pMODL23->vertexData);
+				nVertices = pMODL23->vertexData.nEntries/sizeof(Vertex);
+			}
+		}
+		pViews = GetEntries<DIV>( pMODL23->views );
+		break;
+
+	default:
+		ok = false;
+		return;
+	}
+
+	// Get all region data
+	regions = GetEntries<Region>( pViews->regions );
+	
+	// Get the face data
+	faces = GetEntries<uint16>( pViews->faces );
+	nFaces = pViews->faces.nEntries;
+
+	// Everything ok, if not throw an exception
+	if ( !ok )
+		throw DeadlyImportError( "Failed to open file " + pFile + ".");
+
+	// Convert the vertices
+	std::vector<aiVector3D> vertices;
+	vertices.resize( nVertices );
+	unsigned int offset = 0;
+	for ( unsigned int i = 0; i < nVertices; i++ )
+	{
+		if ( pVerts1 )
+		{
+			vertices[ offset ].Set( pVerts1[i].pos.x, pVerts1[i].pos.y, pVerts1[i].pos.z );
+			offset++;
+		}
+
+		if ( pVerts2 )
+		{
+			vertices[ offset ].Set( pVerts2[ i ].pos.x, pVerts2[ i ].pos.y, pVerts2[ i ].pos.z );
+			offset++;
+		}
+	}
+
+	// Compute the normals  
+	std::vector<aiVector3D> normals;
+	normals.resize( nVertices );
+	float w = 0.0f;
+	Vec3D norm;
+	for( unsigned int i = 0; i < nVertices; i++ )
+	{
+		w = 0.0f;
+		if( pVerts1 )
+		{
+			norm.x = (float) 2*pVerts1[ i ].normal[ 0 ]/255.0f - 1;
+			norm.y = (float) 2*pVerts1[ i ].normal[ 1 ]/255.0f - 1;
+			norm.z = (float) 2*pVerts1[ i ].normal[ 2 ]/255.0f - 1;
+			w = (float) pVerts1[ i ].normal[ 3 ]/255.0f;
+		}
+
+		if( pVerts2 )
+		{
+			norm.x = (float) 2*pVerts2[ i ].normal[ 0 ]/255.0f - 1;
+			norm.y = (float) 2*pVerts2[ i ].normal[ 1 ]/255.0f - 1;
+			norm.z = (float) 2*pVerts2[ i ].normal[ 2 ]/255.0f - 1;
+
+			w = (float) pVerts2[ i ].normal[ 3 ] / 255.0f;
+		}
+
+		if ( w )
+		{
+			const float invW = 1.0f / w;
+			norm.x = norm.x * invW;
+			norm.y = norm.y * invW;
+			norm.z = norm.z * invW;
+		}
+
+		normals[ i ].Set( norm.x, norm.y, norm.z );
+	}
+
+	// Convert the data into the assimp specific data structures
+	convertToAssimp( pFile, pScene, pViews, regions, faces, vertices, normals );
+}
+
+// ------------------------------------------------------------------------------------------------
+//
+void M3Importer::convertToAssimp( const std::string& pFile, aiScene* pScene, DIV *pViews, 
+								 Region *pRegions, uint16 *pFaces, 
+								 const std::vector<aiVector3D> &vertices,
+								 const std::vector<aiVector3D> &normals )
+{
+	std::vector<aiMesh*> MeshArray;
+
+	// Create the root node
+	pScene->mRootNode = createNode( NULL );
+	
+	// Set the name of the scene
+	ai_assert( !pFile.empty() );
+	pScene->mRootNode->mName.Set( pFile );
+
+	aiNode *pRootNode = pScene->mRootNode;
+	aiNode *pCurrentNode = NULL;
+
+	// Lets create the nodes
+	pRootNode->mNumChildren = pViews->regions.nEntries;
+	if ( pRootNode->mNumChildren > 0 )
+		pRootNode->mChildren = new aiNode*[ pRootNode->mNumChildren ];
+
+	for ( unsigned int i=0; i<pViews->regions.nEntries; ++i )
+	{
+		// Create a new node
+		pCurrentNode = createNode( pRootNode );
+		std::stringstream stream;
+		stream << "Node_" << i;
+		pCurrentNode->mName.Set( stream.str().c_str() );
+		pRootNode->mChildren[ i ] = pCurrentNode;
+		
+		// Loop over the faces of the nodes
+		unsigned int numFaces = ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ) -  pRegions[ i ].ofsIndices;
+		aiMesh *pMesh = new aiMesh;
+		MeshArray.push_back( pMesh );
+
+		pMesh->mNumFaces = numFaces;
+		pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
+		aiFace *pCurrentFace = NULL;
+		unsigned int faceIdx = 0;
+		for ( unsigned int j = pRegions[ i ].ofsIndices; j < ( pRegions[ i ].ofsIndices + pRegions[ i ].nIndices ); j += 3 )
+		{
+			pCurrentFace = &( pMesh->mFaces[ faceIdx ] );
+			faceIdx++;
+			pCurrentFace->mNumIndices = 3;
+			pCurrentFace->mIndices = new unsigned int[ 3 ];
+			pCurrentFace->mIndices[ 0 ] = pFaces[ j ]+1;
+			pCurrentFace->mIndices[ 1 ] = pFaces[ j+1 ] + 1;
+			pCurrentFace->mIndices[ 2 ] = pFaces[ j+2 ] + 1;
+		}
+
+		// Now we can create the vertex data itself
+		pCurrentNode->mNumMeshes = 1;
+		pCurrentNode->mMeshes = new unsigned int[ 1 ];
+		pCurrentNode->mMeshes[ 0 ] = MeshArray.size() - 1;
+		createVertexData( pMesh, vertices, normals );
+	}
+
+	// Copy the meshes into the scene
+	pScene->mNumMeshes = MeshArray.size();
+	pScene->mMeshes = new aiMesh*[ MeshArray.size() ];
+	unsigned int pos = 0;
+	for ( std::vector<aiMesh*>::iterator it = MeshArray.begin(); it != MeshArray.end(); ++it )
+	{
+		pScene->mMeshes[ pos ] = *it;
+		pos++;
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+//
+void M3Importer::createVertexData( aiMesh *pMesh, const std::vector<aiVector3D> &vertices,
+								  const std::vector<aiVector3D> &normals )
+{
+	unsigned int numIndices = 0;
+
+	pMesh->mNumVertices = pMesh->mNumFaces * 3;
+	pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
+	pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
+	unsigned int pos = 0;
+	for ( unsigned int currentFace = 0; currentFace < pMesh->mNumFaces; currentFace++ )
+	{
+		aiFace *pFace = &( pMesh->mFaces[ currentFace ] );
+		for ( unsigned int currentIdx=0; currentIdx<pFace->mNumIndices; currentIdx++ )
+		{
+			unsigned int idx = pFace->mIndices[ currentIdx ];
+			if ( vertices.size() > idx )
+			{
+				pMesh->mVertices[ pos ] = vertices[ idx ];
+				pMesh->mNormals[ pos ] = normals[ idx ];
 
+				pFace->mIndices[ currentIdx ] = pos;
+				pos++;
+			}
+		}
+	}
+}
+
+// ------------------------------------------------------------------------------------------------
+//
+aiNode *M3Importer::createNode( aiNode *pParent )
+{
+	aiNode *pNode = new aiNode;
+	if ( pParent )
+		pNode->mParent = pParent;
+	else
+		pNode->mParent = NULL;
+
+	return pNode;
 }
 
 // ------------------------------------------------------------------------------------------------
 
 } // Namespace M3
 } // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_M3_IMPORTER

+ 26 - 23
code/M3Importer.h

@@ -278,7 +278,7 @@ void rotate(float x0, float y0, float *x, float *y, float angle)
 
 struct Reference 
 {
-	uint32 nunEntries;	// Code 0x00
+	uint32 nEntries;	// Code 0x00
 	uint32 ref;			// Code 0x04
 };
 
@@ -611,39 +611,39 @@ struct SEQS
 
 struct STC
 {
-	Reference name;	// Code 0x00
-	uint16 s1;	// Code 0x08
-	uint16 s2;	// Code 0x0A
-	uint16 s3;	// Code 0x0C
-	uint16 s4;	// Code 0x0E
-	Reference unk2; // uint32	// Code 0x12
-	Reference unk3; // uint32	// Code 0x1A
-	uint32 d3;	// Code 0x22
-	Reference evt;	// Code 0x24
+	Reference name;		// Code 0x00
+	uint16 s1;			// Code 0x08
+	uint16 s2;			// Code 0x0A
+	uint16 s3;			// Code 0x0C
+	uint16 s4;			// Code 0x0E
+	Reference unk2;		// uint32	// Code 0x12
+	Reference unk3;		// uint32	// Code 0x1A
+	uint32 d3;			// Code 0x22
+	Reference evt;		// Code 0x24
 	Reference unk4[11]; // Seems to be transformation data	// Code 0x2C
-	Reference bnds;	// Code 0x84
+	Reference bnds;		// Code 0x84
 };
 
 struct STS
 {
 	Reference unk1; // uint32	// Code 0x00
 	int32 unk[3];	// Code 0x08
-	int16 s1;	// Code 0x14
-	int16 s2;	// Code 0x16
+	int16 s1;		// Code 0x14
+	int16 s2;		// Code 0x16
 };
 
 struct STG
 {
-	Reference name;	// Code 0x00
+	Reference name;		// Code 0x00
 	Reference stcID;	// Code 0x08
 };
 
 struct SD
 {
 	Reference timeline;	// Code 0x00
-	uint32 flags;	// Code 0x08
-	uint32 length;	// Code 0x0C
-	Reference data;	// Code 0x10
+	uint32 flags;		// Code 0x08
+	uint32 length;		// Code 0x0C
+	Reference data;		// Code 0x10
 };
 
 struct BNDS
@@ -678,25 +678,28 @@ struct QUAT
 /**	Loader to import M3-models.
  */
 // ------------------------------------------------------------------------------------------------
-class M3Importer : BaseImporter
+class M3Importer : public BaseImporter
 {
 	friend class Importer;
 
-protected:
-	///	@brief	Default constructor.
+public:
+	///	@brief	The default constructor.
 	M3Importer();
 
-	///	@brief	Destructor.
+	///	@brief	The destructor.
 	~M3Importer();
 
-public:
 	/// @brief	Returns whether the class can handle the format of the given file. 
 	/// @remark	See BaseImporter::CanRead() for details.
 	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
 
 private:
-	void GetExtensionList(std::set<std::string>& extensions);
+	void GetExtensionList( std::set<std::string>& extensions );
 	void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
+	void convertToAssimp( const std::string& pFile, aiScene* pScene, DIV *pViews, Region *pRegions, uint16 *pFaces, 
+		const std::vector<aiVector3D> &vertices, const std::vector<aiVector3D> &normals );
+	void createVertexData( aiMesh *pMesh, const std::vector<aiVector3D> &vertices, const std::vector<aiVector3D> &normals  );
+	aiNode *createNode( aiNode *pParent );
 	template<typename T>
 	T* GetEntries( Reference ref );
 

+ 5 - 4
code/ObjFileParser.cpp

@@ -336,7 +336,8 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 		pPtr += iStep;
 	}
 
-	if (pIndices->empty()) {
+	if ( pIndices->empty() ) 
+	{
 		DefaultLogger::get()->error("Obj: Ignoring empty face");
 		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 		return;
@@ -350,7 +351,7 @@ void ObjFileParser::getFace(aiPrimitiveType type)
 	else 
 		face->m_pMaterial = m_pModel->m_pDefaultMaterial;
 
-	// Create a default object, if nothing there
+	// Create a default object, if nothing is there
 	if ( NULL == m_pModel->m_pCurrent )
 		createObject( "defaultobject" );
 	
@@ -524,11 +525,11 @@ void ObjFileParser::getGroupName()
 	if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) )
 		return;
 
-	// Store groupname in group library 
+	// Store the group name in the group library 
 	char *pStart = &(*m_DataIt);
 	while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
 		m_DataIt++;
-	std::string strGroupName(pStart, &(*m_DataIt));
+	std::string strGroupName( pStart, &(*m_DataIt) );
 
 	// Change active group, if necessary
 	if ( m_pModel->m_strActiveGroup != strGroupName )