- revamp DXF loader. It now correctly distinguishes BLOCKS and ENTITIES and resolves cross references to entities from a block. Support for block-based coordinate-space transformations. Better polymesh handling. Improve error reporting. Refactor loader structure: the class itself is now stateless, reading is done using LineSplitter.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@905 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2011-02-22 19:58:29 +00:00
parent 00238e84e8
commit 4a88e50aa4
5 changed files with 957 additions and 460 deletions

View File

@ -170,6 +170,7 @@ SOURCE_GROUP( Collada FILES
SOURCE_GROUP( DXF FILES SOURCE_GROUP( DXF FILES
DXFLoader.cpp DXFLoader.cpp
DXFLoader.h DXFLoader.h
DXFHelper.h
) )
SOURCE_GROUP( CSM FILES SOURCE_GROUP( CSM FILES
@ -493,6 +494,7 @@ ADD_LIBRARY( assimp SHARED
ConvertToLHProcess.h ConvertToLHProcess.h
DXFLoader.cpp DXFLoader.cpp
DXFLoader.h DXFLoader.h
DXFHelper.h
CSMLoader.cpp CSMLoader.cpp
CSMLoader.h CSMLoader.h
DefaultIOStream.cpp DefaultIOStream.cpp

230
code/DXFHelper.h 100644
View File

@ -0,0 +1,230 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file DXFHelper.h
* @brief Internal utilities for the DXF loader.
*/
#ifndef INCLUDED_DXFHELPER_H
#define INCLUDED_DXFHELPER_H
#include "LineSplitter.h"
#include "TinyFormatter.h"
#include "StreamReader.h"
namespace Assimp {
namespace DXF {
// read pairs of lines, parse group code and value and provide utilities
// to convert the data to the target data type.
class LineReader
{
public:
LineReader(StreamReaderLE& reader)
// do NOT skip empty lines. In DXF files, they count as valid data.
: splitter(reader,false,true)
, end()
{
}
public:
// -----------------------------------------
bool Is(int gc, const char* what) const {
return groupcode == gc && !strcmp(what,value.c_str());
}
// -----------------------------------------
bool Is(int gc) const {
return groupcode == gc;
}
// -----------------------------------------
int GroupCode() const {
return groupcode;
}
// -----------------------------------------
const std::string& Value() const {
return value;
}
// -----------------------------------------
bool End() const {
return !((bool)*this);
}
public:
// -----------------------------------------
unsigned int ValueAsUnsignedInt() const {
return strtol10(value.c_str());
}
// -----------------------------------------
int ValueAsSignedInt() const {
return strtol10s(value.c_str());
}
// -----------------------------------------
float ValueAsFloat() const {
return fast_atof(value.c_str());
}
public:
// -----------------------------------------
/** pseudo-iterator increment to advance to the next (groupcode/value) pair */
LineReader& operator++() {
if (end) {
if (end == 1) {
++end;
}
return *this;
}
try {
groupcode = strtol10s(splitter->c_str());
splitter++;
value = *splitter;
splitter++;
// automatically skip over {} meta blocks (these are for application use
// and currently not relevant for Assimp).
if (value.length() && value[0] == '{') {
size_t cnt = 0;
for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
splitter++;
DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
}
} catch(std::logic_error&) {
ai_assert(!splitter);
}
if (!splitter) {
end = 1;
}
return *this;
}
// -----------------------------------------
LineReader& operator++(int) {
return ++(*this);
}
// -----------------------------------------
operator bool() const {
return end <= 1;
}
private:
LineSplitter splitter;
int groupcode;
std::string value;
int end;
};
// represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed.
struct PolyLine
{
PolyLine()
: flags()
{}
std::vector<aiVector3D> positions;
std::vector<aiColor4D> colors;
std::vector<unsigned int> indices;
std::vector<unsigned int> counts;
unsigned int flags;
std::string layer;
std::string desc;
};
// reference to a BLOCK. Specifies its own coordinate system.
struct InsertBlock
{
InsertBlock()
: scale(1.f,1.f,1.f)
, angle()
{}
aiVector3D pos;
aiVector3D scale;
float angle;
std::string name;
};
// keeps track of all geometry in a single BLOCK.
struct Block
{
std::vector< boost::shared_ptr<PolyLine> > lines;
std::vector<InsertBlock> insertions;
std::string name;
aiVector3D base;
};
struct FileData
{
// note: the LAST block always contains the stuff from ENTITIES.
std::vector<Block> blocks;
};
}}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -47,9 +47,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
namespace Assimp { namespace Assimp {
namespace DXF {
class LineReader;
struct FileData;
struct PolyLine;
struct Block;
struct InsertBlock;
typedef std::map<std::string, const DXF::Block*> BlockMap;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** DXF importer class /** DXF importer implementation.
*
*/ */
class DXFImporter : public BaseImporter class DXFImporter : public BaseImporter
{ {
@ -63,25 +75,6 @@ protected:
~DXFImporter(); ~DXFImporter();
// describes a single layer in the DXF file
struct LayerInfo
{
LayerInfo()
{
name[0] = '\0';
}
char name[4096];
// face buffer - order is x,y,z v1,v2,v3,v4
// if v2 = v3: line
// elsif v3 = v2: triangle
// else: polygon
std::vector<aiVector3D> vPositions;
std::vector<aiColor4D> vColors;
};
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -94,89 +87,68 @@ protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called by Importer::GetExtensionList() for each loaded importer. /** Called by Importer::GetExtensionList() for each loaded importer.
* See BaseImporter::GetExtensionList() for details * See BaseImporter::GetExtensionList() for details*/
*/
void GetExtensionList(std::set<std::string>& extensions); void GetExtensionList(std::set<std::string>& extensions);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. /** 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,
void InternReadFile( const std::string& pFile, aiScene* pScene, 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 a 3DFACE section in the file
* @return false if the end of the file was reached
*/
bool Parse3DFace();
// -------------------------------------------------------------------
/** Parses a POLYLINE section in the file
* @return false if the end of the file was reached
*/
bool ParsePolyLine();
// -------------------------------------------------------------------
/** Sets the current layer - cursor must point to the name of it.
* @param out Receives a handle to the layer
*/
void SetLayer(LayerInfo*& out);
// -------------------------------------------------------------------
/** Creates a default layer.
* @param out Receives a handle to the default layer
*/
void SetDefaultLayer(LayerInfo*& out);
// -------------------------------------------------------------------
/** Parses a VERTEX element in a POLYLINE/POLYFACE
* @param out Receives the output vertex.
* @param clr Receives the output vertex color - won't be modified
* if it is not existing.
* @param outIdx Receives the output vertex indices, if present.
* Wont't be modified otherwise. Size must be at least 4.
* @return false if the end of the file was reached
*/
bool ParsePolyLineVertex(aiVector3D& out, aiColor4D& clr,
unsigned int* outIdx);
private: private:
// points to the next section // -----------------------------------------------------
const char* buffer; void SkipSection(DXF::LineReader& reader);
// specifies the current group code // -----------------------------------------------------
int groupCode; void ParseHeader(DXF::LineReader& reader,
DXF::FileData& output);
// contains the current data line // -----------------------------------------------------
char cursor[4096]; void ParseEntities(DXF::LineReader& reader,
DXF::FileData& output);
// specifies whether the next call to GetNextToken() // -----------------------------------------------------
// should return the current token a second time void ParseBlocks(DXF::LineReader& reader,
bool bRepeat; DXF::FileData& output);
// list of all loaded layers // -----------------------------------------------------
std::vector<LayerInfo> mLayers; void ParseBlock(DXF::LineReader& reader,
LayerInfo* mDefaultLayer; DXF::FileData& output);
// -----------------------------------------------------
void ParseInsertion(DXF::LineReader& reader,
DXF::FileData& output);
// -----------------------------------------------------
void ParsePolyLine(DXF::LineReader& reader,
DXF::FileData& output);
// -----------------------------------------------------
void ParsePolyLineVertex(DXF::LineReader& reader,
DXF::PolyLine& line);
// -----------------------------------------------------
void Parse3DFace(DXF::LineReader& reader,
DXF::FileData& output);
// -----------------------------------------------------
void ConvertMeshes(aiScene* pScene,
DXF::FileData& output);
// -----------------------------------------------------
void GenerateHierarchy(aiScene* pScene,
DXF::FileData& output);
// -----------------------------------------------------
void GenerateMaterials(aiScene* pScene,
DXF::FileData& output);
// -----------------------------------------------------
void ExpandBlockReferences(DXF::Block& bl,
const DXF::BlockMap& blocks_by_name);
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -79,10 +79,14 @@ public:
public: public:
// ----------------------------------------- // -----------------------------------------
/** construct from existing stream reader */ /** construct from existing stream reader
LineSplitter(StreamReaderLE& stream) note: trim is *always* assumed true if skyp_empty_lines==true
*/
LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true)
: stream(stream) : stream(stream)
, swallow() , swallow()
, skip_empty_lines(skip_empty_lines)
, trim(trim)
{ {
cur.reserve(1024); cur.reserve(1024);
operator++(); operator++();
@ -106,14 +110,30 @@ public:
char s; char s;
cur.clear(); // I will kill you if you deallocate. cur.clear();
while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) { while(stream.GetRemainingSize() && (s = stream.GetI1(),1)) {
if (s == '\n' || s == '\r') { if (s == '\n' || s == '\r') {
if (skip_empty_lines) {
while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n')); while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n'));
if (stream.GetRemainingSize()) { if (stream.GetRemainingSize()) {
stream.IncPtr(-1); stream.IncPtr(-1);
} }
break; }
else {
// skip both potential line terminators but don't read past this line.
if (stream.GetRemainingSize() && (s == '\r' && stream.GetI1() != '\n')) {
stream.IncPtr(-1);
}
if (trim) {
while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ') || s == '\t');
if (stream.GetRemainingSize()) {
stream.IncPtr(-1);
}
}
}
break;
} }
cur += s; cur += s;
} }
@ -122,6 +142,11 @@ public:
return *this; return *this;
} }
// -----------------------------------------
LineSplitter& operator++(int) {
return ++(*this);
}
// ----------------------------------------- // -----------------------------------------
/** get a pointer to the beginning of a particular token */ /** get a pointer to the beginning of a particular token */
const char* operator[] (size_t idx) const { const char* operator[] (size_t idx) const {
@ -210,7 +235,7 @@ private:
line_idx idx; line_idx idx;
std::string cur; std::string cur;
StreamReaderLE& stream; StreamReaderLE& stream;
bool swallow; bool swallow, skip_empty_lines, trim;
}; };
} }