]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/opengl/penguin/dxfrenderer.cpp
Replace the sample animation timer with an idle loops and the animation with a busy...
[wxWidgets.git] / samples / opengl / penguin / dxfrenderer.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: dxfrenderer.cpp
3// Purpose: DXF reader and renderer
4// Author: Sandro Sigala
5// Modified by:
6// Created: 2005-11-10
7// RCS-ID: $Id$
8// Copyright: (c) Sandro Sigala
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include "wx/wx.h"
21#endif
22
23#include "wx/wfstream.h"
24#include "wx/txtstrm.h"
25
26#if !wxUSE_GLCANVAS
27 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
28#endif
29
30#ifdef __DARWIN__
31 #include <OpenGL/glu.h>
32#else
33 #include <GL/glu.h>
34#endif
35
36#include <sstream>
37
38#include "dxfrenderer.h"
39
40#include "wx/listimpl.cpp"
41WX_DEFINE_LIST(DXFEntityList)
42WX_DEFINE_LIST(DXFLayerList)
43
44// Conversion table from AutoCAD ACI colours to RGB values
45static const struct { unsigned char r, g, b; } aci_to_rgb[256] = {
46/* 0 */ {255, 255, 255},
47/* 1 */ {255, 0, 0},
48/* 2 */ {255, 255, 0},
49/* 3 */ { 0, 255, 0},
50/* 4 */ { 0, 255, 255},
51/* 5 */ { 0, 0, 255},
52/* 6 */ {255, 0, 255},
53/* 7 */ {255, 255, 255},
54/* 8 */ {128, 128, 128},
55/* 9 */ {192, 192, 192},
56/* 10 */ {255, 0, 0},
57/* 11 */ {255, 127, 127},
58/* 12 */ {204, 0, 0},
59/* 13 */ {204, 102, 102},
60/* 14 */ {153, 0, 0},
61/* 15 */ {153, 76, 76},
62/* 16 */ {127, 0, 0},
63/* 17 */ {127, 63, 63},
64/* 18 */ { 76, 0, 0},
65/* 19 */ { 76, 38, 38},
66/* 20 */ {255, 63, 0},
67/* 21 */ {255, 159, 127},
68/* 22 */ {204, 51, 0},
69/* 23 */ {204, 127, 102},
70/* 24 */ {153, 38, 0},
71/* 25 */ {153, 95, 76},
72/* 26 */ {127, 31, 0},
73/* 27 */ {127, 79, 63},
74/* 28 */ { 76, 19, 0},
75/* 29 */ { 76, 47, 38},
76/* 30 */ {255, 127, 0},
77/* 31 */ {255, 191, 127},
78/* 32 */ {204, 102, 0},
79/* 33 */ {204, 153, 102},
80/* 34 */ {153, 76, 0},
81/* 35 */ {153, 114, 76},
82/* 36 */ {127, 63, 0},
83/* 37 */ {127, 95, 63},
84/* 38 */ { 76, 38, 0},
85/* 39 */ { 76, 57, 38},
86/* 40 */ {255, 191, 0},
87/* 41 */ {255, 223, 127},
88/* 42 */ {204, 153, 0},
89/* 43 */ {204, 178, 102},
90/* 44 */ {153, 114, 0},
91/* 45 */ {153, 133, 76},
92/* 46 */ {127, 95, 0},
93/* 47 */ {127, 111, 63},
94/* 48 */ { 76, 57, 0},
95/* 49 */ { 76, 66, 38},
96/* 50 */ {255, 255, 0},
97/* 51 */ {255, 255, 127},
98/* 52 */ {204, 204, 0},
99/* 53 */ {204, 204, 102},
100/* 54 */ {153, 153, 0},
101/* 55 */ {153, 153, 76},
102/* 56 */ {127, 127, 0},
103/* 57 */ {127, 127, 63},
104/* 58 */ { 76, 76, 0},
105/* 59 */ { 76, 76, 38},
106/* 60 */ {191, 255, 0},
107/* 61 */ {223, 255, 127},
108/* 62 */ {153, 204, 0},
109/* 63 */ {178, 204, 102},
110/* 64 */ {114, 153, 0},
111/* 65 */ {133, 153, 76},
112/* 66 */ { 95, 127, 0},
113/* 67 */ {111, 127, 63},
114/* 68 */ { 57, 76, 0},
115/* 69 */ { 66, 76, 38},
116/* 70 */ {127, 255, 0},
117/* 71 */ {191, 255, 127},
118/* 72 */ {102, 204, 0},
119/* 73 */ {153, 204, 102},
120/* 74 */ { 76, 153, 0},
121/* 75 */ {114, 153, 76},
122/* 76 */ { 63, 127, 0},
123/* 77 */ { 95, 127, 63},
124/* 78 */ { 38, 76, 0},
125/* 79 */ { 57, 76, 38},
126/* 80 */ { 63, 255, 0},
127/* 81 */ {159, 255, 127},
128/* 82 */ { 51, 204, 0},
129/* 83 */ {127, 204, 102},
130/* 84 */ { 38, 153, 0},
131/* 85 */ { 95, 153, 76},
132/* 86 */ { 31, 127, 0},
133/* 87 */ { 79, 127, 63},
134/* 88 */ { 19, 76, 0},
135/* 89 */ { 47, 76, 38},
136/* 90 */ { 0, 255, 0},
137/* 91 */ {127, 255, 127},
138/* 92 */ { 0, 204, 0},
139/* 93 */ {102, 204, 102},
140/* 94 */ { 0, 153, 0},
141/* 95 */ { 76, 153, 76},
142/* 96 */ { 0, 127, 0},
143/* 97 */ { 63, 127, 63},
144/* 98 */ { 0, 76, 0},
145/* 99 */ { 38, 76, 38},
146/* 100 */ { 0, 255, 63},
147/* 101 */ {127, 255, 159},
148/* 102 */ { 0, 204, 51},
149/* 103 */ {102, 204, 127},
150/* 104 */ { 0, 153, 38},
151/* 105 */ { 76, 153, 95},
152/* 106 */ { 0, 127, 31},
153/* 107 */ { 63, 127, 79},
154/* 108 */ { 0, 76, 19},
155/* 109 */ { 38, 76, 47},
156/* 110 */ { 0, 255, 127},
157/* 111 */ {127, 255, 191},
158/* 112 */ { 0, 204, 102},
159/* 113 */ {102, 204, 153},
160/* 114 */ { 0, 153, 76},
161/* 115 */ { 76, 153, 114},
162/* 116 */ { 0, 127, 63},
163/* 117 */ { 63, 127, 95},
164/* 118 */ { 0, 76, 38},
165/* 119 */ { 38, 76, 57},
166/* 120 */ { 0, 255, 191},
167/* 121 */ {127, 255, 223},
168/* 122 */ { 0, 204, 153},
169/* 123 */ {102, 204, 178},
170/* 124 */ { 0, 153, 114},
171/* 125 */ { 76, 153, 133},
172/* 126 */ { 0, 127, 95},
173/* 127 */ { 63, 127, 111},
174/* 128 */ { 0, 76, 57},
175/* 129 */ { 38, 76, 66},
176/* 130 */ { 0, 255, 255},
177/* 131 */ {127, 255, 255},
178/* 132 */ { 0, 204, 204},
179/* 133 */ {102, 204, 204},
180/* 134 */ { 0, 153, 153},
181/* 135 */ { 76, 153, 153},
182/* 136 */ { 0, 127, 127},
183/* 137 */ { 63, 127, 127},
184/* 138 */ { 0, 76, 76},
185/* 139 */ { 38, 76, 76},
186/* 140 */ { 0, 191, 255},
187/* 141 */ {127, 223, 255},
188/* 142 */ { 0, 153, 204},
189/* 143 */ {102, 178, 204},
190/* 144 */ { 0, 114, 153},
191/* 145 */ { 76, 133, 153},
192/* 146 */ { 0, 95, 127},
193/* 147 */ { 63, 111, 127},
194/* 148 */ { 0, 57, 76},
195/* 149 */ { 38, 66, 76},
196/* 150 */ { 0, 127, 255},
197/* 151 */ {127, 191, 255},
198/* 152 */ { 0, 102, 204},
199/* 153 */ {102, 153, 204},
200/* 154 */ { 0, 76, 153},
201/* 155 */ { 76, 114, 153},
202/* 156 */ { 0, 63, 127},
203/* 157 */ { 63, 95, 127},
204/* 158 */ { 0, 38, 76},
205/* 159 */ { 38, 57, 76},
206/* 160 */ { 0, 63, 255},
207/* 161 */ {127, 159, 255},
208/* 162 */ { 0, 51, 204},
209/* 163 */ {102, 127, 204},
210/* 164 */ { 0, 38, 153},
211/* 165 */ { 76, 95, 153},
212/* 166 */ { 0, 31, 127},
213/* 167 */ { 63, 79, 127},
214/* 168 */ { 0, 19, 76},
215/* 169 */ { 38, 47, 76},
216/* 170 */ { 0, 0, 255},
217/* 171 */ {127, 127, 255},
218/* 172 */ { 0, 0, 204},
219/* 173 */ {102, 102, 204},
220/* 174 */ { 0, 0, 153},
221/* 175 */ { 76, 76, 153},
222/* 176 */ { 0, 0, 127},
223/* 177 */ { 63, 63, 127},
224/* 178 */ { 0, 0, 76},
225/* 179 */ { 38, 38, 76},
226/* 180 */ { 63, 0, 255},
227/* 181 */ {159, 127, 255},
228/* 182 */ { 51, 0, 204},
229/* 183 */ {127, 102, 204},
230/* 184 */ { 38, 0, 153},
231/* 185 */ { 95, 76, 153},
232/* 186 */ { 31, 0, 127},
233/* 187 */ { 79, 63, 127},
234/* 188 */ { 19, 0, 76},
235/* 189 */ { 47, 38, 76},
236/* 190 */ {127, 0, 255},
237/* 191 */ {191, 127, 255},
238/* 192 */ {102, 0, 204},
239/* 193 */ {153, 102, 204},
240/* 194 */ { 76, 0, 153},
241/* 195 */ {114, 76, 153},
242/* 196 */ { 63, 0, 127},
243/* 197 */ { 95, 63, 127},
244/* 198 */ { 38, 0, 76},
245/* 199 */ { 57, 38, 76},
246/* 200 */ {191, 0, 255},
247/* 201 */ {223, 127, 255},
248/* 202 */ {153, 0, 204},
249/* 203 */ {178, 102, 204},
250/* 204 */ {114, 0, 153},
251/* 205 */ {133, 76, 153},
252/* 206 */ { 95, 0, 127},
253/* 207 */ {111, 63, 127},
254/* 208 */ { 57, 0, 76},
255/* 209 */ { 66, 38, 76},
256/* 210 */ {255, 0, 255},
257/* 211 */ {255, 127, 255},
258/* 212 */ {204, 0, 204},
259/* 213 */ {204, 102, 204},
260/* 214 */ {153, 0, 153},
261/* 215 */ {153, 76, 153},
262/* 216 */ {127, 0, 127},
263/* 217 */ {127, 63, 127},
264/* 218 */ { 76, 0, 76},
265/* 219 */ { 76, 38, 76},
266/* 220 */ {255, 0, 191},
267/* 221 */ {255, 127, 223},
268/* 222 */ {204, 0, 153},
269/* 223 */ {204, 102, 178},
270/* 224 */ {153, 0, 114},
271/* 225 */ {153, 76, 133},
272/* 226 */ {127, 0, 95},
273/* 227 */ {127, 63, 111},
274/* 228 */ { 76, 0, 57},
275/* 229 */ { 76, 38, 66},
276/* 230 */ {255, 0, 127},
277/* 231 */ {255, 127, 191},
278/* 232 */ {204, 0, 102},
279/* 233 */ {204, 102, 153},
280/* 234 */ {153, 0, 76},
281/* 235 */ {153, 76, 114},
282/* 236 */ {127, 0, 63},
283/* 237 */ {127, 63, 95},
284/* 238 */ { 76, 0, 38},
285/* 239 */ { 76, 38, 57},
286/* 240 */ {255, 0, 63},
287/* 241 */ {255, 127, 159},
288/* 242 */ {204, 0, 51},
289/* 243 */ {204, 102, 127},
290/* 244 */ {153, 0, 38},
291/* 245 */ {153, 76, 95},
292/* 246 */ {127, 0, 31},
293/* 247 */ {127, 63, 79},
294/* 248 */ { 76, 0, 19},
295/* 249 */ { 76, 38, 47},
296/* 250 */ { 51, 51, 51},
297/* 251 */ { 91, 91, 91},
298/* 252 */ {132, 132, 132},
299/* 253 */ {173, 173, 173},
300/* 254 */ {214, 214, 214},
301/* 255 */ {255, 255, 255}
302};
303
304inline DXFVector Cross(const DXFVector& v1, const DXFVector& v2)
305{
306 return DXFVector(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
307}
308
309void DXFFace::CalculateNormal()
310{
311 DXFVector v01, v02;
312 v01.x = v0.x - v1.x;
313 v01.y = v0.y - v1.y;
314 v01.z = v0.z - v1.z;
315 v02.x = v0.x - v2.x;
316 v02.y = v0.y - v2.y;
317 v02.z = v0.z - v2.z;
318 n = Cross(v01, v02);
319 float mod = sqrt(n.x*n.x + n.y*n.y + n.z*n.z);
320 n.x /= mod;
321 n.y /= mod;
322 n.z /= mod;
323}
324
325// convert an AutoCAD ACI colour to wxWidgets RGB colour
326inline wxColour ACIColourToRGB(int col)
327{
328 wxASSERT(col >= 0 && col <= 255);
329 return wxColour(aci_to_rgb[col].r, aci_to_rgb[col].g, aci_to_rgb[col].b);
330}
331
332// DXFReader constructor
333DXFRenderer::DXFRenderer()
334{
335 m_loaded = false;
336}
337
338// DXFReader destructor
339DXFRenderer::~DXFRenderer()
340{
341 Clear();
342}
343
344// deallocate all the dynamic data
345void DXFRenderer::Clear()
346{
347 m_loaded = false;
348 {
349 for (DXFLayerList::compatibility_iterator node = m_layers.GetFirst(); node; node = node->GetNext())
350 {
351 DXFLayer *current = node->GetData();
352 delete current;
353 }
354 }
355 m_layers.Clear();
356 {
357 for (DXFEntityList::compatibility_iterator node = m_entities.GetFirst(); node; node = node->GetNext())
358 {
359 DXFEntity *current = node->GetData();
360 delete current;
361 }
362 m_entities.Clear();
363 }
364}
365
366int DXFRenderer::GetLayerColour(const wxString& layer) const
367{
368 for (DXFLayerList::compatibility_iterator node = m_layers.GetFirst(); node; node = node->GetNext())
369 {
370 DXFLayer *current = node->GetData();
371 if (current->name == layer)
372 return current->colour;
373 }
374 return 7; // white
375}
376
377// read two sequential lines
378inline void GetLines(wxTextInputStream& text, wxString& line1, wxString& line2)
379{
380 line1 = text.ReadLine().Trim().Trim(false);
381 line2 = text.ReadLine().Trim().Trim(false);
382}
383
384// parse header section: just skip everything
385bool DXFRenderer::ParseHeader(wxInputStream& stream)
386{
387 wxTextInputStream text(stream);
388 wxString line1, line2;
389 while (stream.CanRead())
390 {
391 GetLines(text, line1, line2);
392 if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
393 return true;
394 }
395 return false;
396}
397
398// parse tables section: save layers name and colour
399bool DXFRenderer::ParseTables(wxInputStream& stream)
400{
401 wxTextInputStream text(stream);
402 wxString line1, line2;
403 bool inlayer=false;
404 DXFLayer layer;
405 while (stream.CanRead())
406 {
407 GetLines(text, line1, line2);
408 if (line1 == wxT("0") && inlayer)
409 {
410 // flush layer
411 if (!layer.name.IsEmpty() && layer.colour != -1)
412 {
413 DXFLayer *p = new DXFLayer;
414 p->name = layer.name;
415 p->colour = layer.colour;
416 m_layers.Append(p);
417 }
418 layer = DXFLayer();
419 inlayer = false;
420 }
421 if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
422 return true;
423 else if (line1 == wxT("0") && line2 == wxT("LAYER"))
424 inlayer = true;
425 else if (inlayer)
426 {
427 if (line1 == wxT("2")) // layer name
428 layer.name = line2;
429 else if (line1 == wxT("62")) // ACI colour
430 {
431 long l;
432 line2.ToLong(&l);
433 layer.colour = l;
434 }
435 }
436 }
437 return false;
438}
439
440// This method is used instead of numStr.ToDouble(d) because the latter
441// (wxString::ToDouble()) takes the systems proper locale into account,
442// whereas the implementation below works with the default locale.
443// (Converting numbers that are formatted in the default locale can fail
444// with system locales that use e.g. the comma as the decimal separator.)
445static double ToDouble(const wxString& numStr)
446{
447 double d;
448 std::string numStr_(numStr.c_str());
449 std::istringstream iss(numStr_);
450
451 iss >> d;
452
453 return d;
454}
455
456// parse entities section: save 3DFACE and LINE entities
457bool DXFRenderer::ParseEntities(wxInputStream& stream)
458{
459 wxTextInputStream text(stream);
460 wxString line1, line2;
461 int state = 0; // 0: none, 1: 3DFACE, 2: LINE
462 DXFVector v[4];
463 int colour = -1;
464 wxString layer;
465 while (stream.CanRead())
466 {
467 GetLines(text, line1, line2);
468 if (line1 == wxT("0") && state > 0)
469 {
470 // flush entity
471 if (state == 1) // 3DFACE
472 {
473 DXFFace *p = new DXFFace;
474 p->v0 = v[0];
475 p->v1 = v[1];
476 p->v2 = v[2];
477 p->v3 = v[3];
478 p->CalculateNormal();
479 if (colour != -1)
480 p->colour = colour;
481 else
482 p->colour = GetLayerColour(layer);
483 m_entities.Append(p);
484 colour = -1; layer = wxEmptyString;
485 v[0] = v[1] = v[2] = v[3] = DXFVector();
486 state = 0;
487 }
488 else if (state == 2) // LINE
489 {
490 DXFLine *p = new DXFLine;
491 p->v0 = v[0];
492 p->v1 = v[1];
493 if (colour != -1)
494 p->colour = colour;
495 else
496 p->colour = GetLayerColour(layer);
497 m_entities.Append(p);
498 colour = -1; layer = wxEmptyString;
499 v[0] = v[1] = v[2] = v[3] = DXFVector();
500 state = 0;
501 }
502 }
503 if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
504 return true;
505 else if (line1 == wxT("0") && line2 == wxT("3DFACE"))
506 state = 1;
507 else if (line1 == wxT("0") && line2 == wxT("LINE"))
508 state = 2;
509 else if (state > 0)
510 {
511 const double d=ToDouble(line2);
512
513 if (line1 == wxT("10"))
514 v[0].x = d;
515 else if (line1 == wxT("20"))
516 v[0].y = d;
517 else if (line1 == wxT("30"))
518 v[0].z = d;
519 else if (line1 == wxT("11"))
520 v[1].x = d;
521 else if (line1 == wxT("21"))
522 v[1].y = d;
523 else if (line1 == wxT("31"))
524 v[1].z = d;
525 else if (line1 == wxT("12"))
526 v[2].x = d;
527 else if (line1 == wxT("22"))
528 v[2].y = d;
529 else if (line1 == wxT("32"))
530 v[2].z = d;
531 else if (line1 == wxT("13"))
532 v[3].x = d;
533 else if (line1 == wxT("23"))
534 v[3].y = d;
535 else if (line1 == wxT("33"))
536 v[3].z = d;
537 else if (line1 == wxT("8")) // layer
538 layer = line2;
539 else if (line1 == wxT("62")) // colour
540 {
541 long l;
542 line2.ToLong(&l);
543 colour = l;
544 }
545 }
546 }
547 return false;
548}
549
550// parse and load a DXF file
551// currently pretty limited, but knows enought do handle 3DFACEs and LINEs
552bool DXFRenderer::Load(wxInputStream& stream)
553{
554 Clear();
555 wxTextInputStream text(stream);
556
557 wxString line1, line2;
558 while (stream.CanRead())
559 {
560 GetLines(text, line1, line2);
561 if (line1 == wxT("999")) // comment
562 continue;
563 else if (line1 == wxT("0") && line2 == wxT("SECTION"))
564 {
565 GetLines(text, line1, line2);
566 if (line1 == wxT("2"))
567 {
568 if (line2 == wxT("HEADER"))
569 {
570 if (!ParseHeader(stream))
571 return false;
572 }
573 else if (line2 == wxT("TABLES"))
574 {
575 if (!ParseTables(stream))
576 return false;
577 }
578 else if (line2 == wxT("ENTITIES"))
579 {
580 if (!ParseEntities(stream))
581 return false;
582 }
583 }
584 }
585 }
586
587 NormalizeEntities();
588 m_loaded = true;
589 return true;
590}
591
592inline float mymin(float x, float y) { return x < y ? x : y; }
593inline float mymax(float x, float y) { return x > y ? x : y; }
594
595// Scale object boundings to [-5,5]
596void DXFRenderer::NormalizeEntities()
597{
598 // calculate current min and max boundings of object
599 DXFVector minv(10e20f, 10e20f, 10e20f);
600 DXFVector maxv(-10e20f, -10e20f, -10e20f);
601 for (DXFEntityList::compatibility_iterator node = m_entities.GetFirst(); node; node = node->GetNext())
602 {
603 DXFEntity *p = node->GetData();
604 if (p->type == DXFEntity::Line)
605 {
606 DXFLine *line = (DXFLine *)p;
607 const DXFVector *v[2] = { &line->v0, &line->v1 };
608 for (int i = 0; i < 2; ++i)
609 {
610 minv.x = mymin(v[i]->x, minv.x);
611 minv.y = mymin(v[i]->y, minv.y);
612 minv.z = mymin(v[i]->z, minv.z);
613 maxv.x = mymax(v[i]->x, maxv.x);
614 maxv.y = mymax(v[i]->y, maxv.y);
615 maxv.z = mymax(v[i]->z, maxv.z);
616 }
617 } else if (p->type == DXFEntity::Face)
618 {
619 DXFFace *face = (DXFFace *)p;
620 const DXFVector *v[4] = { &face->v0, &face->v1, &face->v2, &face->v3 };
621 for (int i = 0; i < 4; ++i)
622 {
623 minv.x = mymin(v[i]->x, minv.x);
624 minv.y = mymin(v[i]->y, minv.y);
625 minv.z = mymin(v[i]->z, minv.z);
626 maxv.x = mymax(v[i]->x, maxv.x);
627 maxv.y = mymax(v[i]->y, maxv.y);
628 maxv.z = mymax(v[i]->z, maxv.z);
629 }
630 }
631 }
632
633 // rescale object down to [-5,5]
634 DXFVector span(maxv.x - minv.x, maxv.y - minv.y, maxv.z - minv.z);
635 float factor = mymin(mymin(10.0f / span.x, 10.0f / span.y), 10.0f / span.z);
636 for (DXFEntityList::compatibility_iterator node2 = m_entities.GetFirst(); node2; node2 = node2->GetNext())
637 {
638 DXFEntity *p = node2->GetData();
639 if (p->type == DXFEntity::Line)
640 {
641 DXFLine *line = (DXFLine *)p;
642 DXFVector *v[2] = { &line->v0, &line->v1 };
643 for (int i = 0; i < 2; ++i)
644 {
645 v[i]->x -= minv.x + span.x/2; v[i]->x *= factor;
646 v[i]->y -= minv.y + span.y/2; v[i]->y *= factor;
647 v[i]->z -= minv.z + span.z/2; v[i]->z *= factor;
648 }
649 } else if (p->type == DXFEntity::Face)
650 {
651 DXFFace *face = (DXFFace *)p;
652 DXFVector *v[4] = { &face->v0, &face->v1, &face->v2, &face->v3 };
653 for (int i = 0; i < 4; ++i)
654 {
655 v[i]->x -= minv.x + span.x/2; v[i]->x *= factor;
656 v[i]->y -= minv.y + span.y/2; v[i]->y *= factor;
657 v[i]->z -= minv.z + span.z/2; v[i]->z *= factor;
658 }
659 }
660 }
661}
662
663// OpenGL renderer for DXF entities
664void DXFRenderer::Render() const
665{
666 if (!m_loaded)
667 return;
668
669 for (DXFEntityList::compatibility_iterator node = m_entities.GetFirst(); node; node = node->GetNext())
670 {
671 DXFEntity *p = node->GetData();
672 wxColour c = ACIColourToRGB(p->colour);
673 if (p->type == DXFEntity::Line)
674 {
675 DXFLine *line = (DXFLine *)p;
676 glBegin(GL_LINES);
677 glColor3f(c.Red()/255.0,c.Green()/255.0,c.Blue()/255.0);
678 glVertex3f(line->v0.x, line->v0.y, line->v0.z);
679 glVertex3f(line->v1.x, line->v1.y, line->v1.z);
680 glEnd();
681 }
682 else if (p->type == DXFEntity::Face)
683 {
684 DXFFace *face = (DXFFace *)p;
685 glBegin(GL_TRIANGLES);
686 glColor3f(c.Red()/255.0,c.Green()/255.0,c.Blue()/255.0);
687 glNormal3f(face->n.x, face->n.y, face->n.z);
688 glVertex3f(face->v0.x, face->v0.y, face->v0.z);
689 glVertex3f(face->v1.x, face->v1.y, face->v1.z);
690 glVertex3f(face->v2.x, face->v2.y, face->v2.z);
691 glEnd();
692 }
693 }
694}