]>
git.saurik.com Git - wxWidgets.git/blob - samples/opengl/penguin/dxfrenderer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dxfrenderer.cpp
3 // Purpose: DXF reader and renderer
4 // Author: Sandro Sigala
8 // Copyright: (c) Sandro Sigala
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/wfstream.h"
24 #include "wx/txtstrm.h"
27 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
32 # include <OpenGL/glu.h>
40 #include "dxfrenderer.h"
42 #include <wx/listimpl.cpp>
43 WX_DEFINE_LIST(DXFEntityList
)
44 WX_DEFINE_LIST(DXFLayerList
)
46 // Conversion table from AutoCAD ACI colours to RGB values
47 static const struct { unsigned char r
, g
, b
; } aci_to_rgb
[256] = {
48 /* 0 */ 255, 255, 255,
55 /* 7 */ 255, 255, 255,
56 /* 8 */ 128, 128, 128,
57 /* 9 */ 192, 192, 192,
59 /* 11 */ 255, 127, 127,
61 /* 13 */ 204, 102, 102,
69 /* 21 */ 255, 159, 127,
71 /* 23 */ 204, 127, 102,
79 /* 31 */ 255, 191, 127,
81 /* 33 */ 204, 153, 102,
83 /* 35 */ 153, 114, 76,
89 /* 41 */ 255, 223, 127,
91 /* 43 */ 204, 178, 102,
93 /* 45 */ 153, 133, 76,
95 /* 47 */ 127, 111, 63,
99 /* 51 */ 255, 255, 127,
100 /* 52 */ 204, 204, 0,
101 /* 53 */ 204, 204, 102,
102 /* 54 */ 153, 153, 0,
103 /* 55 */ 153, 153, 76,
104 /* 56 */ 127, 127, 0,
105 /* 57 */ 127, 127, 63,
108 /* 60 */ 191, 255, 0,
109 /* 61 */ 223, 255, 127,
110 /* 62 */ 153, 204, 0,
111 /* 63 */ 178, 204, 102,
112 /* 64 */ 114, 153, 0,
113 /* 65 */ 133, 153, 76,
115 /* 67 */ 111, 127, 63,
118 /* 70 */ 127, 255, 0,
119 /* 71 */ 191, 255, 127,
120 /* 72 */ 102, 204, 0,
121 /* 73 */ 153, 204, 102,
123 /* 75 */ 114, 153, 76,
125 /* 77 */ 95, 127, 63,
129 /* 81 */ 159, 255, 127,
131 /* 83 */ 127, 204, 102,
133 /* 85 */ 95, 153, 76,
135 /* 87 */ 79, 127, 63,
139 /* 91 */ 127, 255, 127,
141 /* 93 */ 102, 204, 102,
143 /* 95 */ 76, 153, 76,
145 /* 97 */ 63, 127, 63,
148 /* 100 */ 0, 255, 63,
149 /* 101 */ 127, 255, 159,
150 /* 102 */ 0, 204, 51,
151 /* 103 */ 102, 204, 127,
152 /* 104 */ 0, 153, 38,
153 /* 105 */ 76, 153, 95,
154 /* 106 */ 0, 127, 31,
155 /* 107 */ 63, 127, 79,
157 /* 109 */ 38, 76, 47,
158 /* 110 */ 0, 255, 127,
159 /* 111 */ 127, 255, 191,
160 /* 112 */ 0, 204, 102,
161 /* 113 */ 102, 204, 153,
162 /* 114 */ 0, 153, 76,
163 /* 115 */ 76, 153, 114,
164 /* 116 */ 0, 127, 63,
165 /* 117 */ 63, 127, 95,
167 /* 119 */ 38, 76, 57,
168 /* 120 */ 0, 255, 191,
169 /* 121 */ 127, 255, 223,
170 /* 122 */ 0, 204, 153,
171 /* 123 */ 102, 204, 178,
172 /* 124 */ 0, 153, 114,
173 /* 125 */ 76, 153, 133,
174 /* 126 */ 0, 127, 95,
175 /* 127 */ 63, 127, 111,
177 /* 129 */ 38, 76, 66,
178 /* 130 */ 0, 255, 255,
179 /* 131 */ 127, 255, 255,
180 /* 132 */ 0, 204, 204,
181 /* 133 */ 102, 204, 204,
182 /* 134 */ 0, 153, 153,
183 /* 135 */ 76, 153, 153,
184 /* 136 */ 0, 127, 127,
185 /* 137 */ 63, 127, 127,
187 /* 139 */ 38, 76, 76,
188 /* 140 */ 0, 191, 255,
189 /* 141 */ 127, 223, 255,
190 /* 142 */ 0, 153, 204,
191 /* 143 */ 102, 178, 204,
192 /* 144 */ 0, 114, 153,
193 /* 145 */ 76, 133, 153,
194 /* 146 */ 0, 95, 127,
195 /* 147 */ 63, 111, 127,
197 /* 149 */ 38, 66, 76,
198 /* 150 */ 0, 127, 255,
199 /* 151 */ 127, 191, 255,
200 /* 152 */ 0, 102, 204,
201 /* 153 */ 102, 153, 204,
202 /* 154 */ 0, 76, 153,
203 /* 155 */ 76, 114, 153,
204 /* 156 */ 0, 63, 127,
205 /* 157 */ 63, 95, 127,
207 /* 159 */ 38, 57, 76,
208 /* 160 */ 0, 63, 255,
209 /* 161 */ 127, 159, 255,
210 /* 162 */ 0, 51, 204,
211 /* 163 */ 102, 127, 204,
212 /* 164 */ 0, 38, 153,
213 /* 165 */ 76, 95, 153,
214 /* 166 */ 0, 31, 127,
215 /* 167 */ 63, 79, 127,
217 /* 169 */ 38, 47, 76,
219 /* 171 */ 127, 127, 255,
221 /* 173 */ 102, 102, 204,
223 /* 175 */ 76, 76, 153,
225 /* 177 */ 63, 63, 127,
227 /* 179 */ 38, 38, 76,
228 /* 180 */ 63, 0, 255,
229 /* 181 */ 159, 127, 255,
230 /* 182 */ 51, 0, 204,
231 /* 183 */ 127, 102, 204,
232 /* 184 */ 38, 0, 153,
233 /* 185 */ 95, 76, 153,
234 /* 186 */ 31, 0, 127,
235 /* 187 */ 79, 63, 127,
237 /* 189 */ 47, 38, 76,
238 /* 190 */ 127, 0, 255,
239 /* 191 */ 191, 127, 255,
240 /* 192 */ 102, 0, 204,
241 /* 193 */ 153, 102, 204,
242 /* 194 */ 76, 0, 153,
243 /* 195 */ 114, 76, 153,
244 /* 196 */ 63, 0, 127,
245 /* 197 */ 95, 63, 127,
247 /* 199 */ 57, 38, 76,
248 /* 200 */ 191, 0, 255,
249 /* 201 */ 223, 127, 255,
250 /* 202 */ 153, 0, 204,
251 /* 203 */ 178, 102, 204,
252 /* 204 */ 114, 0, 153,
253 /* 205 */ 133, 76, 153,
254 /* 206 */ 95, 0, 127,
255 /* 207 */ 111, 63, 127,
257 /* 209 */ 66, 38, 76,
258 /* 210 */ 255, 0, 255,
259 /* 211 */ 255, 127, 255,
260 /* 212 */ 204, 0, 204,
261 /* 213 */ 204, 102, 204,
262 /* 214 */ 153, 0, 153,
263 /* 215 */ 153, 76, 153,
264 /* 216 */ 127, 0, 127,
265 /* 217 */ 127, 63, 127,
267 /* 219 */ 76, 38, 76,
268 /* 220 */ 255, 0, 191,
269 /* 221 */ 255, 127, 223,
270 /* 222 */ 204, 0, 153,
271 /* 223 */ 204, 102, 178,
272 /* 224 */ 153, 0, 114,
273 /* 225 */ 153, 76, 133,
274 /* 226 */ 127, 0, 95,
275 /* 227 */ 127, 63, 111,
277 /* 229 */ 76, 38, 66,
278 /* 230 */ 255, 0, 127,
279 /* 231 */ 255, 127, 191,
280 /* 232 */ 204, 0, 102,
281 /* 233 */ 204, 102, 153,
282 /* 234 */ 153, 0, 76,
283 /* 235 */ 153, 76, 114,
284 /* 236 */ 127, 0, 63,
285 /* 237 */ 127, 63, 95,
287 /* 239 */ 76, 38, 57,
288 /* 240 */ 255, 0, 63,
289 /* 241 */ 255, 127, 159,
290 /* 242 */ 204, 0, 51,
291 /* 243 */ 204, 102, 127,
292 /* 244 */ 153, 0, 38,
293 /* 245 */ 153, 76, 95,
294 /* 246 */ 127, 0, 31,
295 /* 247 */ 127, 63, 79,
297 /* 249 */ 76, 38, 47,
298 /* 250 */ 51, 51, 51,
299 /* 251 */ 91, 91, 91,
300 /* 252 */ 132, 132, 132,
301 /* 253 */ 173, 173, 173,
302 /* 254 */ 214, 214, 214,
303 /* 255 */ 255, 255, 255,
306 inline DXFVector
Cross(const DXFVector
& v1
, const DXFVector
& v2
)
308 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
);
311 void DXFFace::CalculateNormal()
321 float mod
= sqrt(n
.x
*n
.x
+ n
.y
*n
.y
+ n
.z
*n
.z
);
327 // convert an AutoCAD ACI colour to wxWidgets RGB colour
328 inline wxColour
ACIColourToRGB(int col
)
330 wxASSERT(col
>= 0 && col
<= 255);
331 return wxColour(aci_to_rgb
[col
].r
, aci_to_rgb
[col
].g
, aci_to_rgb
[col
].b
);
334 // DXFReader constructor
335 DXFRenderer::DXFRenderer()
340 // DXFReader destructor
341 DXFRenderer::~DXFRenderer()
346 // deallocate all the dynamic data
347 void DXFRenderer::Clear()
351 for (DXFLayerList::Node
*node
= m_layers
.GetFirst(); node
; node
= node
->GetNext())
353 DXFLayer
*current
= node
->GetData();
359 for (DXFEntityList::Node
*node
= m_entities
.GetFirst(); node
; node
= node
->GetNext())
361 DXFEntity
*current
= node
->GetData();
368 int DXFRenderer::GetLayerColour(const wxString
& layer
) const
370 for (DXFLayerList::Node
*node
= m_layers
.GetFirst(); node
; node
= node
->GetNext())
372 DXFLayer
*current
= node
->GetData();
373 if (current
->name
== layer
)
374 return current
->colour
;
379 // read two sequential lines
380 inline void GetLines(wxTextInputStream
& text
, wxString
& line1
, wxString
& line2
)
382 line1
= text
.ReadLine().Trim().Trim(false);
383 line2
= text
.ReadLine().Trim().Trim(false);
386 // parse header section: just skip everything
387 bool DXFRenderer::ParseHeader(wxInputStream
& stream
)
389 wxTextInputStream
text(stream
);
390 wxString line1
, line2
;
391 while (stream
.CanRead())
393 GetLines(text
, line1
, line2
);
394 if (line1
== wxT("0") && line2
== wxT("ENDSEC"))
400 // parse tables section: save layers name and colour
401 bool DXFRenderer::ParseTables(wxInputStream
& stream
)
403 wxTextInputStream
text(stream
);
404 wxString line1
, line2
;
407 while (stream
.CanRead())
409 GetLines(text
, line1
, line2
);
410 if (line1
== wxT("0") && inlayer
)
413 if (!layer
.name
.IsEmpty() && layer
.colour
!= -1)
415 DXFLayer
*p
= new DXFLayer
;
416 p
->name
= layer
.name
;
417 p
->colour
= layer
.colour
;
423 if (line1
== wxT("0") && line2
== wxT("ENDSEC"))
425 else if (line1
== wxT("0") && line2
== wxT("LAYER"))
429 if (line1
== wxT("2")) // layer name
431 else if (line1
== wxT("62")) // ACI colour
442 // parse entities section: save 3DFACE and LINE entities
443 bool DXFRenderer::ParseEntities(wxInputStream
& stream
)
445 wxTextInputStream
text(stream
);
446 wxString line1
, line2
;
447 int state
= 0; // 0: none, 1: 3DFACE, 2: LINE
451 while (stream
.CanRead())
453 GetLines(text
, line1
, line2
);
454 if (line1
== wxT("0") && state
> 0)
457 if (state
== 1) // 3DFACE
459 DXFFace
*p
= new DXFFace
;
464 p
->CalculateNormal();
468 p
->colour
= GetLayerColour(layer
);
469 m_entities
.Append(p
);
470 colour
= -1; layer
= wxEmptyString
;
471 v
[0] = v
[1] = v
[2] = v
[3] = DXFVector();
474 else if (state
== 2) // LINE
476 DXFLine
*p
= new DXFLine
;
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();
489 if (line1
== wxT("0") && line2
== wxT("ENDSEC"))
491 else if (line1
== wxT("0") && line2
== wxT("3DFACE"))
493 else if (line1
== wxT("0") && line2
== wxT("LINE"))
499 if (line1
== wxT("10"))
501 else if (line1
== wxT("20"))
503 else if (line1
== wxT("30"))
505 else if (line1
== wxT("11"))
507 else if (line1
== wxT("21"))
509 else if (line1
== wxT("31"))
511 else if (line1
== wxT("12"))
513 else if (line1
== wxT("22"))
515 else if (line1
== wxT("32"))
517 else if (line1
== wxT("13"))
519 else if (line1
== wxT("23"))
521 else if (line1
== wxT("33"))
523 else if (line1
== wxT("8")) // layer
525 else if (line1
== wxT("62")) // colour
536 // parse and load a DXF file
537 // currently pretty limited, but knows enought do handle 3DFACEs and LINEs
538 bool DXFRenderer::Load(wxInputStream
& stream
)
541 wxTextInputStream
text(stream
);
543 wxString line1
, line2
;
544 while (stream
.CanRead())
546 GetLines(text
, line1
, line2
);
547 if (line1
== wxT("999")) // comment
549 else if (line1
== wxT("0") && line2
== wxT("SECTION"))
551 GetLines(text
, line1
, line2
);
552 if (line1
== wxT("2"))
554 if (line2
== wxT("HEADER"))
556 if (!ParseHeader(stream
))
559 else if (line2
== wxT("TABLES"))
561 if (!ParseTables(stream
))
564 else if (line2
== wxT("ENTITIES"))
566 if (!ParseEntities(stream
))
578 inline float mymin(float x
, float y
) { return x
< y
? x
: y
; }
579 inline float mymax(float x
, float y
) { return x
> y
? x
: y
; }
581 // Scale object boundings to [-5,5]
582 void DXFRenderer::NormalizeEntities()
584 // calculate current min and max boundings of object
585 DXFVector
minv(10e20f
, 10e20f
, 10e20f
);
586 DXFVector
maxv(-10e20f
, -10e20f
, -10e20f
);
587 for (DXFEntityList::Node
*node
= m_entities
.GetFirst(); node
; node
= node
->GetNext())
589 DXFEntity
*p
= node
->GetData();
590 if (p
->type
== DXFEntity::Line
)
592 DXFLine
*line
= (DXFLine
*)p
;
593 const DXFVector
*v
[2] = { &line
->v0
, &line
->v1
};
594 for (int i
= 0; i
< 2; ++i
)
596 minv
.x
= mymin(v
[i
]->x
, minv
.x
);
597 minv
.y
= mymin(v
[i
]->y
, minv
.y
);
598 minv
.z
= mymin(v
[i
]->z
, minv
.z
);
599 maxv
.x
= mymax(v
[i
]->x
, maxv
.x
);
600 maxv
.y
= mymax(v
[i
]->y
, maxv
.y
);
601 maxv
.z
= mymax(v
[i
]->z
, maxv
.z
);
603 } else if (p
->type
== DXFEntity::Face
)
605 DXFFace
*face
= (DXFFace
*)p
;
606 const DXFVector
*v
[4] = { &face
->v0
, &face
->v1
, &face
->v2
, &face
->v3
};
607 for (int i
= 0; i
< 4; ++i
)
609 minv
.x
= mymin(v
[i
]->x
, minv
.x
);
610 minv
.y
= mymin(v
[i
]->y
, minv
.y
);
611 minv
.z
= mymin(v
[i
]->z
, minv
.z
);
612 maxv
.x
= mymax(v
[i
]->x
, maxv
.x
);
613 maxv
.y
= mymax(v
[i
]->y
, maxv
.y
);
614 maxv
.z
= mymax(v
[i
]->z
, maxv
.z
);
619 // rescale object down to [-5,5]
620 DXFVector
span(maxv
.x
- minv
.x
, maxv
.y
- minv
.y
, maxv
.z
- minv
.z
);
621 float factor
= mymin(mymin(10.0f
/ span
.x
, 10.0f
/ span
.y
), 10.0f
/ span
.z
);
622 for (DXFEntityList::Node
*node2
= m_entities
.GetFirst(); node2
; node2
= node2
->GetNext())
624 DXFEntity
*p
= node2
->GetData();
625 if (p
->type
== DXFEntity::Line
)
627 DXFLine
*line
= (DXFLine
*)p
;
628 DXFVector
*v
[2] = { &line
->v0
, &line
->v1
};
629 for (int i
= 0; i
< 2; ++i
)
631 v
[i
]->x
-= minv
.x
+ span
.x
/2; v
[i
]->x
*= factor
;
632 v
[i
]->y
-= minv
.y
+ span
.y
/2; v
[i
]->y
*= factor
;
633 v
[i
]->z
-= minv
.z
+ span
.z
/2; v
[i
]->z
*= factor
;
635 } else if (p
->type
== DXFEntity::Face
)
637 DXFFace
*face
= (DXFFace
*)p
;
638 DXFVector
*v
[4] = { &face
->v0
, &face
->v1
, &face
->v2
, &face
->v3
};
639 for (int i
= 0; i
< 4; ++i
)
641 v
[i
]->x
-= minv
.x
+ span
.x
/2; v
[i
]->x
*= factor
;
642 v
[i
]->y
-= minv
.y
+ span
.y
/2; v
[i
]->y
*= factor
;
643 v
[i
]->z
-= minv
.z
+ span
.z
/2; v
[i
]->z
*= factor
;
649 // OpenGL renderer for DXF entities
650 void DXFRenderer::Render() const
655 for (DXFEntityList::Node
*node
= m_entities
.GetFirst(); node
; node
= node
->GetNext())
657 DXFEntity
*p
= node
->GetData();
658 wxColour c
= ACIColourToRGB(p
->colour
);
659 if (p
->type
== DXFEntity::Line
)
661 DXFLine
*line
= (DXFLine
*)p
;
663 glColor3f(c
.Red()/255.0,c
.Green()/255.0,c
.Blue()/255.0);
664 glVertex3f(line
->v0
.x
, line
->v0
.y
, line
->v0
.z
);
665 glVertex3f(line
->v1
.x
, line
->v1
.y
, line
->v1
.z
);
668 else if (p
->type
== DXFEntity::Face
)
670 DXFFace
*face
= (DXFFace
*)p
;
671 glBegin(GL_TRIANGLES
);
672 glColor3f(c
.Red()/255.0,c
.Green()/255.0,c
.Blue()/255.0);
673 glNormal3f(face
->n
.x
, face
->n
.y
, face
->n
.z
);
674 glVertex3f(face
->v0
.x
, face
->v0
.y
, face
->v0
.z
);
675 glVertex3f(face
->v1
.x
, face
->v1
.y
, face
->v1
.z
);
676 glVertex3f(face
->v2
.x
, face
->v2
.y
, face
->v2
.z
);