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
pull/1/head
aramis_acg 2008-09-05 13:21:01 +00:00
parent ad4cc033d8
commit 56563016b0
5 changed files with 373 additions and 21 deletions

View File

@ -41,6 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the DXF importer class */ /** @file Implementation of the DXF importer class */
#include "DXFLoader.h" #include "DXFLoader.h"
#include "ParsingUtils.h"
#include "fast_atof.h"
#include "MaterialSystem.h"
// public ASSIMP headers // public ASSIMP headers
#include "../include/aiScene.h" #include "../include/aiScene.h"
@ -85,6 +88,32 @@ bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
extension[2] != 'x' && extension[2] != 'X' || extension[2] != 'x' && extension[2] != 'X' ||
extension[3] != 'f' && extension[3] != 'F'); 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. // Imports the given file into the given scene structure.
void DXFImporter::InternReadFile( const std::string& pFile, void DXFImporter::InternReadFile( const std::string& pFile,
@ -96,5 +125,264 @@ void DXFImporter::InternReadFile( const std::string& pFile,
if( file.get() == NULL) if( file.get() == NULL)
throw new ImportErrorException( "Failed to open DXF file " + pFile + ""); 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;
} }

View File

@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_DXFLOADER_H_INCLUDED #ifndef AI_DXFLOADER_H_INCLUDED
#define AI_DXFLOADER_H_INCLUDED #define AI_DXFLOADER_H_INCLUDED
#include <vector>
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/aiTypes.h" #include "../include/aiTypes.h"
@ -86,6 +88,64 @@ protected:
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); 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 } // end of namespace Assimp

View File

@ -107,6 +107,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if (!defined AI_BUILD_NO_LWO_IMPORTER) #if (!defined AI_BUILD_NO_LWO_IMPORTER)
# include "LWOLoader.h" # include "LWOLoader.h"
#endif #endif
#if (!defined AI_BUILD_NO_DXF_IMPORTER)
# include "DXFLoader.h"
#endif
// PostProcess-Steps // PostProcess-Steps
@ -222,6 +225,9 @@ Importer::Importer() :
#if (!defined AI_BUILD_NO_LWO_IMPORTER) #if (!defined AI_BUILD_NO_LWO_IMPORTER)
mImporter.push_back( new LWOImporter()); mImporter.push_back( new LWOImporter());
#endif #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 // 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 - // of sequence it is executed. steps that are added here are not validated -

View File

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

View File

@ -58,6 +58,18 @@ inline unsigned int strtol10( const char* in, const char** out=0)
return value; 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 // specal version of the function, providing higher accuracy