rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file DXFLoader.cpp
|
nuclear@0
|
43 * @brief Implementation of the DXF importer class
|
nuclear@0
|
44 */
|
nuclear@0
|
45
|
nuclear@0
|
46 #include "AssimpPCH.h"
|
nuclear@0
|
47 #ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
|
nuclear@0
|
48
|
nuclear@0
|
49 #include "DXFLoader.h"
|
nuclear@0
|
50 #include "ParsingUtils.h"
|
nuclear@0
|
51 #include "ConvertToLHProcess.h"
|
nuclear@0
|
52 #include "fast_atof.h"
|
nuclear@0
|
53
|
nuclear@0
|
54 #include "DXFHelper.h"
|
nuclear@0
|
55
|
nuclear@0
|
56 using namespace Assimp;
|
nuclear@0
|
57
|
nuclear@0
|
58 // AutoCAD Binary DXF<CR><LF><SUB><NULL>
|
nuclear@0
|
59 #define AI_DXF_BINARY_IDENT ("AutoCAD Binary DXF\r\n\x1a\0")
|
nuclear@0
|
60 #define AI_DXF_BINARY_IDENT_LEN (24)
|
nuclear@0
|
61
|
nuclear@0
|
62 // default vertex color that all uncolored vertices will receive
|
nuclear@0
|
63 #define AI_DXF_DEFAULT_COLOR aiColor4D(0.6f,0.6f,0.6f,0.6f)
|
nuclear@0
|
64
|
nuclear@0
|
65 // color indices for DXF - 16 are supported, the table is
|
nuclear@0
|
66 // taken directly from the DXF spec.
|
nuclear@0
|
67 static aiColor4D g_aclrDxfIndexColors[] =
|
nuclear@0
|
68 {
|
nuclear@0
|
69 aiColor4D (0.6f, 0.6f, 0.6f, 1.0f),
|
nuclear@0
|
70 aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red
|
nuclear@0
|
71 aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green
|
nuclear@0
|
72 aiColor4D (0.0f, 0.0f, 1.0f, 1.0f), // blue
|
nuclear@0
|
73 aiColor4D (0.3f, 1.0f, 0.3f, 1.0f), // light green
|
nuclear@0
|
74 aiColor4D (0.3f, 0.3f, 1.0f, 1.0f), // light blue
|
nuclear@0
|
75 aiColor4D (1.0f, 0.3f, 0.3f, 1.0f), // light red
|
nuclear@0
|
76 aiColor4D (1.0f, 0.0f, 1.0f, 1.0f), // pink
|
nuclear@0
|
77 aiColor4D (1.0f, 0.6f, 0.0f, 1.0f), // orange
|
nuclear@0
|
78 aiColor4D (0.6f, 0.3f, 0.0f, 1.0f), // dark orange
|
nuclear@0
|
79 aiColor4D (1.0f, 1.0f, 0.0f, 1.0f), // yellow
|
nuclear@0
|
80 aiColor4D (0.3f, 0.3f, 0.3f, 1.0f), // dark gray
|
nuclear@0
|
81 aiColor4D (0.8f, 0.8f, 0.8f, 1.0f), // light gray
|
nuclear@0
|
82 aiColor4D (0.0f, 00.f, 0.0f, 1.0f), // black
|
nuclear@0
|
83 aiColor4D (1.0f, 1.0f, 1.0f, 1.0f), // white
|
nuclear@0
|
84 aiColor4D (0.6f, 0.0f, 1.0f, 1.0f) // violet
|
nuclear@0
|
85 };
|
nuclear@0
|
86 #define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0]))
|
nuclear@0
|
87 #define AI_DXF_ENTITIES_MAGIC_BLOCK "$ASSIMP_ENTITIES_MAGIC"
|
nuclear@0
|
88
|
nuclear@0
|
89
|
nuclear@0
|
90 static const aiImporterDesc desc = {
|
nuclear@0
|
91 "Drawing Interchange Format (DXF) Importer",
|
nuclear@0
|
92 "",
|
nuclear@0
|
93 "",
|
nuclear@0
|
94 "",
|
nuclear@0
|
95 aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport,
|
nuclear@0
|
96 0,
|
nuclear@0
|
97 0,
|
nuclear@0
|
98 0,
|
nuclear@0
|
99 0,
|
nuclear@0
|
100 "dxf"
|
nuclear@0
|
101 };
|
nuclear@0
|
102
|
nuclear@0
|
103 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
104 // Constructor to be privately used by Importer
|
nuclear@0
|
105 DXFImporter::DXFImporter()
|
nuclear@0
|
106 {}
|
nuclear@0
|
107
|
nuclear@0
|
108 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
109 // Destructor, private as well
|
nuclear@0
|
110 DXFImporter::~DXFImporter()
|
nuclear@0
|
111 {}
|
nuclear@0
|
112
|
nuclear@0
|
113 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
114 // Returns whether the class can handle the format of the given file.
|
nuclear@0
|
115 bool DXFImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
|
nuclear@0
|
116 {
|
nuclear@0
|
117 return SimpleExtensionCheck(pFile,"dxf");
|
nuclear@0
|
118 }
|
nuclear@0
|
119
|
nuclear@0
|
120 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
121 // Get a list of all supported file extensions
|
nuclear@0
|
122 const aiImporterDesc* DXFImporter::GetInfo () const
|
nuclear@0
|
123 {
|
nuclear@0
|
124 return &desc;
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
128 // Imports the given file into the given scene structure.
|
nuclear@0
|
129 void DXFImporter::InternReadFile( const std::string& pFile,
|
nuclear@0
|
130 aiScene* pScene,
|
nuclear@0
|
131 IOSystem* pIOHandler)
|
nuclear@0
|
132 {
|
nuclear@0
|
133 boost::shared_ptr<IOStream> file = boost::shared_ptr<IOStream>( pIOHandler->Open( pFile) );
|
nuclear@0
|
134
|
nuclear@0
|
135 // Check whether we can read the file
|
nuclear@0
|
136 if( file.get() == NULL) {
|
nuclear@0
|
137 throw DeadlyImportError( "Failed to open DXF file " + pFile + "");
|
nuclear@0
|
138 }
|
nuclear@0
|
139
|
nuclear@0
|
140 // check whether this is a binaray DXF file - we can't read binary DXF files :-(
|
nuclear@0
|
141 char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0};
|
nuclear@0
|
142 file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1);
|
nuclear@0
|
143
|
nuclear@0
|
144 if (!strncmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) {
|
nuclear@0
|
145 throw DeadlyImportError("DXF: Binary files are not supported at the moment");
|
nuclear@0
|
146 }
|
nuclear@0
|
147
|
nuclear@0
|
148 // DXF files can grow very large, so read them via the StreamReader,
|
nuclear@0
|
149 // which will choose a suitable strategy.
|
nuclear@0
|
150 file->Seek(0,aiOrigin_SET);
|
nuclear@0
|
151 StreamReaderLE stream( file );
|
nuclear@0
|
152
|
nuclear@0
|
153 DXF::LineReader reader (stream);
|
nuclear@0
|
154 DXF::FileData output;
|
nuclear@0
|
155
|
nuclear@0
|
156 // now get all lines of the file and process top-level sections
|
nuclear@0
|
157 bool eof = false;
|
nuclear@0
|
158 while(!reader.End()) {
|
nuclear@0
|
159
|
nuclear@0
|
160 // blocks table - these 'build blocks' are later (in ENTITIES)
|
nuclear@0
|
161 // referenced an included via INSERT statements.
|
nuclear@0
|
162 if (reader.Is(2,"BLOCKS")) {
|
nuclear@0
|
163 ParseBlocks(reader,output);
|
nuclear@0
|
164 continue;
|
nuclear@0
|
165 }
|
nuclear@0
|
166
|
nuclear@0
|
167 // primary entity table
|
nuclear@0
|
168 if (reader.Is(2,"ENTITIES")) {
|
nuclear@0
|
169 ParseEntities(reader,output);
|
nuclear@0
|
170 continue;
|
nuclear@0
|
171 }
|
nuclear@0
|
172
|
nuclear@0
|
173 // skip unneeded sections entirely to avoid any problems with them
|
nuclear@0
|
174 // alltogether.
|
nuclear@0
|
175 else if (reader.Is(2,"CLASSES") || reader.Is(2,"TABLES")) {
|
nuclear@0
|
176 SkipSection(reader);
|
nuclear@0
|
177 continue;
|
nuclear@0
|
178 }
|
nuclear@0
|
179
|
nuclear@0
|
180 else if (reader.Is(2,"HEADER")) {
|
nuclear@0
|
181 ParseHeader(reader,output);
|
nuclear@0
|
182 continue;
|
nuclear@0
|
183 }
|
nuclear@0
|
184
|
nuclear@0
|
185 // comments
|
nuclear@0
|
186 else if (reader.Is(999)) {
|
nuclear@0
|
187 DefaultLogger::get()->info("DXF Comment: " + reader.Value());
|
nuclear@0
|
188 }
|
nuclear@0
|
189
|
nuclear@0
|
190 // don't read past the official EOF sign
|
nuclear@0
|
191 else if (reader.Is(0,"EOF")) {
|
nuclear@0
|
192 eof = true;
|
nuclear@0
|
193 break;
|
nuclear@0
|
194 }
|
nuclear@0
|
195
|
nuclear@0
|
196 ++reader;
|
nuclear@0
|
197 }
|
nuclear@0
|
198 if (!eof) {
|
nuclear@0
|
199 DefaultLogger::get()->warn("DXF: EOF reached, but did not encounter DXF EOF marker");
|
nuclear@0
|
200 }
|
nuclear@0
|
201
|
nuclear@0
|
202 ConvertMeshes(pScene,output);
|
nuclear@0
|
203
|
nuclear@0
|
204 // Now rotate the whole scene by 90 degrees around the x axis to convert from AutoCAD's to Assimp's coordinate system
|
nuclear@0
|
205 pScene->mRootNode->mTransformation = aiMatrix4x4(
|
nuclear@0
|
206 1.f,0.f,0.f,0.f,
|
nuclear@0
|
207 0.f,0.f,1.f,0.f,
|
nuclear@0
|
208 0.f,-1.f,0.f,0.f,
|
nuclear@0
|
209 0.f,0.f,0.f,1.f) * pScene->mRootNode->mTransformation;
|
nuclear@0
|
210 }
|
nuclear@0
|
211
|
nuclear@0
|
212 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
213 void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
|
nuclear@0
|
214 {
|
nuclear@0
|
215 // the process of resolving all the INSERT statements can grow the
|
nuclear@0
|
216 // polycount excessively, so log the original number.
|
nuclear@0
|
217 // XXX Option to import blocks as separate nodes?
|
nuclear@0
|
218 if (!DefaultLogger::isNullLogger()) {
|
nuclear@0
|
219
|
nuclear@0
|
220 unsigned int vcount = 0, icount = 0;
|
nuclear@0
|
221 BOOST_FOREACH (const DXF::Block& bl, output.blocks) {
|
nuclear@0
|
222 BOOST_FOREACH (boost::shared_ptr<const DXF::PolyLine> pl, bl.lines) {
|
nuclear@0
|
223 vcount += pl->positions.size();
|
nuclear@0
|
224 icount += pl->counts.size();
|
nuclear@0
|
225 }
|
nuclear@0
|
226 }
|
nuclear@0
|
227
|
nuclear@0
|
228 DefaultLogger::get()->debug((Formatter::format("DXF: Unexpanded polycount is "),
|
nuclear@0
|
229 icount,", vertex count is ",vcount
|
nuclear@0
|
230 ));
|
nuclear@0
|
231 }
|
nuclear@0
|
232
|
nuclear@0
|
233 if (! output.blocks.size() ) {
|
nuclear@0
|
234 throw DeadlyImportError("DXF: no data blocks loaded");
|
nuclear@0
|
235 }
|
nuclear@0
|
236
|
nuclear@0
|
237 DXF::Block* entities = 0;
|
nuclear@0
|
238
|
nuclear@0
|
239 // index blocks by name
|
nuclear@0
|
240 DXF::BlockMap blocks_by_name;
|
nuclear@0
|
241 BOOST_FOREACH (DXF::Block& bl, output.blocks) {
|
nuclear@0
|
242 blocks_by_name[bl.name] = &bl;
|
nuclear@0
|
243 if ( !entities && bl.name == AI_DXF_ENTITIES_MAGIC_BLOCK ) {
|
nuclear@0
|
244 entities = &bl;
|
nuclear@0
|
245 }
|
nuclear@0
|
246 }
|
nuclear@0
|
247
|
nuclear@0
|
248 if (!entities) {
|
nuclear@0
|
249 throw DeadlyImportError("DXF: no ENTITIES data block loaded");
|
nuclear@0
|
250 }
|
nuclear@0
|
251
|
nuclear@0
|
252 typedef std::map<std::string, unsigned int> LayerMap;
|
nuclear@0
|
253
|
nuclear@0
|
254 LayerMap layers;
|
nuclear@0
|
255 std::vector< std::vector< const DXF::PolyLine*> > corr;
|
nuclear@0
|
256
|
nuclear@0
|
257 // now expand all block references in the primary ENTITIES block
|
nuclear@0
|
258 // XXX this involves heavy memory copying, consider a faster solution for future versions.
|
nuclear@0
|
259 ExpandBlockReferences(*entities,blocks_by_name);
|
nuclear@0
|
260
|
nuclear@0
|
261 unsigned int cur = 0;
|
nuclear@0
|
262 BOOST_FOREACH (boost::shared_ptr<const DXF::PolyLine> pl, entities->lines) {
|
nuclear@0
|
263 if (pl->positions.size()) {
|
nuclear@0
|
264
|
nuclear@0
|
265 std::map<std::string, unsigned int>::iterator it = layers.find(pl->layer);
|
nuclear@0
|
266 if (it == layers.end()) {
|
nuclear@0
|
267 ++pScene->mNumMeshes;
|
nuclear@0
|
268
|
nuclear@0
|
269 layers[pl->layer] = cur++;
|
nuclear@0
|
270
|
nuclear@0
|
271 std::vector< const DXF::PolyLine* > pv;
|
nuclear@0
|
272 pv.push_back(&*pl);
|
nuclear@0
|
273
|
nuclear@0
|
274 corr.push_back(pv);
|
nuclear@0
|
275 }
|
nuclear@0
|
276 else {
|
nuclear@0
|
277 corr[(*it).second].push_back(&*pl);
|
nuclear@0
|
278 }
|
nuclear@0
|
279 }
|
nuclear@0
|
280 }
|
nuclear@0
|
281
|
nuclear@0
|
282 if (!pScene->mNumMeshes) {
|
nuclear@0
|
283 throw DeadlyImportError("DXF: this file contains no 3d data");
|
nuclear@0
|
284 }
|
nuclear@0
|
285
|
nuclear@0
|
286 pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ] ();
|
nuclear@0
|
287
|
nuclear@0
|
288 BOOST_FOREACH(const LayerMap::value_type& elem, layers){
|
nuclear@0
|
289 aiMesh* const mesh = pScene->mMeshes[elem.second] = new aiMesh();
|
nuclear@0
|
290 mesh->mName.Set(elem.first);
|
nuclear@0
|
291
|
nuclear@0
|
292 unsigned int cvert = 0,cface = 0;
|
nuclear@0
|
293 BOOST_FOREACH(const DXF::PolyLine* pl, corr[elem.second]){
|
nuclear@0
|
294 // sum over all faces since we need to 'verbosify' them.
|
nuclear@0
|
295 cvert += std::accumulate(pl->counts.begin(),pl->counts.end(),0);
|
nuclear@0
|
296 cface += pl->counts.size();
|
nuclear@0
|
297 }
|
nuclear@0
|
298
|
nuclear@0
|
299 aiVector3D* verts = mesh->mVertices = new aiVector3D[cvert];
|
nuclear@0
|
300 aiColor4D* colors = mesh->mColors[0] = new aiColor4D[cvert];
|
nuclear@0
|
301 aiFace* faces = mesh->mFaces = new aiFace[cface];
|
nuclear@0
|
302
|
nuclear@0
|
303 mesh->mNumVertices = cvert;
|
nuclear@0
|
304 mesh->mNumFaces = cface;
|
nuclear@0
|
305
|
nuclear@0
|
306 unsigned int prims = 0;
|
nuclear@0
|
307 unsigned int overall_indices = 0;
|
nuclear@0
|
308 BOOST_FOREACH(const DXF::PolyLine* pl, corr[elem.second]){
|
nuclear@0
|
309
|
nuclear@0
|
310 std::vector<unsigned int>::const_iterator it = pl->indices.begin();
|
nuclear@0
|
311 BOOST_FOREACH(unsigned int facenumv,pl->counts) {
|
nuclear@0
|
312 aiFace& face = *faces++;
|
nuclear@0
|
313 face.mIndices = new unsigned int[face.mNumIndices = facenumv];
|
nuclear@0
|
314
|
nuclear@0
|
315 for (unsigned int i = 0; i < facenumv; ++i) {
|
nuclear@0
|
316 face.mIndices[i] = overall_indices++;
|
nuclear@0
|
317
|
nuclear@0
|
318 ai_assert(pl->positions.size() == pl->colors.size());
|
nuclear@0
|
319 if (*it >= pl->positions.size()) {
|
nuclear@0
|
320 throw DeadlyImportError("DXF: vertex index out of bounds");
|
nuclear@0
|
321 }
|
nuclear@0
|
322
|
nuclear@0
|
323 *verts++ = pl->positions[*it];
|
nuclear@0
|
324 *colors++ = pl->colors[*it++];
|
nuclear@0
|
325 }
|
nuclear@0
|
326
|
nuclear@0
|
327 // set primitive flags now, this saves the extra pass in ScenePreprocessor.
|
nuclear@0
|
328 switch(face.mNumIndices) {
|
nuclear@0
|
329 case 1:
|
nuclear@0
|
330 prims |= aiPrimitiveType_POINT;
|
nuclear@0
|
331 break;
|
nuclear@0
|
332 case 2:
|
nuclear@0
|
333 prims |= aiPrimitiveType_LINE;
|
nuclear@0
|
334 break;
|
nuclear@0
|
335 case 3:
|
nuclear@0
|
336 prims |= aiPrimitiveType_TRIANGLE;
|
nuclear@0
|
337 break;
|
nuclear@0
|
338 default:
|
nuclear@0
|
339 prims |= aiPrimitiveType_POLYGON;
|
nuclear@0
|
340 break;
|
nuclear@0
|
341 }
|
nuclear@0
|
342 }
|
nuclear@0
|
343 }
|
nuclear@0
|
344
|
nuclear@0
|
345 mesh->mPrimitiveTypes = prims;
|
nuclear@0
|
346 mesh->mMaterialIndex = 0;
|
nuclear@0
|
347 }
|
nuclear@0
|
348
|
nuclear@0
|
349 GenerateHierarchy(pScene,output);
|
nuclear@0
|
350 GenerateMaterials(pScene,output);
|
nuclear@0
|
351 }
|
nuclear@0
|
352
|
nuclear@0
|
353
|
nuclear@0
|
354 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
355 void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name)
|
nuclear@0
|
356 {
|
nuclear@0
|
357 BOOST_FOREACH (const DXF::InsertBlock& insert, bl.insertions) {
|
nuclear@0
|
358
|
nuclear@0
|
359 // first check if the referenced blocks exists ...
|
nuclear@0
|
360 const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
|
nuclear@0
|
361 if (it == blocks_by_name.end()) {
|
nuclear@0
|
362 DefaultLogger::get()->error((Formatter::format("DXF: Failed to resolve block reference: "),
|
nuclear@0
|
363 insert.name,"; skipping"
|
nuclear@0
|
364 ));
|
nuclear@0
|
365 continue;
|
nuclear@0
|
366 }
|
nuclear@0
|
367
|
nuclear@0
|
368 // XXX this would be the place to implement recursive expansion if needed.
|
nuclear@0
|
369 const DXF::Block& bl_src = *(*it).second;
|
nuclear@0
|
370
|
nuclear@0
|
371 BOOST_FOREACH (boost::shared_ptr<const DXF::PolyLine> pl_in, bl_src.lines) {
|
nuclear@0
|
372 boost::shared_ptr<DXF::PolyLine> pl_out = boost::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
|
nuclear@0
|
373
|
nuclear@0
|
374 if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {
|
nuclear@0
|
375 // manual coordinate system transformation
|
nuclear@0
|
376 // XXX order
|
nuclear@0
|
377 aiMatrix4x4 trafo, tmp;
|
nuclear@0
|
378 aiMatrix4x4::Translation(-bl_src.base,trafo);
|
nuclear@0
|
379 trafo *= aiMatrix4x4::Scaling(insert.scale,tmp);
|
nuclear@0
|
380 trafo *= aiMatrix4x4::Translation(insert.pos,tmp);
|
nuclear@0
|
381
|
nuclear@0
|
382 // XXX rotation currently ignored - I didn't find an appropriate sample model.
|
nuclear@0
|
383 if (insert.angle != 0.f) {
|
nuclear@0
|
384 DefaultLogger::get()->warn("DXF: BLOCK rotation not currently implemented");
|
nuclear@0
|
385 }
|
nuclear@0
|
386
|
nuclear@0
|
387 BOOST_FOREACH (aiVector3D& v, pl_out->positions) {
|
nuclear@0
|
388 v *= trafo;
|
nuclear@0
|
389 }
|
nuclear@0
|
390 }
|
nuclear@0
|
391
|
nuclear@0
|
392 bl.lines.push_back(pl_out);
|
nuclear@0
|
393 }
|
nuclear@0
|
394 }
|
nuclear@0
|
395 }
|
nuclear@0
|
396
|
nuclear@0
|
397
|
nuclear@0
|
398 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
399 void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/)
|
nuclear@0
|
400 {
|
nuclear@0
|
401 // generate an almost-white default material. Reason:
|
nuclear@0
|
402 // the default vertex color is GREY, so we are
|
nuclear@0
|
403 // already at Assimp's usual default color.
|
nuclear@0
|
404 // generate a default material
|
nuclear@0
|
405 aiMaterial* pcMat = new aiMaterial();
|
nuclear@0
|
406 aiString s;
|
nuclear@0
|
407 s.Set(AI_DEFAULT_MATERIAL_NAME);
|
nuclear@0
|
408 pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
nuclear@0
|
409
|
nuclear@0
|
410 aiColor4D clrDiffuse(0.9f,0.9f,0.9f,1.0f);
|
nuclear@0
|
411 pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
412
|
nuclear@0
|
413 clrDiffuse = aiColor4D(1.0f,1.0f,1.0f,1.0f);
|
nuclear@0
|
414 pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
|
nuclear@0
|
415
|
nuclear@0
|
416 clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
|
nuclear@0
|
417 pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
|
nuclear@0
|
418
|
nuclear@0
|
419 pScene->mNumMaterials = 1;
|
nuclear@0
|
420 pScene->mMaterials = new aiMaterial*[1];
|
nuclear@0
|
421 pScene->mMaterials[0] = pcMat;
|
nuclear@0
|
422 }
|
nuclear@0
|
423
|
nuclear@0
|
424
|
nuclear@0
|
425 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
426 void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
|
nuclear@0
|
427 {
|
nuclear@0
|
428 // generate the output scene graph, which is just the root node with a single child for each layer.
|
nuclear@0
|
429 pScene->mRootNode = new aiNode();
|
nuclear@0
|
430 pScene->mRootNode->mName.Set("<DXF_ROOT>");
|
nuclear@0
|
431
|
nuclear@0
|
432 if (1 == pScene->mNumMeshes) {
|
nuclear@0
|
433 pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
|
nuclear@0
|
434 pScene->mRootNode->mMeshes[0] = 0;
|
nuclear@0
|
435 }
|
nuclear@0
|
436 else
|
nuclear@0
|
437 {
|
nuclear@0
|
438 pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
|
nuclear@0
|
439 for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m) {
|
nuclear@0
|
440 aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
|
nuclear@0
|
441 p->mName = pScene->mMeshes[m]->mName;
|
nuclear@0
|
442
|
nuclear@0
|
443 p->mMeshes = new unsigned int[p->mNumMeshes = 1];
|
nuclear@0
|
444 p->mMeshes[0] = m;
|
nuclear@0
|
445 p->mParent = pScene->mRootNode;
|
nuclear@0
|
446 }
|
nuclear@0
|
447 }
|
nuclear@0
|
448 }
|
nuclear@0
|
449
|
nuclear@0
|
450
|
nuclear@0
|
451 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
452 void DXFImporter::SkipSection(DXF::LineReader& reader)
|
nuclear@0
|
453 {
|
nuclear@0
|
454 for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
|
nuclear@0
|
455 }
|
nuclear@0
|
456
|
nuclear@0
|
457
|
nuclear@0
|
458 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
459 void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& /*output*/)
|
nuclear@0
|
460 {
|
nuclear@0
|
461 for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
|
nuclear@0
|
462 }
|
nuclear@0
|
463
|
nuclear@0
|
464
|
nuclear@0
|
465 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
466 void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output)
|
nuclear@0
|
467 {
|
nuclear@0
|
468 while( !reader.End() && !reader.Is(0,"ENDSEC")) {
|
nuclear@0
|
469 if (reader.Is(0,"BLOCK")) {
|
nuclear@0
|
470 ParseBlock(++reader,output);
|
nuclear@0
|
471 continue;
|
nuclear@0
|
472 }
|
nuclear@0
|
473 ++reader;
|
nuclear@0
|
474 }
|
nuclear@0
|
475
|
nuclear@0
|
476 DefaultLogger::get()->debug((Formatter::format("DXF: got "),
|
nuclear@0
|
477 output.blocks.size()," entries in BLOCKS"
|
nuclear@0
|
478 ));
|
nuclear@0
|
479 }
|
nuclear@0
|
480
|
nuclear@0
|
481
|
nuclear@0
|
482 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
483 void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
|
nuclear@0
|
484 {
|
nuclear@0
|
485 // push a new block onto the stack.
|
nuclear@0
|
486 output.blocks.push_back( DXF::Block() );
|
nuclear@0
|
487 DXF::Block& block = output.blocks.back();
|
nuclear@0
|
488
|
nuclear@0
|
489 while( !reader.End() && !reader.Is(0,"ENDBLK")) {
|
nuclear@0
|
490
|
nuclear@0
|
491 switch(reader.GroupCode()) {
|
nuclear@0
|
492 case 2:
|
nuclear@0
|
493 block.name = reader.Value();
|
nuclear@0
|
494 break;
|
nuclear@0
|
495
|
nuclear@0
|
496 case 10:
|
nuclear@0
|
497 block.base.x = reader.ValueAsFloat();
|
nuclear@0
|
498 break;
|
nuclear@0
|
499 case 20:
|
nuclear@0
|
500 block.base.y = reader.ValueAsFloat();
|
nuclear@0
|
501 break;
|
nuclear@0
|
502 case 30:
|
nuclear@0
|
503 block.base.z = reader.ValueAsFloat();
|
nuclear@0
|
504 break;
|
nuclear@0
|
505 }
|
nuclear@0
|
506
|
nuclear@0
|
507 if (reader.Is(0,"POLYLINE")) {
|
nuclear@0
|
508 ParsePolyLine(++reader,output);
|
nuclear@0
|
509 continue;
|
nuclear@0
|
510 }
|
nuclear@0
|
511
|
nuclear@0
|
512 // XXX is this a valid case?
|
nuclear@0
|
513 if (reader.Is(0,"INSERT")) {
|
nuclear@0
|
514 DefaultLogger::get()->warn("DXF: INSERT within a BLOCK not currently supported; skipping");
|
nuclear@0
|
515 for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader);
|
nuclear@0
|
516 break;
|
nuclear@0
|
517 }
|
nuclear@0
|
518
|
nuclear@0
|
519 else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
|
nuclear@0
|
520 //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
|
nuclear@0
|
521 Parse3DFace(++reader, output);
|
nuclear@0
|
522 continue;
|
nuclear@0
|
523 }
|
nuclear@0
|
524 ++reader;
|
nuclear@0
|
525 }
|
nuclear@0
|
526 }
|
nuclear@0
|
527
|
nuclear@0
|
528
|
nuclear@0
|
529 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
530 void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
|
nuclear@0
|
531 {
|
nuclear@0
|
532 // push a new block onto the stack.
|
nuclear@0
|
533 output.blocks.push_back( DXF::Block() );
|
nuclear@0
|
534 DXF::Block& block = output.blocks.back();
|
nuclear@0
|
535
|
nuclear@0
|
536 block.name = AI_DXF_ENTITIES_MAGIC_BLOCK;
|
nuclear@0
|
537
|
nuclear@0
|
538 while( !reader.End() && !reader.Is(0,"ENDSEC")) {
|
nuclear@0
|
539 if (reader.Is(0,"POLYLINE")) {
|
nuclear@0
|
540 ParsePolyLine(++reader,output);
|
nuclear@0
|
541 continue;
|
nuclear@0
|
542 }
|
nuclear@0
|
543
|
nuclear@0
|
544 else if (reader.Is(0,"INSERT")) {
|
nuclear@0
|
545 ParseInsertion(++reader,output);
|
nuclear@0
|
546 continue;
|
nuclear@0
|
547 }
|
nuclear@0
|
548
|
nuclear@0
|
549 else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
|
nuclear@0
|
550 //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
|
nuclear@0
|
551 Parse3DFace(++reader, output);
|
nuclear@0
|
552 continue;
|
nuclear@0
|
553 }
|
nuclear@0
|
554
|
nuclear@0
|
555 ++reader;
|
nuclear@0
|
556 }
|
nuclear@0
|
557
|
nuclear@0
|
558 DefaultLogger::get()->debug((Formatter::format("DXF: got "),
|
nuclear@0
|
559 block.lines.size()," polylines and ", block.insertions.size() ," inserted blocks in ENTITIES"
|
nuclear@0
|
560 ));
|
nuclear@0
|
561 }
|
nuclear@0
|
562
|
nuclear@0
|
563
|
nuclear@0
|
564 void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
|
nuclear@0
|
565 {
|
nuclear@0
|
566 output.blocks.back().insertions.push_back( DXF::InsertBlock() );
|
nuclear@0
|
567 DXF::InsertBlock& bl = output.blocks.back().insertions.back();
|
nuclear@0
|
568
|
nuclear@0
|
569 while( !reader.End() && !reader.Is(0)) {
|
nuclear@0
|
570
|
nuclear@0
|
571 switch(reader.GroupCode())
|
nuclear@0
|
572 {
|
nuclear@0
|
573 // name of referenced block
|
nuclear@0
|
574 case 2:
|
nuclear@0
|
575 bl.name = reader.Value();
|
nuclear@0
|
576 break;
|
nuclear@0
|
577
|
nuclear@0
|
578 // translation
|
nuclear@0
|
579 case 10:
|
nuclear@0
|
580 bl.pos.x = reader.ValueAsFloat();
|
nuclear@0
|
581 break;
|
nuclear@0
|
582 case 20:
|
nuclear@0
|
583 bl.pos.y = reader.ValueAsFloat();
|
nuclear@0
|
584 break;
|
nuclear@0
|
585 case 30:
|
nuclear@0
|
586 bl.pos.z = reader.ValueAsFloat();
|
nuclear@0
|
587 break;
|
nuclear@0
|
588
|
nuclear@0
|
589 // scaling
|
nuclear@0
|
590 case 41:
|
nuclear@0
|
591 bl.scale.x = reader.ValueAsFloat();
|
nuclear@0
|
592 break;
|
nuclear@0
|
593 case 42:
|
nuclear@0
|
594 bl.scale.y = reader.ValueAsFloat();
|
nuclear@0
|
595 break;
|
nuclear@0
|
596 case 43:
|
nuclear@0
|
597 bl.scale.z = reader.ValueAsFloat();
|
nuclear@0
|
598 break;
|
nuclear@0
|
599
|
nuclear@0
|
600 // rotation angle
|
nuclear@0
|
601 case 50:
|
nuclear@0
|
602 bl.angle = reader.ValueAsFloat();
|
nuclear@0
|
603 break;
|
nuclear@0
|
604 }
|
nuclear@0
|
605 reader++;
|
nuclear@0
|
606 }
|
nuclear@0
|
607 }
|
nuclear@0
|
608
|
nuclear@0
|
609 #define DXF_POLYLINE_FLAG_CLOSED 0x1
|
nuclear@0
|
610 #define DXF_POLYLINE_FLAG_3D_POLYLINE 0x8
|
nuclear@0
|
611 #define DXF_POLYLINE_FLAG_3D_POLYMESH 0x10
|
nuclear@0
|
612 #define DXF_POLYLINE_FLAG_POLYFACEMESH 0x40
|
nuclear@0
|
613
|
nuclear@0
|
614 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
615 void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
|
nuclear@0
|
616 {
|
nuclear@0
|
617 output.blocks.back().lines.push_back( boost::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
|
nuclear@0
|
618 DXF::PolyLine& line = *output.blocks.back().lines.back();
|
nuclear@0
|
619
|
nuclear@0
|
620 unsigned int iguess = 0, vguess = 0;
|
nuclear@0
|
621 while( !reader.End() && !reader.Is(0,"ENDSEC")) {
|
nuclear@0
|
622
|
nuclear@0
|
623 if (reader.Is(0,"VERTEX")) {
|
nuclear@0
|
624 ParsePolyLineVertex(++reader,line);
|
nuclear@0
|
625 if (reader.Is(0,"SEQEND")) {
|
nuclear@0
|
626 break;
|
nuclear@0
|
627 }
|
nuclear@0
|
628 continue;
|
nuclear@0
|
629 }
|
nuclear@0
|
630
|
nuclear@0
|
631 switch(reader.GroupCode())
|
nuclear@0
|
632 {
|
nuclear@0
|
633 // flags --- important that we know whether it is a
|
nuclear@0
|
634 // polyface mesh or 'just' a line.
|
nuclear@0
|
635 case 70:
|
nuclear@0
|
636 if (!line.flags) {
|
nuclear@0
|
637 line.flags = reader.ValueAsSignedInt();
|
nuclear@0
|
638 }
|
nuclear@0
|
639 break;
|
nuclear@0
|
640
|
nuclear@0
|
641 // optional number of vertices
|
nuclear@0
|
642 case 71:
|
nuclear@0
|
643 vguess = reader.ValueAsSignedInt();
|
nuclear@0
|
644 line.positions.reserve(vguess);
|
nuclear@0
|
645 break;
|
nuclear@0
|
646
|
nuclear@0
|
647 // optional number of faces
|
nuclear@0
|
648 case 72:
|
nuclear@0
|
649 iguess = reader.ValueAsSignedInt();
|
nuclear@0
|
650 line.indices.reserve(iguess);
|
nuclear@0
|
651 break;
|
nuclear@0
|
652
|
nuclear@0
|
653 // 8 specifies the layer on which this line is placed on
|
nuclear@0
|
654 case 8:
|
nuclear@0
|
655 line.layer = reader.Value();
|
nuclear@0
|
656 break;
|
nuclear@0
|
657 }
|
nuclear@0
|
658
|
nuclear@0
|
659 reader++;
|
nuclear@0
|
660 }
|
nuclear@0
|
661
|
nuclear@0
|
662 //if (!(line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH)) {
|
nuclear@0
|
663 // DefaultLogger::get()->warn((Formatter::format("DXF: polyline not currently supported: "),line.flags));
|
nuclear@0
|
664 // output.blocks.back().lines.pop_back();
|
nuclear@0
|
665 // return;
|
nuclear@0
|
666 //}
|
nuclear@0
|
667
|
nuclear@0
|
668 if (vguess && line.positions.size() != vguess) {
|
nuclear@0
|
669 DefaultLogger::get()->warn((Formatter::format("DXF: unexpected vertex count in polymesh: "),
|
nuclear@0
|
670 line.positions.size(),", expected ", vguess
|
nuclear@0
|
671 ));
|
nuclear@0
|
672 }
|
nuclear@0
|
673
|
nuclear@0
|
674 if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) {
|
nuclear@0
|
675 if (line.positions.size() < 3 || line.indices.size() < 3) {
|
nuclear@0
|
676 DefaultLogger::get()->warn("DXF: not enough vertices for polymesh; ignoring");
|
nuclear@0
|
677 output.blocks.back().lines.pop_back();
|
nuclear@0
|
678 return;
|
nuclear@0
|
679 }
|
nuclear@0
|
680
|
nuclear@0
|
681 // if these numbers are wrong, parsing might have gone wild.
|
nuclear@0
|
682 // however, the docs state that applications are not required
|
nuclear@0
|
683 // to set the 71 and 72 fields, respectively, to valid values.
|
nuclear@0
|
684 // So just fire a warning.
|
nuclear@0
|
685 if (iguess && line.counts.size() != iguess) {
|
nuclear@0
|
686 DefaultLogger::get()->warn((Formatter::format("DXF: unexpected face count in polymesh: "),
|
nuclear@0
|
687 line.counts.size(),", expected ", iguess
|
nuclear@0
|
688 ));
|
nuclear@0
|
689 }
|
nuclear@0
|
690 }
|
nuclear@0
|
691 else if (!line.indices.size() && !line.counts.size()) {
|
nuclear@0
|
692 // a polyline - so there are no indices yet.
|
nuclear@0
|
693 size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0);
|
nuclear@0
|
694 line.indices.reserve(guess);
|
nuclear@0
|
695
|
nuclear@0
|
696 line.counts.reserve(guess/2);
|
nuclear@0
|
697 for (unsigned int i = 0; i < line.positions.size()/2; ++i) {
|
nuclear@0
|
698 line.indices.push_back(i*2);
|
nuclear@0
|
699 line.indices.push_back(i*2+1);
|
nuclear@0
|
700 line.counts.push_back(2);
|
nuclear@0
|
701 }
|
nuclear@0
|
702
|
nuclear@0
|
703 // closed polyline?
|
nuclear@0
|
704 if (line.flags & DXF_POLYLINE_FLAG_CLOSED) {
|
nuclear@0
|
705 line.indices.push_back(line.positions.size()-1);
|
nuclear@0
|
706 line.indices.push_back(0);
|
nuclear@0
|
707 line.counts.push_back(2);
|
nuclear@0
|
708 }
|
nuclear@0
|
709 }
|
nuclear@0
|
710 }
|
nuclear@0
|
711
|
nuclear@0
|
712 #define DXF_VERTEX_FLAG_PART_OF_POLYFACE 0x80
|
nuclear@0
|
713 #define DXF_VERTEX_FLAG_HAS_POSITIONS 0x40
|
nuclear@0
|
714
|
nuclear@0
|
715 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
716 void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line)
|
nuclear@0
|
717 {
|
nuclear@0
|
718 unsigned int cnti = 0, flags = 0;
|
nuclear@0
|
719 unsigned int indices[4];
|
nuclear@0
|
720
|
nuclear@0
|
721 aiVector3D out;
|
nuclear@0
|
722 aiColor4D clr = AI_DXF_DEFAULT_COLOR;
|
nuclear@0
|
723
|
nuclear@0
|
724 while( !reader.End() ) {
|
nuclear@0
|
725
|
nuclear@0
|
726 if (reader.Is(0)) { // SEQEND or another VERTEX
|
nuclear@0
|
727 break;
|
nuclear@0
|
728 }
|
nuclear@0
|
729
|
nuclear@0
|
730 switch (reader.GroupCode())
|
nuclear@0
|
731 {
|
nuclear@0
|
732 case 8:
|
nuclear@0
|
733 // layer to which the vertex belongs to - assume that
|
nuclear@0
|
734 // this is always the layer the top-level polyline
|
nuclear@0
|
735 // entity resides on as well.
|
nuclear@0
|
736 if(reader.Value() != line.layer) {
|
nuclear@0
|
737 DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
|
nuclear@0
|
738 }
|
nuclear@0
|
739 break;
|
nuclear@0
|
740
|
nuclear@0
|
741 case 70:
|
nuclear@0
|
742 flags = reader.ValueAsUnsignedInt();
|
nuclear@0
|
743 break;
|
nuclear@0
|
744
|
nuclear@0
|
745 // VERTEX COORDINATES
|
nuclear@0
|
746 case 10: out.x = reader.ValueAsFloat();break;
|
nuclear@0
|
747 case 20: out.y = reader.ValueAsFloat();break;
|
nuclear@0
|
748 case 30: out.z = reader.ValueAsFloat();break;
|
nuclear@0
|
749
|
nuclear@0
|
750 // POLYFACE vertex indices
|
nuclear@0
|
751 case 71:
|
nuclear@0
|
752 case 72:
|
nuclear@0
|
753 case 73:
|
nuclear@0
|
754 case 74:
|
nuclear@0
|
755 if (cnti == 4) {
|
nuclear@0
|
756 DefaultLogger::get()->warn("DXF: more than 4 indices per face not supported; ignoring");
|
nuclear@0
|
757 break;
|
nuclear@0
|
758 }
|
nuclear@0
|
759 indices[cnti++] = reader.ValueAsUnsignedInt();
|
nuclear@0
|
760 break;
|
nuclear@0
|
761
|
nuclear@0
|
762 // color
|
nuclear@0
|
763 case 62:
|
nuclear@0
|
764 clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
|
nuclear@0
|
765 break;
|
nuclear@0
|
766 };
|
nuclear@0
|
767
|
nuclear@0
|
768 reader++;
|
nuclear@0
|
769 }
|
nuclear@0
|
770
|
nuclear@0
|
771 if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) {
|
nuclear@0
|
772 DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
|
nuclear@0
|
773 }
|
nuclear@0
|
774
|
nuclear@0
|
775 if (cnti) {
|
nuclear@0
|
776 line.counts.push_back(cnti);
|
nuclear@0
|
777 for (unsigned int i = 0; i < cnti; ++i) {
|
nuclear@0
|
778 // IMPORTANT NOTE: POLYMESH indices are ONE-BASED
|
nuclear@0
|
779 if (indices[i] == 0) {
|
nuclear@0
|
780 DefaultLogger::get()->warn("DXF: invalid vertex index, indices are one-based.");
|
nuclear@0
|
781 --line.counts.back();
|
nuclear@0
|
782 continue;
|
nuclear@0
|
783 }
|
nuclear@0
|
784 line.indices.push_back(indices[i]-1);
|
nuclear@0
|
785 }
|
nuclear@0
|
786 }
|
nuclear@0
|
787 else {
|
nuclear@0
|
788 line.positions.push_back(out);
|
nuclear@0
|
789 line.colors.push_back(clr);
|
nuclear@0
|
790 }
|
nuclear@0
|
791 }
|
nuclear@0
|
792
|
nuclear@0
|
793 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
794 void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
|
nuclear@0
|
795 {
|
nuclear@0
|
796 // (note) this is also used for for parsing line entities, so we
|
nuclear@0
|
797 // must handle the vertex_count == 2 case as well.
|
nuclear@0
|
798
|
nuclear@0
|
799 output.blocks.back().lines.push_back( boost::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
|
nuclear@0
|
800 DXF::PolyLine& line = *output.blocks.back().lines.back();
|
nuclear@0
|
801
|
nuclear@0
|
802 aiVector3D vip[4];
|
nuclear@0
|
803 aiColor4D clr = AI_DXF_DEFAULT_COLOR;
|
nuclear@0
|
804
|
nuclear@0
|
805 bool b[4] = {false,false,false,false};
|
nuclear@0
|
806 while( !reader.End() ) {
|
nuclear@0
|
807
|
nuclear@0
|
808 // next entity with a groupcode == 0 is probably already the next vertex or polymesh entity
|
nuclear@0
|
809 if (reader.GroupCode() == 0) {
|
nuclear@0
|
810 break;
|
nuclear@0
|
811 }
|
nuclear@0
|
812 switch (reader.GroupCode())
|
nuclear@0
|
813 {
|
nuclear@0
|
814
|
nuclear@0
|
815 // 8 specifies the layer
|
nuclear@0
|
816 case 8:
|
nuclear@0
|
817 line.layer = reader.Value();
|
nuclear@0
|
818 break;
|
nuclear@0
|
819
|
nuclear@0
|
820 // x position of the first corner
|
nuclear@0
|
821 case 10: vip[0].x = reader.ValueAsFloat();
|
nuclear@0
|
822 b[2] = true;
|
nuclear@0
|
823 break;
|
nuclear@0
|
824
|
nuclear@0
|
825 // y position of the first corner
|
nuclear@0
|
826 case 20: vip[0].y = reader.ValueAsFloat();
|
nuclear@0
|
827 b[2] = true;
|
nuclear@0
|
828 break;
|
nuclear@0
|
829
|
nuclear@0
|
830 // z position of the first corner
|
nuclear@0
|
831 case 30: vip[0].z = reader.ValueAsFloat();
|
nuclear@0
|
832 b[2] = true;
|
nuclear@0
|
833 break;
|
nuclear@0
|
834
|
nuclear@0
|
835 // x position of the second corner
|
nuclear@0
|
836 case 11: vip[1].x = reader.ValueAsFloat();
|
nuclear@0
|
837 b[3] = true;
|
nuclear@0
|
838 break;
|
nuclear@0
|
839
|
nuclear@0
|
840 // y position of the second corner
|
nuclear@0
|
841 case 21: vip[1].y = reader.ValueAsFloat();
|
nuclear@0
|
842 b[3] = true;
|
nuclear@0
|
843 break;
|
nuclear@0
|
844
|
nuclear@0
|
845 // z position of the second corner
|
nuclear@0
|
846 case 31: vip[1].z = reader.ValueAsFloat();
|
nuclear@0
|
847 b[3] = true;
|
nuclear@0
|
848 break;
|
nuclear@0
|
849
|
nuclear@0
|
850 // x position of the third corner
|
nuclear@0
|
851 case 12: vip[2].x = reader.ValueAsFloat();
|
nuclear@0
|
852 b[0] = true;
|
nuclear@0
|
853 break;
|
nuclear@0
|
854
|
nuclear@0
|
855 // y position of the third corner
|
nuclear@0
|
856 case 22: vip[2].y = reader.ValueAsFloat();
|
nuclear@0
|
857 b[0] = true;
|
nuclear@0
|
858 break;
|
nuclear@0
|
859
|
nuclear@0
|
860 // z position of the third corner
|
nuclear@0
|
861 case 32: vip[2].z = reader.ValueAsFloat();
|
nuclear@0
|
862 b[0] = true;
|
nuclear@0
|
863 break;
|
nuclear@0
|
864
|
nuclear@0
|
865 // x position of the fourth corner
|
nuclear@0
|
866 case 13: vip[3].x = reader.ValueAsFloat();
|
nuclear@0
|
867 b[1] = true;
|
nuclear@0
|
868 break;
|
nuclear@0
|
869
|
nuclear@0
|
870 // y position of the fourth corner
|
nuclear@0
|
871 case 23: vip[3].y = reader.ValueAsFloat();
|
nuclear@0
|
872 b[1] = true;
|
nuclear@0
|
873 break;
|
nuclear@0
|
874
|
nuclear@0
|
875 // z position of the fourth corner
|
nuclear@0
|
876 case 33: vip[3].z = reader.ValueAsFloat();
|
nuclear@0
|
877 b[1] = true;
|
nuclear@0
|
878 break;
|
nuclear@0
|
879
|
nuclear@0
|
880 // color
|
nuclear@0
|
881 case 62:
|
nuclear@0
|
882 clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
|
nuclear@0
|
883 break;
|
nuclear@0
|
884 };
|
nuclear@0
|
885
|
nuclear@0
|
886 ++reader;
|
nuclear@0
|
887 }
|
nuclear@0
|
888
|
nuclear@0
|
889 // the fourth corner may even be identical to the third,
|
nuclear@0
|
890 // in this case we treat it as if it didn't exist.
|
nuclear@0
|
891 if (vip[3] == vip[2]) {
|
nuclear@0
|
892 b[1] = false;
|
nuclear@0
|
893 }
|
nuclear@0
|
894
|
nuclear@0
|
895 // sanity checks to see if we got something meaningful
|
nuclear@0
|
896 if ((b[1] && !b[0]) || !b[2] || !b[3]) {
|
nuclear@0
|
897 DefaultLogger::get()->warn("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
|
nuclear@0
|
898 output.blocks.back().lines.pop_back();
|
nuclear@0
|
899 return;
|
nuclear@0
|
900 }
|
nuclear@0
|
901
|
nuclear@0
|
902 const unsigned int cnt = (2+(b[0]?1:0)+(b[1]?1:0));
|
nuclear@0
|
903 line.counts.push_back(cnt);
|
nuclear@0
|
904
|
nuclear@0
|
905 for (unsigned int i = 0; i < cnt; ++i) {
|
nuclear@0
|
906 line.indices.push_back(line.positions.size());
|
nuclear@0
|
907 line.positions.push_back(vip[i]);
|
nuclear@0
|
908 line.colors.push_back(clr);
|
nuclear@0
|
909 }
|
nuclear@0
|
910 }
|
nuclear@0
|
911
|
nuclear@0
|
912 #endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER
|
nuclear@0
|
913
|