src/gldata.cc

changeset 672
0925d25ea32c
parent 671
14a6da9c0bfe
child 673
8e6f5b3f9d38
equal deleted inserted replaced
671:14a6da9c0bfe 672:0925d25ea32c
1 #include <cstring>
2 #include "gldata.h"
3 #include "ldtypes.h"
4 #include "colors.h"
5 #include "document.h"
6 #include "misc.h"
7 #include "gldraw.h"
8 #include <QDate>
9
10 #define DEBUG_PRINT(...) fprint (stdout, __VA_ARGS__)
11
12 extern_cfg (Bool, gl_blackedges);
13 static QList<short> g_warnedColors;
14 VertexCompiler g_vertexCompiler;
15
16 // =============================================================================
17 // -----------------------------------------------------------------------------
18 VertexCompiler::VertexCompiler() :
19 m_file (null)
20 {
21 needMerge();
22 }
23
24 VertexCompiler::~VertexCompiler() {}
25
26 // =============================================================================
27 // Note: we use the top level object's color but the draw object's vertices.
28 // This is so that the index color is generated correctly - it has to reference
29 // the top level object's ID. This is crucial for picking to work.
30 // -----------------------------------------------------------------------------
31 void VertexCompiler::compilePolygon (LDObject* drawobj, LDObject* trueobj, QList< VertexCompiler::CompiledTriangle >& data)
32 {
33 const QColor pickColor = getObjectColor (trueobj, PickColor);
34 LDObject::Type type = drawobj->getType();
35 LDObjectList objs;
36
37 assert (type != LDObject::ESubfile);
38
39 if (type == LDObject::EQuad)
40 {
41 for (LDTriangle* t : static_cast<LDQuad*> (drawobj)->splitToTriangles())
42 objs << t;
43 }
44 else
45 objs << drawobj;
46
47 for (LDObject* obj : objs)
48 {
49 const LDObject::Type objtype = obj->getType();
50 const bool isline = (objtype == LDObject::ELine || objtype == LDObject::ECondLine);
51 const int verts = isline ? 2 : obj->vertices();
52 QColor normalColor = getObjectColor (obj, Normal);
53
54 assert (isline || objtype == LDObject::ETriangle);
55
56 CompiledTriangle a;
57 a.rgb = getColorRGB (normalColor);
58 a.pickrgb = getColorRGB (pickColor);
59 a.numVerts = verts;
60 a.obj = trueobj;
61 a.isCondLine = (objtype == LDObject::ECondLine);
62
63 for (int i = 0; i < verts; ++i)
64 {
65 a.verts[i] = obj->getVertex (i);
66 a.verts[i].y() = -a.verts[i].y();
67 a.verts[i].z() = -a.verts[i].z();
68 }
69
70 data << a;
71 }
72 }
73
74 // =============================================================================
75 // -----------------------------------------------------------------------------
76 void VertexCompiler::compileObject (LDObject* obj)
77 {
78 initObject (obj);
79 QList<CompiledTriangle> data;
80 QTime t0;
81
82 t0 = QTime::currentTime();
83 for (int i = 0; i < GL::ENumArrays; ++i)
84 m_objArrays[obj][i].clear();
85 DEBUG_PRINT ("INIT: %1ms\n", t0.msecsTo (QTime::currentTime()));
86
87 t0 = QTime::currentTime();
88 compileSubObject (obj, obj, data);
89 DEBUG_PRINT ("COMPILATION: %1ms\n", t0.msecsTo (QTime::currentTime()));
90
91 t0 = QTime::currentTime();
92
93 for (int i = 0; i < GL::ENumArrays; ++i)
94 {
95 GL::VAOType type = (GL::VAOType) i;
96 const bool islinearray = (type == GL::EEdgeArray || type == GL::EEdgePickArray);
97
98 for (const CompiledTriangle & poly : data)
99 {
100 if (poly.isCondLine)
101 {
102 // Conditional lines go to the edge pick array and the array
103 // specifically designated for conditional lines and nowhere else.
104 if (type != GL::EEdgePickArray && type != GL::ECondEdgeArray)
105 continue;
106 }
107 else
108 {
109 // Lines and only lines go to the line array and only to the line array.
110 if ( (poly.numVerts == 2) ^ islinearray)
111 continue;
112
113 // Only conditional lines go into the conditional line array
114 if (type == GL::ECondEdgeArray)
115 continue;
116 }
117
118 Array* verts = postprocess (poly, type);
119 m_objArrays[obj][type] += *verts;
120 delete verts;
121 }
122 }
123
124 DEBUG_PRINT ("POST-PROCESS: %1ms\n", t0.msecsTo (QTime::currentTime()));
125
126 needMerge();
127 }
128
129 // =============================================================================
130 // -----------------------------------------------------------------------------
131 void VertexCompiler::compileSubObject (LDObject* obj, LDObject* topobj, VertexCompiler::PolygonList& data)
132 {
133 LDObjectList objs;
134
135 switch (obj->getType())
136 {
137 case LDObject::ETriangle:
138 case LDObject::ELine:
139 case LDObject::ECondLine:
140 {
141 compilePolygon (obj, topobj, data);
142 } break;
143
144 case LDObject::EQuad:
145 {
146 QTime t0 = QTime::currentTime();
147 for (LDTriangle* triangle : static_cast<LDQuad*> (obj)->splitToTriangles())
148 compilePolygon (triangle, topobj, data);
149 DEBUG_PRINT ("\t- QUAD COMPILE: %1ms\n", t0.msecsTo (QTime::currentTime()));
150 } break;
151
152 case LDObject::ESubfile:
153 {
154 QTime t0 = QTime::currentTime();
155 objs = static_cast<LDSubfile*> (obj)->inlineContents (LDSubfile::RendererInline | LDSubfile::DeepCacheInline);
156 DEBUG_PRINT ("\t- INLINE: %1ms\n", t0.msecsTo (QTime::currentTime()));
157 DEBUG_PRINT ("\t- %1 objects\n", objs.size());
158
159 t0 = QTime::currentTime();
160
161 for (LDObject* obj : objs)
162 {
163 compileSubObject (obj, topobj, data);
164 obj->deleteSelf();
165 }
166
167 DEBUG_PRINT ("\t- SUB-COMPILATION: %1ms\n", t0.msecsTo (QTime::currentTime()));
168 } break;
169
170 default:
171 {} break;
172 }
173 }
174
175 // =============================================================================
176 // -----------------------------------------------------------------------------
177 void VertexCompiler::compileDocument()
178 {
179 for (LDObject * obj : m_file->getObjects())
180 compileObject (obj);
181 }
182
183 // =============================================================================
184 // -----------------------------------------------------------------------------
185 void VertexCompiler::forgetObject (LDObject* obj)
186 {
187 auto it = m_objArrays.find (obj);
188
189 if (it != m_objArrays.end())
190 delete *it;
191
192 m_objArrays.remove (obj);
193 }
194
195 // =============================================================================
196 // -----------------------------------------------------------------------------
197 void VertexCompiler::setFile (LDDocument* file)
198 {
199 m_file = file;
200 }
201
202 // =============================================================================
203 // -----------------------------------------------------------------------------
204 const VertexCompiler::Array* VertexCompiler::getMergedBuffer (GL::VAOType type)
205 {
206 // If there are objects staged for compilation, compile them now.
207 if (m_staged.size() > 0)
208 {
209 for (LDObject * obj : m_staged)
210 compileObject (obj);
211
212 m_staged.clear();
213 }
214
215 assert (type < GL::ENumArrays);
216
217 if (m_changed[type])
218 {
219 m_changed[type] = false;
220 m_mainArrays[type].clear();
221
222 for (LDObject* obj : m_file->getObjects())
223 {
224 if (!obj->isScemantic())
225 continue;
226
227 auto it = m_objArrays.find (obj);
228
229 if (it != m_objArrays.end())
230 m_mainArrays[type] += (*it)[type];
231 }
232
233 DEBUG_PRINT ("merged array %1: %2 entries\n", (int) type, m_mainArrays[type].size());
234 }
235
236 return &m_mainArrays[type];
237 }
238
239 // =============================================================================
240 // This turns a compiled triangle into usable VAO vertices
241 // -----------------------------------------------------------------------------
242 VertexCompiler::Array* VertexCompiler::postprocess (const CompiledTriangle& poly, GLRenderer::VAOType type)
243 {
244 Array* va = new Array;
245 QList<Vertex> verts;
246
247 for (int i = 0; i < poly.numVerts; ++i)
248 {
249 alias v0 = poly.verts[i];
250 Vertex v;
251 v.x = v0.x();
252 v.y = v0.y();
253 v.z = v0.z();
254
255 switch (type)
256 {
257 case GL::ESurfaceArray:
258 case GL::EEdgeArray:
259 case GL::ECondEdgeArray:
260 {
261 v.color = poly.rgb;
262 } break;
263
264 case GL::EPickArray:
265 case GL::EEdgePickArray:
266 {
267 v.color = poly.pickrgb;
268 } break;
269
270 case GL::EBFCArray:
271 case GL::ENumArrays:
272 break; // handled separately
273 }
274
275 verts << v;
276 }
277
278 if (type == GL::EBFCArray)
279 {
280 int32 rgb = getColorRGB (getObjectColor (poly.obj, BFCFront));
281
282 for (Vertex v : verts)
283 {
284 v.color = rgb;
285 *va << v;
286 }
287
288 rgb = getColorRGB (getObjectColor (poly.obj, BFCBack));
289
290 for (int i = verts.size() - 1; i >= 0; --i)
291 {
292 Vertex v = verts[i];
293 v.color = rgb;
294 *va << v;
295 }
296 }
297 else
298 {
299 for (Vertex v : verts)
300 *va << v;
301 }
302
303 return va;
304 }
305
306 // =============================================================================
307 // -----------------------------------------------------------------------------
308 uint32 VertexCompiler::getColorRGB (const QColor& color)
309 {
310 return
311 (color.red() & 0xFF) << 0x00 |
312 (color.green() & 0xFF) << 0x08 |
313 (color.blue() & 0xFF) << 0x10 |
314 (color.alpha() & 0xFF) << 0x18;
315 }
316
317 // =============================================================================
318 // -----------------------------------------------------------------------------
319 QColor VertexCompiler::getObjectColor (LDObject* obj, ColorType colotype) const
320 {
321 QColor qcol;
322
323 if (!obj->isColored())
324 return QColor();
325
326 if (colotype == PickColor)
327 {
328 // Make the color by the object's ID if we're picking, so we can make the
329 // ID again from the color we get from the picking results. Be sure to use
330 // the top level parent's index since we want a subfile's children point
331 // to the subfile itself.
332 long i = obj->topLevelParent()->getID();
333
334 // Calculate a color based from this index. This method caters for
335 // 16777216 objects. I don't think that'll be exceeded anytime soon. :)
336 // ATM biggest is 53588.dat with 12600 lines.
337 int r = (i / 0x10000) % 0x100,
338 g = (i / 0x100) % 0x100,
339 b = i % 0x100;
340
341 return QColor (r, g, b);
342 }
343
344 if ( (colotype == BFCFront || colotype == BFCBack) &&
345 obj->getType() != LDObject::ELine &&
346 obj->getType() != LDObject::ECondLine
347 )
348 {
349 if (colotype == BFCFront)
350 qcol = QColor (40, 192, 0);
351 else
352 qcol = QColor (224, 0, 0);
353 }
354 else
355 {
356 if (obj->getColor() == maincolor)
357 qcol = GL::getMainColor();
358 else
359 {
360 LDColor* col = getColor (obj->getColor());
361
362 if (col)
363 qcol = col->faceColor;
364 }
365
366 if (obj->getColor() == edgecolor)
367 {
368 qcol = QColor (32, 32, 32); // luma (m_bgcolor) < 40 ? QColor (64, 64, 64) : Qt::black;
369 LDColor* col;
370
371 if (!gl_blackedges && obj->getParent() && (col = getColor (obj->getParent()->getColor())))
372 qcol = col->edgeColor;
373 }
374
375 if (qcol.isValid() == false)
376 {
377 // The color was unknown. Use main color to make the object at least
378 // not appear pitch-black.
379 if (obj->getColor() != edgecolor)
380 qcol = GL::getMainColor();
381 else
382 qcol = Qt::black;
383
384 // Warn about the unknown color, but only once.
385 for (short i : g_warnedColors)
386 if (obj->getColor() == i)
387 return qcol;
388
389 log ("%1: Unknown color %2!\n", __func__, obj->getColor());
390 g_warnedColors << obj->getColor();
391 return qcol;
392 }
393 }
394
395 if (obj->topLevelParent()->isSelected())
396 {
397 // Brighten it up if selected.
398 const int add = 51;
399
400 qcol.setRed (min (qcol.red() + add, 255));
401 qcol.setGreen (min (qcol.green() + add, 255));
402 qcol.setBlue (min (qcol.blue() + add, 255));
403 }
404
405 return qcol;
406 }
407
408 // =============================================================================
409 // -----------------------------------------------------------------------------
410 void VertexCompiler::needMerge()
411 {
412 // Set all of m_changed to true
413 memset (m_changed, 0xFF, sizeof m_changed);
414 }
415
416 // =============================================================================
417 // -----------------------------------------------------------------------------
418 void VertexCompiler::initObject (LDObject* obj)
419 {
420 if (m_objArrays.find (obj) == m_objArrays.end())
421 m_objArrays[obj] = new Array[GL::ENumArrays];
422 }
423
424 // =============================================================================
425 // -----------------------------------------------------------------------------
426 void VertexCompiler::stageForCompilation (LDObject* obj)
427 {
428 m_staged << obj;
429 removeDuplicates (m_staged);
430 }
431

mercurial