|
1 #include "gldata.h" |
|
2 #include "ldtypes.h" |
|
3 #include "colors.h" |
|
4 #include "file.h" |
|
5 #include "misc.h" |
|
6 #include "gldraw.h" |
|
7 |
|
8 cfg (bool, gl_blackedges, true); |
|
9 |
|
10 // ============================================================================= |
|
11 // ----------------------------------------------------------------------------- |
|
12 VertexCompiler::Array::Array() : |
|
13 m_data (null) |
|
14 { |
|
15 clear(); |
|
16 } |
|
17 |
|
18 // ============================================================================= |
|
19 // ----------------------------------------------------------------------------- |
|
20 VertexCompiler::Array::~Array() { |
|
21 delete[] m_data; |
|
22 } |
|
23 |
|
24 // ============================================================================= |
|
25 // ----------------------------------------------------------------------------- |
|
26 void VertexCompiler::Array::clear() { |
|
27 delete[] m_data; |
|
28 |
|
29 m_data = new DataType[64]; |
|
30 m_size = 64; |
|
31 m_ptr = &m_data[0]; |
|
32 } |
|
33 |
|
34 // ============================================================================= |
|
35 // ----------------------------------------------------------------------------- |
|
36 void VertexCompiler::Array::resizeToFit ( |
|
37 VertexCompiler::Array::SizeType newSize |
|
38 ) { |
|
39 if (allocatedSize() >= newSize) |
|
40 return; |
|
41 |
|
42 int32 cachedWriteSize = writtenSize(); |
|
43 |
|
44 // Add some lee-way space to reduce the amount of resizing. |
|
45 newSize += 256; |
|
46 |
|
47 const SizeType oldSize = allocatedSize(); |
|
48 |
|
49 // We need to back up the data first |
|
50 DataType* copy = new DataType[oldSize]; |
|
51 memcpy (copy, m_data, oldSize); |
|
52 |
|
53 // Re-create the buffer |
|
54 delete[] m_data; |
|
55 m_data = new DataType[newSize]; |
|
56 m_size = newSize; |
|
57 m_ptr = &m_data[cachedWriteSize / sizeof (DataType)]; |
|
58 |
|
59 // Copy the data back |
|
60 memcpy (m_data, copy, oldSize); |
|
61 delete[] copy; |
|
62 } |
|
63 |
|
64 // ============================================================================= |
|
65 // ----------------------------------------------------------------------------- |
|
66 const VertexCompiler::Array::DataType* VertexCompiler::Array::data() const { |
|
67 return m_data; |
|
68 } |
|
69 |
|
70 // ============================================================================= |
|
71 // ----------------------------------------------------------------------------- |
|
72 const VertexCompiler::Array::SizeType& VertexCompiler::Array::allocatedSize() const { |
|
73 return m_size; |
|
74 } |
|
75 |
|
76 // ============================================================================= |
|
77 // ----------------------------------------------------------------------------- |
|
78 VertexCompiler::Array::SizeType VertexCompiler::Array::writtenSize() const { |
|
79 return (m_ptr - m_data) * sizeof (DataType); |
|
80 } |
|
81 |
|
82 // ============================================================================= |
|
83 // ----------------------------------------------------------------------------- |
|
84 void VertexCompiler::Array::write ( |
|
85 VertexCompiler::Array::DataType f |
|
86 ) { |
|
87 // Ensure there's enoughspace for the new float |
|
88 resizeToFit (writtenSize() + sizeof f); |
|
89 |
|
90 // Write the float in |
|
91 *m_ptr++ = f; |
|
92 } |
|
93 |
|
94 // ============================================================================= |
|
95 // ----------------------------------------------------------------------------- |
|
96 void VertexCompiler::Array::merge ( |
|
97 Array* other |
|
98 ) { |
|
99 // Ensure there's room for both buffers |
|
100 resizeToFit (writtenSize() + other->writtenSize()); |
|
101 |
|
102 memcpy (m_ptr, other->data(), other->writtenSize()); |
|
103 m_ptr += other->writtenSize() / sizeof (DataType); |
|
104 } |
|
105 |
|
106 // ============================================================================= |
|
107 // ----------------------------------------------------------------------------- |
|
108 VertexCompiler::VertexCompiler() : |
|
109 m_file (null) |
|
110 { |
|
111 for (int i = 0; i < NumArrays; ++i) { |
|
112 m_mainArrays[i] = new Array; |
|
113 m_changed[i] = false; |
|
114 } |
|
115 } |
|
116 |
|
117 // ============================================================================= |
|
118 // ----------------------------------------------------------------------------- |
|
119 VertexCompiler::~VertexCompiler() { |
|
120 for (Array* array : m_mainArrays) |
|
121 delete array; |
|
122 } |
|
123 |
|
124 // ============================================================================= |
|
125 // ----------------------------------------------------------------------------- |
|
126 void VertexCompiler::compileVertex ( |
|
127 vertex v, |
|
128 QColor col, |
|
129 Array* array |
|
130 ) { |
|
131 VertexCompiler::Vertex glvertex; |
|
132 glvertex.x = v.x(); |
|
133 glvertex.y = v.y(); |
|
134 glvertex.z = v.z(); |
|
135 glvertex.color = |
|
136 (col.red() & 0xFF) << 0x00 | |
|
137 (col.green() & 0xFF) << 0x08 | |
|
138 (col.blue() & 0xFF) << 0x10 | |
|
139 (col.alpha() & 0xFF) << 0x18; |
|
140 |
|
141 array->write (glvertex); |
|
142 } |
|
143 |
|
144 // ============================================================================= |
|
145 // ----------------------------------------------------------------------------- |
|
146 void VertexCompiler::compilePolygon ( |
|
147 LDObject* obj, |
|
148 VertexCompiler::Array** arrays |
|
149 ) { |
|
150 LDObject::Type objtype = obj->getType(); |
|
151 bool isline = (objtype == LDObject::Line || objtype == LDObject::CondLine); |
|
152 int verts = isline ? 2 : obj->vertices(); |
|
153 |
|
154 for (int i = 0; i < verts; ++i) { |
|
155 compileVertex (obj->getVertex (i), getObjectColor (obj, Normal), |
|
156 arrays[isline ? EdgeArray : MainArray]); |
|
157 } |
|
158 |
|
159 // For non-lines, compile BFC data |
|
160 if (!isline) { |
|
161 QColor col = getObjectColor (obj, BFCFront); |
|
162 for (int i = 0; i < verts; ++i) |
|
163 compileVertex (obj->getVertex(i), col, arrays[BFCArray]); |
|
164 |
|
165 col = getObjectColor (obj, BFCBack); |
|
166 for (int i = verts - 1; i >= 0; --i) |
|
167 compileVertex (obj->getVertex(i), col, arrays[BFCArray]); |
|
168 } |
|
169 } |
|
170 |
|
171 // ============================================================================= |
|
172 // ----------------------------------------------------------------------------- |
|
173 void VertexCompiler::compileObject ( |
|
174 LDObject* obj |
|
175 ) { |
|
176 if (m_objArrays.find (obj) == m_objArrays.end()) { |
|
177 m_objArrays[obj] = new Array*[NumArrays]; |
|
178 |
|
179 for (int i = 0; i < NumArrays; ++i) |
|
180 m_objArrays[obj][i] = new Array; |
|
181 } else { |
|
182 for (int i = 0; i < NumArrays; ++i) |
|
183 m_objArrays[obj][i]->clear(); |
|
184 } |
|
185 |
|
186 switch (obj->getType()) { |
|
187 case LDObject::Triangle: |
|
188 compilePolygon (obj, m_objArrays[obj]); |
|
189 m_changed[MainArray] = true; |
|
190 break; |
|
191 |
|
192 case LDObject::Quad: |
|
193 for (LDTriangleObject* triangle : static_cast<LDQuadObject*> (obj)->splitToTriangles()) |
|
194 compilePolygon (triangle, m_objArrays[obj]); |
|
195 m_changed[MainArray] = true; |
|
196 break; |
|
197 |
|
198 case LDObject::Line: |
|
199 compilePolygon (obj, m_objArrays[obj]); |
|
200 break; |
|
201 |
|
202 default: |
|
203 break; |
|
204 } |
|
205 } |
|
206 |
|
207 // ============================================================================= |
|
208 // ----------------------------------------------------------------------------- |
|
209 void VertexCompiler::compileFile() { |
|
210 for (LDObject* obj : *m_file) |
|
211 compileObject (obj); |
|
212 } |
|
213 |
|
214 // ============================================================================= |
|
215 // ----------------------------------------------------------------------------- |
|
216 void VertexCompiler::forgetObject ( |
|
217 LDObject* obj |
|
218 ) { |
|
219 for (int i = 0; i < NumArrays; ++i) |
|
220 delete m_objArrays[obj][i]; |
|
221 |
|
222 delete m_objArrays[obj]; |
|
223 m_objArrays.remove (obj); |
|
224 } |
|
225 |
|
226 // ============================================================================= |
|
227 // ----------------------------------------------------------------------------- |
|
228 void VertexCompiler::setFile ( |
|
229 LDFile* file |
|
230 ) { |
|
231 m_file = file; |
|
232 } |
|
233 |
|
234 // ============================================================================= |
|
235 // ----------------------------------------------------------------------------- |
|
236 VertexCompiler::Array* VertexCompiler::getMergedBuffer ( |
|
237 VertexCompiler::MergedArrayType type |
|
238 ) { |
|
239 assert (type < NumArrays); |
|
240 |
|
241 if (m_changed) { |
|
242 m_changed[type] = false; |
|
243 m_mainArrays[type]->clear(); |
|
244 |
|
245 for (LDObject* obj : *m_file) { |
|
246 auto it = m_objArrays.find (obj); |
|
247 |
|
248 if (it != m_objArrays.end()) |
|
249 m_mainArrays[type]->merge ((*it)[type]); |
|
250 } |
|
251 } |
|
252 |
|
253 return m_mainArrays[type]; |
|
254 } |
|
255 |
|
256 // ============================================================================= |
|
257 // ----------------------------------------------------------------------------- |
|
258 static List<short> g_warnedColors; |
|
259 QColor VertexCompiler::getObjectColor ( |
|
260 LDObject* obj, |
|
261 ColorType colotype |
|
262 ) const { |
|
263 QColor qcol; |
|
264 |
|
265 if (!obj->isColored()) |
|
266 return QColor(); |
|
267 |
|
268 /* |
|
269 if (list == GL::PickList) { |
|
270 // Make the color by the object's ID if we're picking, so we can make the |
|
271 // ID again from the color we get from the picking results. Be sure to use |
|
272 // the top level parent's index since we want a subfile's children point |
|
273 // to the subfile itself. |
|
274 long i = obj->topLevelParent()->id(); |
|
275 |
|
276 // Calculate a color based from this index. This method caters for |
|
277 // 16777216 objects. I don't think that'll be exceeded anytime soon. :) |
|
278 // ATM biggest is 53588.dat with 12600 lines. |
|
279 double r = (i / (256 * 256)) % 256, |
|
280 g = (i / 256) % 256, |
|
281 b = i % 256; |
|
282 |
|
283 qglColor (QColor (r, g, b)); |
|
284 return; |
|
285 } |
|
286 */ |
|
287 |
|
288 if ((colotype == BFCFront || colotype == BFCBack) && |
|
289 obj->getType() != LDObject::Line && |
|
290 obj->getType() != LDObject::CondLine) { |
|
291 |
|
292 if (colotype == BFCFront) |
|
293 qcol = QColor (40, 192, 0); |
|
294 else |
|
295 qcol = QColor (224, 0, 0); |
|
296 } else { |
|
297 if (obj->color() == maincolor) |
|
298 qcol = GL::getMainColor(); |
|
299 else { |
|
300 LDColor* col = getColor (obj->color()); |
|
301 |
|
302 if (col) |
|
303 qcol = col->faceColor; |
|
304 } |
|
305 |
|
306 if (obj->color() == edgecolor) { |
|
307 qcol = QColor (32, 32, 32); // luma (m_bgcolor) < 40 ? QColor (64, 64, 64) : Qt::black; |
|
308 LDColor* col; |
|
309 |
|
310 if (!gl_blackedges && obj->parent() && (col = getColor (obj->parent()->color()))) |
|
311 qcol = col->edgeColor; |
|
312 } |
|
313 |
|
314 if (qcol.isValid() == false) { |
|
315 // The color was unknown. Use main color to make the object at least |
|
316 // not appear pitch-black. |
|
317 if (obj->color() != edgecolor) |
|
318 qcol = GL::getMainColor(); |
|
319 |
|
320 // Warn about the unknown colors, but only once. |
|
321 for (short i : g_warnedColors) |
|
322 if (obj->color() == i) |
|
323 return Qt::black; |
|
324 |
|
325 print ("%1: Unknown color %2!\n", __func__, obj->color()); |
|
326 g_warnedColors << obj->color(); |
|
327 return Qt::black; |
|
328 } |
|
329 } |
|
330 |
|
331 if (obj->topLevelParent()->selected()) { |
|
332 // Brighten it up for the select list. |
|
333 const uchar add = 51; |
|
334 |
|
335 qcol.setRed (min (qcol.red() + add, 255)); |
|
336 qcol.setGreen (min (qcol.green() + add, 255)); |
|
337 qcol.setBlue (min (qcol.blue() + add, 255)); |
|
338 } |
|
339 |
|
340 return qcol; |
|
341 } |