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