23 #include "config.h" |
23 #include "config.h" |
24 #include "file.h" |
24 #include "file.h" |
25 #include "gldraw.h" |
25 #include "gldraw.h" |
26 #include "bbox.h" |
26 #include "bbox.h" |
27 #include "colors.h" |
27 #include "colors.h" |
|
28 #include "gui.h" |
28 |
29 |
29 static double g_faObjectOffset[3]; |
30 static double g_faObjectOffset[3]; |
30 static double g_StoredBBoxSize; |
31 static double g_StoredBBoxSize; |
|
32 static bool g_bPicking = false; |
31 |
33 |
32 cfg (str, gl_bgcolor, "#CCCCD9"); |
34 cfg (str, gl_bgcolor, "#CCCCD9"); |
33 cfg (str, gl_maincolor, "#707078"); |
35 cfg (str, gl_maincolor, "#707078"); |
34 cfg (float, gl_maincolor_alpha, 1.0); |
36 cfg (float, gl_maincolor_alpha, 1.0); |
35 cfg (int, gl_linethickness, 2); |
37 cfg (int, gl_linethickness, 2); |
36 cfg (bool, gl_colorbfc, true); |
38 cfg (bool, gl_colorbfc, true); |
37 |
39 |
38 // ============================================================================= |
40 // ========================================================================= // |
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
41 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
40 // ============================================================================= |
42 // ========================================================================= // |
41 renderer::renderer (QWidget* parent) { |
43 renderer::renderer (QWidget* parent) { |
42 parent = parent; // shhh, GCC |
44 parent = parent; // shhh, GCC |
43 fRotX = fRotY = fRotZ = 0.0f; |
45 fRotX = fRotY = fRotZ = 0.0f; |
44 fZoom = 1.0f; |
46 fZoom = 1.0f; |
45 } |
47 } |
46 |
48 |
47 // ============================================================================= |
49 // ========================================================================= // |
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
50 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
49 // ============================================================================= |
51 // ========================================================================= // |
50 void renderer::initializeGL () { |
52 void renderer::initializeGL () { |
51 glLoadIdentity(); |
53 glLoadIdentity(); |
52 glMatrixMode (GL_MODELVIEW); |
54 glMatrixMode (GL_MODELVIEW); |
53 |
55 |
54 setBackground (); |
56 setBackground (); |
101 ((double)col.green()) / 255.0f, |
103 ((double)col.green()) / 255.0f, |
102 ((double)col.blue()) / 255.0f, |
104 ((double)col.blue()) / 255.0f, |
103 1.0f); |
105 1.0f); |
104 } |
106 } |
105 |
107 |
106 // ============================================================================= |
108 // ========================================================================= // |
107 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
109 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
108 // ============================================================================= |
110 // ========================================================================= // |
109 static vector<short> g_daWarnedColors; |
111 static vector<short> g_daWarnedColors; |
110 void renderer::setObjectColor (LDObject* obj, bool bBackSide) { |
112 void renderer::setObjectColor (LDObject* obj) { |
|
113 if (g_bPicking) { |
|
114 // Make the color by the object's index color if we're picking, so we can |
|
115 // make the index from the color we get from the picking results. |
|
116 long i = obj->getIndex (g_CurrentFile); |
|
117 |
|
118 // If we couldn't find the index, this object must not be from this file, |
|
119 // therefore it must be an object inlined from another file through a |
|
120 // subfile reference. Use the reference's index. |
|
121 if (i == -1) |
|
122 i = obj->topLevelParent ()->getIndex (g_CurrentFile); |
|
123 |
|
124 // We should have the index now. |
|
125 assert (i != -1); |
|
126 |
|
127 // Calculate a color based from this index. This method caters for |
|
128 // 16777216 objects. I don't think that'll be exceeded anytime soon. :) |
|
129 // ATM biggest is 53588.dat with 12600 lines. |
|
130 double r = i % 256; |
|
131 double g = (i / 256) % 256; |
|
132 double b = (i / (256 * 256)) % 256; |
|
133 |
|
134 glColor3f (r / 255.f, g / 255.f, b / 255.f); |
|
135 return; |
|
136 } |
|
137 |
111 if (obj->dColor == -1) |
138 if (obj->dColor == -1) |
112 return; |
139 return; |
113 |
140 |
|
141 #if 0 |
114 if (gl_colorbfc && |
142 if (gl_colorbfc && |
115 obj->getType () != OBJ_Line && |
143 obj->getType () != OBJ_Line && |
116 obj->getType () != OBJ_CondLine) |
144 obj->getType () != OBJ_CondLine) |
117 { |
145 { |
118 if (bBackSide) |
146 if (bBackSide) |
119 glColor4f (0.9f, 0.0f, 0.0f, 1.0f); |
147 glColor4f (0.9f, 0.0f, 0.0f, 1.0f); |
120 else |
148 else |
121 glColor4f (0.0f, 0.8f, 0.0f, 1.0f); |
149 glColor4f (0.0f, 0.8f, 0.0f, 1.0f); |
122 return; |
150 return; |
123 } |
151 } |
|
152 #endif |
124 |
153 |
125 if (obj->dColor == dMainColor) { |
154 if (obj->dColor == dMainColor) { |
126 setMainColor (); |
155 setMainColor (); |
127 return; |
156 return; |
128 } |
157 } |
149 ((double)col->qColor.green()) / 255.0f, |
178 ((double)col->qColor.green()) / 255.0f, |
150 ((double)col->qColor.blue()) / 255.0f, |
179 ((double)col->qColor.blue()) / 255.0f, |
151 ((double)col->qColor.alpha()) / 255.0f); |
180 ((double)col->qColor.alpha()) / 255.0f); |
152 } |
181 } |
153 |
182 |
154 // ============================================================================= |
183 // ========================================================================= // |
155 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
184 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
156 // ============================================================================= |
185 // ========================================================================= // |
157 void renderer::hardRefresh () { |
186 void renderer::hardRefresh () { |
158 compileObjects (); |
187 compileObjects (); |
159 paintGL (); |
188 paintGL (); |
160 swapBuffers (); |
189 swapBuffers (); |
161 |
190 |
162 glLineWidth (gl_linethickness); |
191 glLineWidth (gl_linethickness); |
163 } |
192 } |
164 |
193 |
165 // ============================================================================= |
194 // ========================================================================= // |
166 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
195 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
167 // ============================================================================= |
196 // ========================================================================= // |
168 void renderer::resizeGL (int w, int h) { |
197 void renderer::resizeGL (int w, int h) { |
169 glViewport (0, 0, w, h); |
198 glViewport (0, 0, w, h); |
170 glLoadIdentity (); |
199 glLoadIdentity (); |
171 glMatrixMode (GL_PROJECTION); |
200 glMatrixMode (GL_PROJECTION); |
172 gluPerspective (45.0f, (double)w / (double)h, 0.1f, 100.0f); |
201 gluPerspective (45.0f, (double)w / (double)h, 0.1f, 100.0f); |
173 } |
202 } |
174 |
203 |
175 // ============================================================================= |
204 // ========================================================================= // |
176 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
205 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
177 // ============================================================================= |
206 // ========================================================================= // |
178 void renderer::paintGL () { |
207 void renderer::paintGL () { |
179 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
208 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
180 glMatrixMode (GL_MODELVIEW); |
209 glMatrixMode (GL_MODELVIEW); |
181 |
210 |
182 glPushMatrix (); |
211 glPushMatrix (); |
187 |
216 |
188 glRotatef (fRotX, 1.0f, 0.0f, 0.0f); |
217 glRotatef (fRotX, 1.0f, 0.0f, 0.0f); |
189 glRotatef (fRotY, 0.0f, 1.0f, 0.0f); |
218 glRotatef (fRotY, 0.0f, 1.0f, 0.0f); |
190 glRotatef (fRotZ, 0.0f, 0.0f, 1.0f); |
219 glRotatef (fRotZ, 0.0f, 0.0f, 1.0f); |
191 |
220 |
192 if (gl_colorbfc) { |
221 for (GLuint uList : uaObjLists) |
193 glEnable (GL_CULL_FACE); |
222 glCallList (uList); |
194 |
|
195 glCullFace (GL_FRONT); |
|
196 glCallList (uObjList); |
|
197 |
|
198 glCullFace (GL_BACK); |
|
199 glCallList (uObjListBack); |
|
200 |
|
201 glDisable (GL_CULL_FACE); |
|
202 } else |
|
203 glCallList (uObjList); |
|
204 glPopMatrix (); |
223 glPopMatrix (); |
205 } |
224 } |
206 |
225 |
207 // ============================================================================= |
226 // ========================================================================= // |
208 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
227 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
209 // ============================================================================= |
228 // ========================================================================= // |
210 void renderer::compileObjects () { |
229 void renderer::compileObjects () { |
|
230 uaObjLists.clear (); |
|
231 |
211 g_faObjectOffset[0] = -(g_BBox.v0.x + g_BBox.v1.x) / 2; |
232 g_faObjectOffset[0] = -(g_BBox.v0.x + g_BBox.v1.x) / 2; |
212 g_faObjectOffset[1] = -(g_BBox.v0.y + g_BBox.v1.y) / 2; |
233 g_faObjectOffset[1] = -(g_BBox.v0.y + g_BBox.v1.y) / 2; |
213 g_faObjectOffset[2] = -(g_BBox.v0.z + g_BBox.v1.z) / 2; |
234 g_faObjectOffset[2] = -(g_BBox.v0.z + g_BBox.v1.z) / 2; |
214 g_StoredBBoxSize = g_BBox.calcSize (); |
235 g_StoredBBoxSize = g_BBox.calcSize (); |
215 printf ("bbox size is %f\n", g_StoredBBoxSize); |
236 printf ("bbox size is %f\n", g_StoredBBoxSize); |
217 if (!g_CurrentFile) { |
238 if (!g_CurrentFile) { |
218 printf ("renderer: no files loaded, cannot compile anything\n"); |
239 printf ("renderer: no files loaded, cannot compile anything\n"); |
219 return; |
240 return; |
220 } |
241 } |
221 |
242 |
222 GLuint* upaLists[2] = { |
243 for (LDObject* obj : g_CurrentFile->objects) |
223 &uObjList, |
244 compileOneObject (obj); |
224 &uObjListBack, |
245 } |
225 }; |
246 |
226 |
247 // ========================================================================= // |
227 for (uchar i = 0; i < 2; ++i) { |
248 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
228 if (i && !gl_colorbfc) |
249 // ========================================================================= // |
229 continue; |
|
230 |
|
231 *upaLists[i] = glGenLists (1); |
|
232 glNewList (*upaLists[i], GL_COMPILE); |
|
233 |
|
234 for (LDObject* obj : g_CurrentFile->objects) |
|
235 compileOneObject (obj, i); |
|
236 |
|
237 glEndList (); |
|
238 } |
|
239 } |
|
240 |
|
241 // ============================================================================= |
|
242 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
243 // ============================================================================= |
|
244 template<class T> void renderer::compileSubObject (LDObject* obj, |
250 template<class T> void renderer::compileSubObject (LDObject* obj, |
245 const bool bBackSide, const GLenum eGLType, const short dVerts) |
251 const GLenum eGLType, const short dVerts) |
246 { |
252 { |
247 setObjectColor (obj, bBackSide); |
253 setObjectColor (obj); |
248 T* newobj = static_cast<T*> (obj); |
254 T* newobj = static_cast<T*> (obj); |
249 glBegin (eGLType); |
255 glBegin (eGLType); |
250 |
256 |
251 for (short i = 0; i < dVerts; ++i) |
257 for (short i = 0; i < dVerts; ++i) |
252 compileVertex (newobj->vaCoords[i]); |
258 compileVertex (newobj->vaCoords[i]); |
253 |
259 |
254 glEnd (); |
260 glEnd (); |
255 } |
261 } |
256 |
262 |
257 // ============================================================================= |
263 // ========================================================================= // |
258 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
264 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
259 // ============================================================================= |
265 // ========================================================================= // |
260 void renderer::compileOneObject (LDObject* obj, bool bBackSide) { |
266 void renderer::compileOneObject (LDObject* obj) { |
261 if (!obj) |
267 GLuint uList = glGenLists (1); |
262 return; |
268 glNewList (uList, GL_COMPILE); |
263 |
269 |
264 switch (obj->getType ()) { |
270 switch (obj->getType ()) { |
265 case OBJ_Line: |
271 case OBJ_Line: |
266 compileSubObject<LDLine> (obj, bBackSide, GL_LINES, 2); |
272 compileSubObject<LDLine> (obj, GL_LINES, 2); |
267 break; |
273 break; |
268 |
274 |
269 case OBJ_CondLine: |
275 case OBJ_CondLine: |
270 glLineStipple (1, 0x6666); |
276 glLineStipple (1, 0x6666); |
271 glEnable (GL_LINE_STIPPLE); |
277 glEnable (GL_LINE_STIPPLE); |
272 |
278 |
273 compileSubObject<LDCondLine> (obj, bBackSide, GL_LINES, 2); |
279 compileSubObject<LDCondLine> (obj, GL_LINES, 2); |
274 |
280 |
275 glDisable (GL_LINE_STIPPLE); |
281 glDisable (GL_LINE_STIPPLE); |
276 break; |
282 break; |
277 |
283 |
278 case OBJ_Triangle: |
284 case OBJ_Triangle: |
279 compileSubObject<LDTriangle> (obj, bBackSide, GL_TRIANGLES, 3); |
285 compileSubObject<LDTriangle> (obj, GL_TRIANGLES, 3); |
280 break; |
286 break; |
281 |
287 |
282 case OBJ_Quad: |
288 case OBJ_Quad: |
283 compileSubObject<LDQuad> (obj, bBackSide, GL_QUADS, 4); |
289 compileSubObject<LDQuad> (obj, GL_QUADS, 4); |
284 break; |
290 break; |
285 |
291 |
286 case OBJ_Subfile: |
292 case OBJ_Subfile: |
287 { |
293 { |
288 LDSubfile* ref = static_cast<LDSubfile*> (obj); |
294 LDSubfile* ref = static_cast<LDSubfile*> (obj); |
289 |
295 |
290 vector<LDObject*> objs = ref->inlineContents (true, true); |
296 vector<LDObject*> objs = ref->inlineContents (true, true); |
291 |
297 |
292 for (LDObject* obj : objs) { |
298 for (LDObject* obj : objs) { |
293 compileOneObject (obj, bBackSide); |
299 compileOneObject (obj); |
294 delete obj; |
300 delete obj; |
295 } |
301 } |
296 } |
302 } |
297 break; |
303 break; |
298 |
304 |
331 #endif // 0 |
337 #endif // 0 |
332 |
338 |
333 default: |
339 default: |
334 break; |
340 break; |
335 } |
341 } |
336 } |
342 |
337 |
343 glEndList (); |
338 // ============================================================================= |
344 uaObjLists.push_back (uList); |
339 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
345 obj->uGLList = uList; |
340 // ============================================================================= |
346 } |
|
347 |
|
348 // ========================================================================= // |
|
349 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
|
350 // ========================================================================= // |
341 void renderer::compileVertex (vertex& vrt) { |
351 void renderer::compileVertex (vertex& vrt) { |
342 glVertex3d ( |
352 glVertex3d ( |
343 (vrt.x + g_faObjectOffset[0]) / g_StoredBBoxSize, |
353 (vrt.x + g_faObjectOffset[0]) / g_StoredBBoxSize, |
344 -(vrt.y + g_faObjectOffset[1]) / g_StoredBBoxSize, |
354 -(vrt.y + g_faObjectOffset[1]) / g_StoredBBoxSize, |
345 -(vrt.z + g_faObjectOffset[2]) / g_StoredBBoxSize); |
355 -(vrt.z + g_faObjectOffset[2]) / g_StoredBBoxSize); |
346 } |
356 } |
347 |
357 |
348 // ============================================================================= |
358 // ========================================================================= // |
349 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
359 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
350 // ============================================================================= |
360 // ========================================================================= // |
351 void renderer::clampAngle (double& fAngle) { |
361 void renderer::clampAngle (double& fAngle) { |
352 while (fAngle < 0) |
362 while (fAngle < 0) |
353 fAngle += 360.0; |
363 fAngle += 360.0; |
354 while (fAngle > 360.0) |
364 while (fAngle > 360.0) |
355 fAngle -= 360.0; |
365 fAngle -= 360.0; |
356 } |
366 } |
357 |
367 |
358 // ============================================================================= |
368 // ========================================================================= // |
359 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
369 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
360 // ============================================================================= |
370 // ========================================================================= // |
|
371 void renderer::mouseReleaseEvent (QMouseEvent* event) { |
|
372 if ((qMouseButtons & Qt::LeftButton) && !(event->buttons() & Qt::LeftButton)) { |
|
373 if (ulTotalMouseMove < 10) |
|
374 pick (event->x(), event->y()); |
|
375 |
|
376 ulTotalMouseMove = 0; |
|
377 } |
|
378 } |
|
379 |
|
380 void renderer::mousePressEvent (QMouseEvent* event) { |
|
381 qMouseButtons = event->buttons(); |
|
382 if (event->buttons() & Qt::LeftButton) |
|
383 ulTotalMouseMove = 0; |
|
384 } |
|
385 |
|
386 // ========================================================================= // |
|
387 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
|
388 // ========================================================================= // |
361 void renderer::mouseMoveEvent (QMouseEvent *event) { |
389 void renderer::mouseMoveEvent (QMouseEvent *event) { |
362 int dx = event->x () - lastPos.x (); |
390 int dx = event->x () - lastPos.x (); |
363 int dy = event->y () - lastPos.y (); |
391 int dy = event->y () - lastPos.y (); |
|
392 ulTotalMouseMove += abs (dx) + abs (dy); |
364 |
393 |
365 if (event->buttons () & Qt::LeftButton) { |
394 if (event->buttons () & Qt::LeftButton) { |
366 fRotX = fRotX + (dy); |
395 fRotX = fRotX + (dy); |
367 fRotY = fRotY + (dx); |
396 fRotY = fRotY + (dx); |
368 clampAngle (fRotX); |
397 clampAngle (fRotX); |
382 } |
411 } |
383 |
412 |
384 lastPos = event->pos(); |
413 lastPos = event->pos(); |
385 updateGL (); |
414 updateGL (); |
386 } |
415 } |
|
416 |
|
417 // ========================================================================= // |
|
418 void renderer::pick (uint mx, uint my) { |
|
419 glDisable (GL_DITHER); |
|
420 glClearColor (1.0f, 1.0f, 1.0f, 1.0f); |
|
421 |
|
422 g_bPicking = true; |
|
423 |
|
424 compileObjects (); |
|
425 paintGL (); |
|
426 |
|
427 GLubyte pixel[3]; |
|
428 GLint viewport[4]; |
|
429 glGetIntegerv (GL_VIEWPORT, viewport); |
|
430 glReadPixels (mx, viewport[3] - my, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*> (pixel)); |
|
431 |
|
432 if (pixel[0] != 255 || pixel[1] != 255 || pixel[2] != 255) { |
|
433 ulong idx = pixel[0] + (pixel[1] * 256) + (pixel[2] * 256 * 256); |
|
434 printf ("idx: %lu\n", idx); |
|
435 |
|
436 LDObject* obj = g_CurrentFile->object (idx); |
|
437 |
|
438 g_ForgeWindow->paSelection.clear (); |
|
439 g_ForgeWindow->paSelection.push_back (obj); |
|
440 } |
|
441 |
|
442 g_bPicking = false; |
|
443 glEnable (GL_DITHER); |
|
444 |
|
445 setBackground (); |
|
446 compileObjects (); |
|
447 paintGL (); |
|
448 |
|
449 g_ForgeWindow->updateSelection (); |
|
450 } |