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-9d2fd5bffc1fpull/1/head
parent
ad4cc033d8
commit
56563016b0
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 -
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue