| 95 m_picking = m_rangepick = false; |
96 m_picking = m_rangepick = false; |
| 96 m_camera = (GL::Camera) gl_camera.value; |
97 m_camera = (GL::Camera) gl_camera.value; |
| 97 m_drawToolTip = false; |
98 m_drawToolTip = false; |
| 98 m_editMode = Select; |
99 m_editMode = Select; |
| 99 m_rectdraw = false; |
100 m_rectdraw = false; |
| |
101 setFile (null); |
| |
102 setDrawOnly (false); |
| 100 |
103 |
| 101 m_toolTipTimer = new QTimer (this); |
104 m_toolTipTimer = new QTimer (this); |
| 102 m_toolTipTimer->setSingleShot (true); |
105 m_toolTipTimer->setSingleShot (true); |
| 103 connect (m_toolTipTimer, SIGNAL (timeout ()), this, SLOT (slot_toolTipTimer ())); |
106 connect (m_toolTipTimer, SIGNAL (timeout ()), this, SLOT (slot_toolTipTimer ())); |
| 104 |
107 |
| 171 m_rotY = 325.f; |
174 m_rotY = 325.f; |
| 172 m_panX = m_panY = m_rotZ = 0.0f; |
175 m_panX = m_panY = m_rotZ = 0.0f; |
| 173 |
176 |
| 174 // Set the default zoom based on the bounding box |
177 // Set the default zoom based on the bounding box |
| 175 if (g_BBox.empty () == false) |
178 if (g_BBox.empty () == false) |
| 176 m_zoom = g_BBox.size () * 6; |
179 setZoom (g_BBox.size () * 6); |
| 177 else |
180 else |
| 178 m_zoom = 30.0f; |
181 setZoom (30.0f); |
| 179 } |
182 } |
| 180 |
183 |
| 181 // ============================================================================= |
184 // ============================================================================= |
| 182 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
185 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 183 // ============================================================================= |
186 // ============================================================================= |
| 231 |
234 |
| 232 if (list == GL::PickList) { |
235 if (list == GL::PickList) { |
| 233 // Make the color by the object's index color if we're picking, so we can |
236 // Make the color by the object's index color if we're picking, so we can |
| 234 // make the index from the color we get from the picking results. Be sure |
237 // make the index from the color we get from the picking results. Be sure |
| 235 // to use the top level parent's index since inlinees don't have an index. |
238 // to use the top level parent's index since inlinees don't have an index. |
| 236 long i = obj->topLevelParent ()->getIndex (g_curfile); |
239 long i = obj->topLevelParent ()->getIndex (file ()); |
| 237 |
240 |
| 238 // We should have the index now. |
241 // We should have the index now. |
| 239 assert (i != -1); |
242 assert (i != -1); |
| 240 |
243 |
| 241 // Calculate a color based from this index. This method caters for |
244 // Calculate a color based from this index. This method caters for |
| 341 glLoadIdentity (); |
344 glLoadIdentity (); |
| 342 gluPerspective (45.0f, (double) w / (double) h, 1.0f, 10000.0f); |
345 gluPerspective (45.0f, (double) w / (double) h, 1.0f, 10000.0f); |
| 343 glMatrixMode (GL_MODELVIEW); |
346 glMatrixMode (GL_MODELVIEW); |
| 344 } |
347 } |
| 345 |
348 |
| 346 void GLRenderer::drawGLScene () const { |
349 void GLRenderer::drawGLScene () { |
| 347 if (g_curfile == null) |
350 if (file () == null) |
| 348 return; |
351 return; |
| 349 |
352 |
| 350 if (gl_wireframe && !picking ()) |
353 if (gl_wireframe && !picking ()) |
| 351 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); |
354 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); |
| 352 |
355 |
| 373 glMatrixMode (GL_MODELVIEW); |
376 glMatrixMode (GL_MODELVIEW); |
| 374 glPushMatrix (); |
377 glPushMatrix (); |
| 375 glLoadIdentity (); |
378 glLoadIdentity (); |
| 376 |
379 |
| 377 glTranslatef (0.0f, 0.0f, -2.0f); |
380 glTranslatef (0.0f, 0.0f, -2.0f); |
| 378 glTranslatef (m_panX, m_panY, -m_zoom); |
381 glTranslatef (m_panX, m_panY, -zoom ()); |
| 379 glRotatef (m_rotX, 1.0f, 0.0f, 0.0f); |
382 glRotatef (m_rotX, 1.0f, 0.0f, 0.0f); |
| 380 glRotatef (m_rotY, 0.0f, 1.0f, 0.0f); |
383 glRotatef (m_rotY, 0.0f, 1.0f, 0.0f); |
| 381 glRotatef (m_rotZ, 0.0f, 0.0f, 1.0f); |
384 glRotatef (m_rotZ, 0.0f, 0.0f, 1.0f); |
| 382 } |
385 } |
| 383 |
386 |
| 384 if (gl_colorbfc && !m_picking) { |
387 const GL::ListType list = (!drawOnly () && m_picking) ? PickList : NormalList; |
| |
388 |
| |
389 if (gl_colorbfc && !m_picking && !drawOnly ()) { |
| 385 glEnable (GL_CULL_FACE); |
390 glEnable (GL_CULL_FACE); |
| 386 |
391 |
| 387 for (LDObject* obj : g_curfile->objs ()) { |
392 for (LDObject* obj : file ()->objs ()) { |
| 388 if (obj->hidden ()) |
393 if (obj->hidden ()) |
| 389 continue; |
394 continue; |
| 390 |
395 |
| 391 glCullFace (GL_BACK); |
396 glCullFace (GL_BACK); |
| 392 glCallList (obj->glLists[BFCFrontList]); |
397 glCallList (obj->glLists[BFCFrontList]); |
| 395 glCallList (obj->glLists[BFCBackList]); |
400 glCallList (obj->glLists[BFCBackList]); |
| 396 } |
401 } |
| 397 |
402 |
| 398 glDisable (GL_CULL_FACE); |
403 glDisable (GL_CULL_FACE); |
| 399 } else { |
404 } else { |
| 400 for (LDObject* obj : g_curfile->objs ()) { |
405 for (LDObject* obj : file ()->objs ()) { |
| 401 if (obj->hidden ()) |
406 if (obj->hidden ()) |
| 402 continue; |
407 continue; |
| 403 |
408 |
| 404 glCallList (obj->glLists[(m_picking) ? PickList : NormalList]); |
409 glCallList (obj->glLists[list]); |
| 405 } |
410 } |
| 406 } |
411 } |
| 407 |
412 |
| 408 if (gl_axes && !m_picking) |
413 if (gl_axes && !m_picking && !drawOnly ()) |
| 409 glCallList (m_axeslist); |
414 glCallList (m_axeslist); |
| 410 |
415 |
| 411 glPopMatrix (); |
416 glPopMatrix (); |
| 412 glMatrixMode (GL_MODELVIEW); |
417 glMatrixMode (GL_MODELVIEW); |
| 413 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); |
418 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); |
| 472 // ============================================================================= |
477 // ============================================================================= |
| 473 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
478 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 474 // ============================================================================= |
479 // ============================================================================= |
| 475 void GLRenderer::paintEvent (QPaintEvent* ev) { |
480 void GLRenderer::paintEvent (QPaintEvent* ev) { |
| 476 Q_UNUSED (ev) |
481 Q_UNUSED (ev) |
| 477 m_virtWidth = m_zoom; |
482 |
| |
483 makeCurrent (); |
| |
484 m_virtWidth = zoom (); |
| 478 m_virtHeight = (m_height * m_virtWidth) / m_width; |
485 m_virtHeight = (m_height * m_virtWidth) / m_width; |
| 479 |
486 |
| 480 initGLData (); |
487 initGLData (); |
| 481 drawGLScene (); |
488 drawGLScene (); |
| 482 |
489 |
| 483 m_hoverpos = g_origin; |
490 m_hoverpos = g_origin; |
| 484 |
491 |
| 485 QPainter paint (this); |
492 QPainter paint (this); |
| 486 QFontMetrics metrics = QFontMetrics (QFont ()); |
493 QFontMetrics metrics = QFontMetrics (QFont ()); |
| 487 paint.setRenderHint (QPainter::HighQualityAntialiasing); |
494 paint.setRenderHint (QPainter::HighQualityAntialiasing); |
| |
495 |
| |
496 // If we wish to only draw the brick, stop here |
| |
497 if (drawOnly ()) |
| |
498 return; |
| 488 |
499 |
| 489 if (m_camera != Free) { |
500 if (m_camera != Free) { |
| 490 // Paint the overlay image if we have one |
501 // Paint the overlay image if we have one |
| 491 const overlayMeta& overlay = m_overlays[m_camera]; |
502 const overlayMeta& overlay = m_overlays[m_camera]; |
| 492 if (overlay.img != null) { |
503 if (overlay.img != null) { |
| 658 |
669 |
| 659 // ============================================================================= |
670 // ============================================================================= |
| 660 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
671 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 661 // ============================================================================= |
672 // ============================================================================= |
| 662 void GLRenderer::compileAllObjects () { |
673 void GLRenderer::compileAllObjects () { |
| 663 if (!g_curfile) { |
674 if (!file ()) |
| 664 printf ("renderer: no files loaded, cannot compile anything\n"); |
|
| 665 return; |
675 return; |
| 666 } |
676 |
| 667 |
677 for (LDObject* obj : file ()->objs ()) |
| 668 for (LDObject* obj : g_curfile->objs ()) |
|
| 669 compileObject (obj); |
678 compileObject (obj); |
| 670 |
679 |
| 671 // Compile axes |
680 // Compile axes |
| 672 glDeleteLists (m_axeslist, 1); |
681 glDeleteLists (m_axeslist, 1); |
| 673 m_axeslist = glGenLists (1); |
682 m_axeslist = glGenLists (1); |
| 939 clampAngle (m_rotX); |
950 clampAngle (m_rotX); |
| 940 clampAngle (m_rotY); |
951 clampAngle (m_rotY); |
| 941 } |
952 } |
| 942 |
953 |
| 943 if (ev->buttons () & Qt::MidButton) { |
954 if (ev->buttons () & Qt::MidButton) { |
| 944 m_panX += 0.03f * dx * (m_zoom / 7.5f); |
955 m_panX += 0.03f * dx * (zoom () / 7.5f); |
| 945 m_panY -= 0.03f * dy * (m_zoom / 7.5f); |
956 m_panY -= 0.03f * dy * (zoom () / 7.5f); |
| 946 } |
957 } |
| 947 |
958 |
| 948 // Start the tool tip timer |
959 // Start the tool tip timer |
| 949 if (!m_drawToolTip) |
960 if (!m_drawToolTip) |
| 950 m_toolTipTimer->start (1000); |
961 m_toolTipTimer->start (1000); |
| 964 m_keymods = ev->modifiers (); |
975 m_keymods = ev->modifiers (); |
| 965 } |
976 } |
| 966 |
977 |
| 967 // ============================================================================= |
978 // ============================================================================= |
| 968 void GLRenderer::wheelEvent (QWheelEvent* ev) { |
979 void GLRenderer::wheelEvent (QWheelEvent* ev) { |
| 969 if (m_zoom > 15) |
980 makeCurrent (); |
| 970 m_zoom *= (ev->delta () < 0) ? 1.2f : (1.0f / 1.2f); |
981 |
| |
982 if (zoom () > 15) |
| |
983 setZoom (zoom () * (ev->delta () < 0 ? 1.2f : 0.833f)); |
| 971 else |
984 else |
| 972 m_zoom += (double) ev->delta () / -100.0f; |
985 setZoom (zoom () + ((double) ev->delta () / -100.0f)); |
| 973 |
986 |
| 974 m_zoom = clamp<double> (m_zoom, 0.01f, 10000.0f); |
987 setZoom (clamp<double> (zoom (), 0.01f, 10000.0f)); |
| 975 |
988 |
| 976 update (); |
989 update (); |
| 977 ev->accept (); |
990 ev->accept (); |
| 978 } |
991 } |
| 979 |
992 |
| 1000 // ============================================================================= |
1013 // ============================================================================= |
| 1001 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
1014 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 1002 // ============================================================================= |
1015 // ============================================================================= |
| 1003 void GLRenderer::pick (uint mouseX, uint mouseY) { |
1016 void GLRenderer::pick (uint mouseX, uint mouseY) { |
| 1004 GLint viewport[4]; |
1017 GLint viewport[4]; |
| |
1018 makeCurrent (); |
| 1005 |
1019 |
| 1006 // Use particularly thick lines while picking ease up selecting lines. |
1020 // Use particularly thick lines while picking ease up selecting lines. |
| 1007 glLineWidth (max<double> (gl_linethickness, 6.5f)); |
1021 glLineWidth (max<double> (gl_linethickness, 6.5f)); |
| 1008 |
1022 |
| 1009 // Clear the selection if we do not wish to add to it. |
1023 // Clear the selection if we do not wish to add to it. |
| 1078 pixelptr += 4; |
1092 pixelptr += 4; |
| 1079 |
1093 |
| 1080 if (idx == 0xFFFFFF) |
1094 if (idx == 0xFFFFFF) |
| 1081 continue; // White is background; skip |
1095 continue; // White is background; skip |
| 1082 |
1096 |
| 1083 LDObject* obj = g_curfile->obj (idx); |
1097 LDObject* obj = file ()->obj (idx); |
| 1084 |
1098 |
| 1085 // If this is an additive single pick and the object is currently selected, |
1099 // If this is an additive single pick and the object is currently selected, |
| 1086 // we remove it from selection instead. |
1100 // we remove it from selection instead. |
| 1087 if (!m_rangepick && m_addpick) { |
1101 if (!m_rangepick && m_addpick) { |
| 1088 bool removed = false; |
1102 bool removed = false; |
| 1219 break; |
1233 break; |
| 1220 } |
1234 } |
| 1221 } |
1235 } |
| 1222 |
1236 |
| 1223 if (obj) { |
1237 if (obj) { |
| 1224 g_curfile->addObject (obj); |
1238 file ()->addObject (obj); |
| 1225 compileObject (obj); |
1239 compileObject (obj); |
| 1226 g_win->fullRefresh (); |
1240 g_win->fullRefresh (); |
| 1227 |
1241 |
| 1228 History::addEntry (new AddHistory ({(ulong) obj->getIndex (g_curfile)}, {obj->clone ()})); |
1242 History::addEntry (new AddHistory ({(ulong) obj->getIndex (file ())}, {obj->clone ()})); |
| 1229 } |
1243 } |
| 1230 |
1244 |
| 1231 m_drawedVerts.clear (); |
1245 m_drawedVerts.clear (); |
| 1232 m_rectdraw = false; |
1246 m_rectdraw = false; |
| 1233 } |
1247 } |
| 1237 // ============================================================================= |
1251 // ============================================================================= |
| 1238 void GLRenderer::compileObject (LDObject* obj) { |
1252 void GLRenderer::compileObject (LDObject* obj) { |
| 1239 deleteLists (obj); |
1253 deleteLists (obj); |
| 1240 |
1254 |
| 1241 for (const GL::ListType listType : g_glListTypes) { |
1255 for (const GL::ListType listType : g_glListTypes) { |
| |
1256 if (drawOnly () && listType != GL::NormalList) |
| |
1257 continue; |
| |
1258 |
| 1242 GLuint list = glGenLists (1); |
1259 GLuint list = glGenLists (1); |
| 1243 glNewList (list, GL_COMPILE); |
1260 glNewList (list, GL_COMPILE); |
| 1244 |
1261 |
| 1245 obj->glLists[listType] = list; |
1262 obj->glLists[listType] = list; |
| 1246 compileList (obj, listType); |
1263 compileList (obj, listType); |