Przeglądaj źródła

Added DXF implementation. No support for polymeshes yes, just 3DFACE elements are implemented.
Added strtol64s function, refactored SMDLoader.cpp to use it.

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

aramis_acg 17 lat temu
rodzic
commit
56563016b0
5 zmienionych plików z 373 dodań i 21 usunięć
  1. 290 2
      code/DXFLoader.cpp
  2. 62 2
      code/DXFLoader.h
  3. 6 0
      code/Importer.cpp
  4. 3 17
      code/SMDLoader.cpp
  5. 12 0
      code/fast_atof.h

+ 290 - 2
code/DXFLoader.cpp

@@ -41,6 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /** @file Implementation of the DXF importer class */
 #include "DXFLoader.h"
+#include "ParsingUtils.h"
+#include "fast_atof.h"
+#include "MaterialSystem.h"
 
 // public ASSIMP headers
 #include "../include/aiScene.h"
@@ -59,7 +62,7 @@ using namespace Assimp;
 // Constructor to be privately used by Importer
 DXFImporter::DXFImporter()
 {
-		// nothing to do here
+	// nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -85,6 +88,32 @@ bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
 			 extension[2] != 'x' && extension[2] != 'X' ||
 			 extension[3] != 'f' && extension[3] != 'F');
 }
+
+// ------------------------------------------------------------------------------------------------
+bool DXFImporter::GetNextLine()
+{
+	if(!SkipLine(buffer,&buffer))return false;
+	if(!SkipSpaces(buffer,&buffer))return GetNextLine();
+	return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+bool DXFImporter::GetNextToken()
+{
+	SkipSpaces(buffer,&buffer);
+	groupCode = strtol10s(buffer,&buffer);
+	if(!GetNextLine())return false;
+	
+	// copy the data line to a separate buffer
+	char* m = cursor;
+	while (!IsLineEnd ( *buffer ) && m < (cursor+sizeof(cursor)/sizeof(char)))
+		*m++ = *buffer++;
+	
+	*m = '\0';
+	GetNextLine(); 
+	return true;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure. 
 void DXFImporter::InternReadFile( const std::string& pFile, 
@@ -96,5 +125,264 @@ void DXFImporter::InternReadFile( const std::string& pFile,
 	if( file.get() == NULL)
 		throw new ImportErrorException( "Failed to open DXF file " + pFile + "");
 
-	throw new ImportErrorException("DXF: not yet implemented");
+	// read the contents of the file in a buffer
+	unsigned int m = (unsigned int)file->FileSize();
+	std::vector<char> buffer2(m+1);
+	buffer = &buffer2[0];
+	file->Read( &buffer2[0], m,1);
+	buffer2[m] = '\0';
+
+	mDefaultLayer = NULL;
+
+	// now get all lines of the file
+	while (GetNextToken())
+	{
+		if (2 == groupCode)
+		{
+			// ENTITIES section
+			if (!::strcmp(cursor,"ENTITIES"))
+				if (!ParseEntities())break;
+
+			// HEADER section - just to print the file format version
+			else if (!::strcmp(cursor,"HEADER"))
+				if (!ParseHeader())break;
+
+			// other sections such as BLOCK - skip them to make
+			// sure there will be no name conflicts
+			else
+			{
+				bool b = false;
+				while (GetNextToken())
+				{
+					if (!groupCode && !::strcmp(cursor,"ENDSEC"))
+						{b = true;break;}
+				}
+				if (!b)break;
+			}
+		}
+		// print comment strings
+		else if (999 == groupCode)
+		{
+			DefaultLogger::get()->info(std::string( cursor ));
+		}
+		else if (!groupCode && !::strcmp(cursor,"EOF"))
+			break;
+	}
+
+	if (mLayers.empty())
+		throw new ImportErrorException("DXF: this file contains no 3d data");
+
+	pScene->mMeshes = new aiMesh*[pScene->mNumMeshes = (unsigned int)mLayers.size()];
+	m = 0;
+	for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end();
+		it != end;++it)
+	{
+		// generate the output mesh
+		aiMesh* pMesh = pScene->mMeshes[m++] = new aiMesh();
+		const std::vector<aiVector3D>& vPositions = (*it).vPositions;
+
+		pMesh->mNumFaces = (unsigned int)vPositions.size() / 4u;
+		pMesh->mFaces = new aiFace[pMesh->mNumFaces];
+
+		aiVector3D* vpOut = pMesh->mVertices = new aiVector3D[vPositions.size()];
+		const aiVector3D* vp = &vPositions[0];
+
+		for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
+		{
+			aiFace& face = pMesh->mFaces[i];
+
+			// check whether we need four indices here
+			if (vp[3] != vp[2])
+			{
+				face.mNumIndices = 4;
+			}
+			else face.mNumIndices = 3;
+			face.mIndices = new unsigned int[face.mNumIndices];
+
+			for (unsigned int a = 0; a < face.mNumIndices;++a)
+			{
+				*vpOut++ = vp[a];
+				face.mIndices[a] = pMesh->mNumVertices++;
+			}
+			vp += 4;
+		}
+	}
+
+	// generate the output scene graph
+	pScene->mRootNode = new aiNode();
+	pScene->mRootNode->mName.Set("<DXF_ROOT>");
+
+	if (1 == pScene->mNumMeshes)
+	{
+		pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
+		pScene->mRootNode->mMeshes[0] = 0;
+	}
+	else
+	{
+		pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
+		for (m = 0; m < pScene->mRootNode->mNumChildren;++m)
+		{
+			aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
+			p->mName.length = ::strlen( mLayers[m].name );
+			::strcpy(p->mName.data, mLayers[m].name);
+
+			p->mMeshes = new unsigned int[p->mNumMeshes = 1];
+			p->mMeshes[0] = m;
+			p->mParent = pScene->mRootNode;
+		}
+	}
+
+	// generate a default material
+	MaterialHelper* pcMat = new MaterialHelper();
+	aiString s;
+	s.Set(AI_DEFAULT_MATERIAL_NAME);
+	pcMat->AddProperty(&s, AI_MATKEY_NAME);
+
+	aiColor4D clrDiffuse(0.6f,0.6f,0.6f,1.0f);
+	pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
+
+	clrDiffuse = aiColor4D(1.0f,1.0f,1.0f,1.0f);
+	pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
+
+	clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
+	pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
+
+	pScene->mNumMaterials = 1;
+	pScene->mMaterials = new aiMaterial*[1];
+	pScene->mMaterials[0] = pcMat;
+
+	// --- everything destructs automatically ---
+}
+
+// ------------------------------------------------------------------------------------------------
+bool DXFImporter::ParseEntities()
+{
+	while (GetNextToken())
+	{
+		if (!groupCode)
+		{
+			while (true) {
+			if (!::strcmp(cursor,"3DFACE"))
+				if (!Parse3DFace()) return false; else continue;
+			break;
+			};
+			if (!::strcmp(cursor,"ENDSEC"))
+				return true;
+		}
+	}
+	return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+bool DXFImporter::ParseHeader()
+{
+	// --- at the moment we don't need any information from the header
+	while (GetNextToken())
+	{
+		if (!groupCode)
+		{
+			if (!::strcmp(cursor,"ENDSEC"))
+				return true;
+		}
+
+		// print comment strings
+		else if (999 == groupCode)
+		{
+			DefaultLogger::get()->info(std::string( cursor ));
+		}
+	}
+	return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+bool DXFImporter::Parse3DFace()
+{
+	bool ret = false;
+	LayerInfo* out = NULL;
+
+	aiVector3D vip[4]; // -- vectors are initialized to zero
+	while (GetNextToken())
+	{
+		switch (groupCode)
+		{
+		case 0: ret = true;break;
+
+		// 8 specifies the layer
+		case 8:
+			{
+				for (std::vector<LayerInfo>::iterator it = mLayers.begin(),end = mLayers.end();
+					it != end;++it)
+				{
+					if (!::strcmp( (*it).name, cursor ))
+					{
+						out = &(*it);
+						break;
+					}
+				}
+				if (!out)
+				{
+					// we don't have this layer yet
+					mLayers.push_back(LayerInfo());
+					out = &mLayers.back();
+					::strcpy(out->name,cursor);
+				}
+				break;
+			}
+
+		// x position of the first corner
+		case 10: vip[0].x = fast_atof(cursor);break;
+
+		// y position of the first corner
+		case 20: vip[0].y = -fast_atof(cursor);break;
+
+		// z position of the first corner
+		case 30: vip[0].z = fast_atof(cursor);break;
+
+		// x position of the second corner
+		case 11: vip[1].x = fast_atof(cursor);break;
+
+		// y position of the second corner
+		case 21: vip[1].y = -fast_atof(cursor);break;
+
+		// z position of the second corner
+		case 31: vip[1].z = fast_atof(cursor);break;
+
+		// x position of the third corner
+		case 12: vip[2].x = fast_atof(cursor);break;
+
+		// y position of the third corner
+		case 22: vip[2].y = -fast_atof(cursor);break;
+
+		// z position of the third corner
+		case 32: vip[2].z = fast_atof(cursor);break;
+
+		// x position of the fourth corner
+		case 13: vip[3].x = fast_atof(cursor);break;
+
+		// y position of the fourth corner
+		case 23: vip[3].y = -fast_atof(cursor);break;
+
+		// z position of the fourth corner
+		case 33: vip[3].z = fast_atof(cursor);break;
+		};
+		if (ret)break;
+	}
+
+	// use a default layer if necessary
+	if (!out)
+	{
+		if (!mDefaultLayer)
+		{
+			mLayers.push_back(LayerInfo());
+			mDefaultLayer = &mLayers.back();
+		}
+		out = mDefaultLayer;
+	}
+
+	// add the faces to the face list for this layer
+	out->vPositions.push_back(vip[0]);
+	out->vPositions.push_back(vip[1]);
+	out->vPositions.push_back(vip[2]);
+	out->vPositions.push_back(vip[3]);
+	return ret;
 }

+ 62 - 2
code/DXFLoader.h

@@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_DXFLOADER_H_INCLUDED
 #define AI_DXFLOADER_H_INCLUDED
 
+#include <vector>
+
 #include "BaseImporter.h"
 #include "../include/aiTypes.h"
 
@@ -81,11 +83,69 @@ protected:
 
 	// -------------------------------------------------------------------
 	/** Imports the given file into the given scene structure. 
-	* See BaseImporter::InternReadFile() for details
-	*/
+	 * See BaseImporter::InternReadFile() for details
+	 */
 	void InternReadFile( const std::string& pFile, aiScene* pScene, 
 		IOSystem* pIOHandler);
 
+	// -------------------------------------------------------------------
+	/** Get the next line from the file.
+	 *  @return false if the end of the file was reached
+	 */
+	bool GetNextLine();
+
+	// -------------------------------------------------------------------
+	/** Get the next token (group code + data line) from the file.
+	 *  @return false if the end of the file was reached
+	 */
+	bool GetNextToken();
+
+	// -------------------------------------------------------------------
+	/** Parses the ENTITIES section in the file
+	 *  @return false if the end of the file was reached
+	 */
+	bool ParseEntities();
+
+	// -------------------------------------------------------------------
+	/** Parses the HEADER section in the file
+	 *  @return false if the end of the file was reached
+	 */
+	bool ParseHeader();
+
+	// -------------------------------------------------------------------
+	/** Parses a 3DFACE section in the file
+	 *  @return false if the end of the file was reached
+	 */
+	bool Parse3DFace();
+
+private:
+
+	// points to the next section 
+	const char* buffer;
+
+	// specifies the current group code
+	int groupCode;
+
+	// contains the current data line
+	char cursor[4096];
+
+	// describes a single layer in the DXF file
+	struct LayerInfo
+	{
+		LayerInfo()
+		{
+			name[0] = '\0';
+		}
+
+		char name[4096];
+
+		// face buffer - order is x,y,z,w v1,v2,v3 (w is equal to z if unused)
+		std::vector<aiVector3D> vPositions;
+	};
+
+	// list of all loaded layers
+	std::vector<LayerInfo> mLayers;
+	LayerInfo* mDefaultLayer;
 };
 
 } // end of namespace Assimp

+ 6 - 0
code/Importer.cpp

@@ -107,6 +107,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #if (!defined AI_BUILD_NO_LWO_IMPORTER)
 #	include "LWOLoader.h"
 #endif
+#if (!defined AI_BUILD_NO_DXF_IMPORTER)
+#	include "DXFLoader.h"
+#endif
 
 
 // PostProcess-Steps
@@ -222,6 +225,9 @@ Importer::Importer() :
 #if (!defined AI_BUILD_NO_LWO_IMPORTER)
 	mImporter.push_back( new LWOImporter());
 #endif
+#if (!defined AI_BUILD_NO_DXF_IMPORTER)
+	mImporter.push_back( new DXFImporter());
+#endif
 
 	// add an instance of each post processing step here in the order 
 	// of sequence it is executed. steps that are added here are not validated -

+ 3 - 17
code/SMDLoader.cpp

@@ -1061,9 +1061,8 @@ bool SMDImporter::ParseFloat(const char* szCurrent,
 	const char** szCurrentOut, float& out)
 {
 	if(!SkipSpaces(szCurrent,&szCurrent))
-	{
 		return false;
-	}
+
 	*szCurrentOut = fast_atof_move(szCurrent,out);
 	return true;
 }
@@ -1073,9 +1072,8 @@ bool SMDImporter::ParseUnsignedInt(const char* szCurrent,
 	const char** szCurrentOut, uint32_t& out)
 {
 	if(!SkipSpaces(szCurrent,&szCurrent))
-	{
 		return false;
-	}
+
 	out = (uint32_t)strtol10(szCurrent,szCurrentOut);
 	return true;
 }
@@ -1085,21 +1083,9 @@ bool SMDImporter::ParseSignedInt(const char* szCurrent,
 	const char** szCurrentOut, int32_t& out)
 {
 	if(!SkipSpaces(szCurrent,&szCurrent))
-	{
 		return false;
-	}
-	// handle signs
-	bool bInv = false;
-	if ('-' == *szCurrent)
-	{
-		++szCurrent;
-		bInv = true;
-	}
-	else if ('+' == *szCurrent)++szCurrent;
 
-	// parse the integer
-	out = (int32_t)strtol10(szCurrent,szCurrentOut);
-	if (bInv)out = -out;
+	out = (int32_t)strtol10s(szCurrent,szCurrentOut);
 	return true;
 }
 // ------------------------------------------------------------------------------------------------

+ 12 - 0
code/fast_atof.h

@@ -58,6 +58,18 @@ inline unsigned int strtol10( const char* in, const char** out=0)
 	return value;
 }
 
+// ------------------------------------------------------------------------------------
+// signed variant of strtol10
+inline int strtol10s( const char* in, const char** out=0)
+{
+	bool bNeg = false;
+	if ('-' == *in){++in;bNeg = true;}
+	if ('+' == *in)++in;
+	int value = strtol10(in,out);
+	if (bNeg)value = -value;
+	return value;
+}
+
 
 // ------------------------------------------------------------------------------------
 // specal version of the function, providing higher accuracy