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); |