76 GLRenderer::Bottom, |
77 GLRenderer::Bottom, |
77 GLRenderer::Back, |
78 GLRenderer::Back, |
78 GLRenderer::Right, |
79 GLRenderer::Right, |
79 GLRenderer::Free |
80 GLRenderer::Free |
80 }; |
81 }; |
|
82 |
|
83 const struct GLAxis { |
|
84 const QColor col; |
|
85 const vertex vert; |
|
86 } g_GLAxes[3] = { |
|
87 { QColor (255, 0, 0), vertex (10000, 0, 0) }, |
|
88 { QColor (128, 192, 0), vertex (0, 10000, 0) }, |
|
89 { QColor (0, 160, 192), vertex (0, 0, 10000) }, |
|
90 }; |
81 |
91 |
82 // ============================================================================= |
92 // ============================================================================= |
83 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
93 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
84 // ============================================================================= |
94 // ============================================================================= |
85 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) { |
95 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) { |
340 glLoadIdentity (); |
350 glLoadIdentity (); |
341 gluPerspective (45.0f, (double)w / (double)h, 1.0f, 100.0f); |
351 gluPerspective (45.0f, (double)w / (double)h, 1.0f, 100.0f); |
342 glMatrixMode (GL_MODELVIEW); |
352 glMatrixMode (GL_MODELVIEW); |
343 } |
353 } |
344 |
354 |
345 const struct GLAxis { |
|
346 const QColor col; |
|
347 const vertex vert; |
|
348 } g_GLAxes[3] = { |
|
349 { QColor (255, 0, 0), vertex (10000, 0, 0) }, |
|
350 { QColor (128, 192, 0), vertex (0, 10000, 0) }, |
|
351 { QColor (0, 160, 192), vertex (0, 0, 10000) }, |
|
352 }; |
|
353 |
|
354 void GLRenderer::drawGLScene () const { |
355 void GLRenderer::drawGLScene () const { |
355 if (g_curfile == null) |
356 if (g_curfile == null) |
356 return; |
357 return; |
357 |
358 |
358 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
359 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
394 |
395 |
395 glPopMatrix (); |
396 glPopMatrix (); |
396 glMatrixMode (GL_MODELVIEW); |
397 glMatrixMode (GL_MODELVIEW); |
397 } |
398 } |
398 |
399 |
|
400 // ============================================================================= |
399 vertex GLRenderer::coord_2to3 (const QPoint& pos2d, const bool snap) const { |
401 vertex GLRenderer::coord_2to3 (const QPoint& pos2d, const bool snap) const { |
400 vertex pos3d; |
402 vertex pos3d; |
401 const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
403 const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
402 const Axis axisX = cam->axisX; |
404 const Axis axisX = cam->axisX; |
403 const Axis axisY = cam->axisY; |
405 const Axis axisY = cam->axisY; |
404 const short negXFac = cam->negX ? -1 : 1, |
406 const short negXFac = cam->negX ? -1 : 1, |
405 negYFac = cam->negY ? -1 : 1; |
407 negYFac = cam->negY ? -1 : 1; |
406 |
408 |
407 // Calculate cx and cy - these are the LDraw unit coords the cursor is at. |
409 // Calculate cx and cy - these are the LDraw unit coords the cursor is at. |
408 double cx = (-m_virtWidth + ((2 * pos2d.x () * m_virtWidth) / m_width) - m_panX) * g_storedBBoxSize - (negXFac * g_objOffset[axisX]); |
410 double cx = (-m_virtWidth + ((2 * pos2d.x () * m_virtWidth) / m_width) - m_panX) * |
409 double cy = (m_virtHeight - ((2 * pos2d.y () * m_virtHeight) / m_height) - m_panY) * g_storedBBoxSize - (negYFac * g_objOffset[axisY]); |
411 g_storedBBoxSize - (negXFac * g_objOffset[axisX]); |
|
412 double cy = (m_virtHeight - ((2 * pos2d.y () * m_virtHeight) / m_height) - m_panY) * |
|
413 g_storedBBoxSize - (negYFac * g_objOffset[axisY]); |
410 |
414 |
411 if (snap) { |
415 if (snap) { |
412 cx = Grid::snap (cx, (Grid::Config) axisX); |
416 cx = Grid::snap (cx, (Grid::Config) axisX); |
413 cy = Grid::snap (cy, (Grid::Config) axisY); |
417 cy = Grid::snap (cy, (Grid::Config) axisY); |
414 } |
418 } |
420 pos3d[axisX] = cx; |
424 pos3d[axisX] = cx; |
421 pos3d[axisY] = cy; |
425 pos3d[axisY] = cy; |
422 return pos3d; |
426 return pos3d; |
423 } |
427 } |
424 |
428 |
|
429 // ============================================================================= |
425 QPoint GLRenderer::coord_3to2 (const vertex& pos3d) const { |
430 QPoint GLRenderer::coord_3to2 (const vertex& pos3d) const { |
426 QPoint pos2d (0, 0); |
431 /* |
427 GLdouble glmatr[16]; |
432 cx = (-m_virtWidth + ((2 * pos2d.x () * m_virtWidth) / m_width) - m_panX) * g_storedBBoxSize - (negXFac * g_objOffset[axisX]); |
428 glGetDoublev (GL_MODELVIEW, glmatr); |
433 |
429 |
434 cx = (-vw + ((2 * x * vw) / w) - panx) * size - (neg * ofs) |
430 matrix<4> matr (glmatr); |
435 cx + (neg * ofs) = (-vw + ((2 * x * vw) / w) - panx) * size |
431 |
436 (cx + (neg * ofs)) / size = ((2 * x * vw) / w) - vw - panx |
432 vertex copy = pos3d; |
437 ((cx + (neg * ofs)) / size) + vw + panx = (2 * x * vw) / w |
433 copy.transform (matrix<3> (matr), g_origin); |
438 (((cx + (neg * ofs)) / size) + vw + panx) * w = 2 * vw * x |
434 return QPoint (copy[X], copy[Y]); |
439 |
|
440 x = ((((cx + (neg * ofs)) / size) + vw + panx) * w) / (2 * vw) |
|
441 */ |
|
442 |
|
443 QPoint pos2d; |
|
444 const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
|
445 const Axis axisX = cam->axisX; |
|
446 const Axis axisY = cam->axisY; |
|
447 const short negXFac = cam->negX ? -1 : 1, |
|
448 negYFac = cam->negY ? -1 : 1; |
|
449 |
|
450 short x1 = ((((pos3d[axisX] + (negXFac * g_objOffset[axisX])) / g_storedBBoxSize) + |
|
451 m_virtWidth + m_panX) * m_width) / (2 * m_virtWidth); |
|
452 short y1 = -((((pos3d[axisY] + (negYFac * g_objOffset[axisY])) / g_storedBBoxSize) - |
|
453 m_virtHeight + m_panY) * m_height) / (2 * m_virtHeight); |
|
454 |
|
455 x1 *= negXFac; |
|
456 y1 *= negYFac; |
|
457 |
|
458 pos2d = QPoint (x1, y1); |
|
459 return pos2d; |
435 } |
460 } |
436 |
461 |
437 // ============================================================================= |
462 // ============================================================================= |
438 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
463 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
439 // ============================================================================= |
464 // ============================================================================= |
463 |
488 |
464 paint.drawText (m_width - textSize.width (), m_height - 16, textSize.width (), |
489 paint.drawText (m_width - textSize.width (), m_height - 16, textSize.width (), |
465 textSize.height (), Qt::AlignCenter, text); |
490 textSize.height (), Qt::AlignCenter, text); |
466 |
491 |
467 // If we're plane drawing, draw the vertices onto the screen. |
492 // If we're plane drawing, draw the vertices onto the screen. |
468 |
493 if (m_planeDraw) { |
|
494 ushort numverts = m_planeDrawVerts.size () + 1; |
|
495 const short blipsize = 8; |
|
496 |
|
497 if (numverts > 0) { |
|
498 QPoint* poly = new QPoint[numverts]; |
|
499 |
|
500 uchar i = 0; |
|
501 for (vertex& vert : m_planeDrawVerts) { |
|
502 poly[i] = coord_3to2 (vert); |
|
503 ++i; |
|
504 } |
|
505 |
|
506 // Draw the cursor vertex as the last one in the list. |
|
507 if (numverts < 5) |
|
508 poly[i] = coord_3to2 (m_hoverpos); |
|
509 else |
|
510 numverts = 4; |
|
511 |
|
512 paint.setPen (m_thinBorderPen); |
|
513 paint.setBrush (QColor (128, 192, 0)); |
|
514 |
|
515 // Draw vertex blips |
|
516 for (ushort i = 0; i < numverts; ++i) { |
|
517 QPoint& blip = poly[i]; |
|
518 paint.drawEllipse (blip.x () - blipsize / 2, blip.y () - blipsize / 2, |
|
519 blipsize, blipsize); |
|
520 } |
|
521 |
|
522 paint.setPen (m_thickBorderPen); |
|
523 paint.setBrush (QColor (128, 192, 0, 128)); |
|
524 paint.drawPolygon (poly, numverts); |
|
525 |
|
526 delete[] poly; |
|
527 } |
|
528 } |
469 } |
529 } |
470 |
530 |
471 // Camera icons |
531 // Camera icons |
472 if (!m_picking && m_planeDraw == false) { |
532 if (!m_picking && m_planeDraw == false) { |
473 // Draw a background for the selected camera |
533 // Draw a background for the selected camera |
717 |
777 |
718 // ============================================================================= |
778 // ============================================================================= |
719 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
779 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
720 // ============================================================================= |
780 // ============================================================================= |
721 void GLRenderer::mouseReleaseEvent (QMouseEvent* ev) { |
781 void GLRenderer::mouseReleaseEvent (QMouseEvent* ev) { |
722 if ((m_lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton)) { |
782 const bool wasLeft = (m_lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton); |
|
783 const bool wasRight = (m_lastButtons & Qt::RightButton) && !(ev->buttons() & Qt::RightButton); |
|
784 |
|
785 if (wasLeft) { |
723 if (m_planeDraw) { |
786 if (m_planeDraw) { |
724 m_planeDrawVerts.push_back ({m_hoverpos, m_pos}); |
787 printf ("vert: %s\n", m_hoverpos.stringRep (true).chars ()); |
|
788 |
|
789 // If we picked an already-existing vertex, stop drawing |
|
790 for (vertex& vert : m_planeDrawVerts) { |
|
791 if (vert == m_hoverpos) { |
|
792 endPlaneDraw (true); |
|
793 return; |
|
794 } |
|
795 } |
|
796 |
|
797 // Also, if have 4 verts, also stop drawing. |
|
798 if (m_planeDrawVerts.size () >= 4) |
|
799 endPlaneDraw (true); |
|
800 |
|
801 m_planeDrawVerts.push_back (m_hoverpos); |
|
802 |
|
803 update (); |
|
804 return; |
725 } else { |
805 } else { |
726 if (!m_rangepick) |
806 if (!m_rangepick) |
727 m_addpick = (m_keymods & Qt::ControlModifier); |
807 m_addpick = (m_keymods & Qt::ControlModifier); |
728 |
808 |
729 if (m_totalmove < 10 || m_rangepick) |
809 if (m_totalmove < 10 || m_rangepick) |
730 pick (ev->x (), ev->y ()); |
810 pick (ev->x (), ev->y ()); |
731 } |
811 } |
732 |
812 |
733 m_rangepick = false; |
813 m_rangepick = false; |
734 m_totalmove = 0; |
814 m_totalmove = 0; |
|
815 return; |
|
816 } |
|
817 |
|
818 if (wasRight && m_planeDraw) { |
|
819 if (m_planeDrawVerts.size () > 0) { |
|
820 // Remove the last vertex |
|
821 m_planeDrawVerts.erase (m_planeDrawVerts.end () - 1); |
|
822 } else { |
|
823 endPlaneDraw (false); |
|
824 return; |
|
825 } |
|
826 |
|
827 update (); |
735 } |
828 } |
736 } |
829 } |
737 |
830 |
738 // ============================================================================= |
831 // ============================================================================= |
739 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
832 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
852 GLint viewport[4]; |
945 GLint viewport[4]; |
853 LDObject* removedObject = null; |
946 LDObject* removedObject = null; |
854 |
947 |
855 // Clear the selection if we do not wish to add to it. |
948 // Clear the selection if we do not wish to add to it. |
856 if (!m_addpick) { |
949 if (!m_addpick) { |
857 std::vector<LDObject*> paOldSelection = g_win->sel (); |
950 std::vector<LDObject*> oldsel = g_win->sel (); |
858 g_win->sel ().clear (); |
951 g_win->sel ().clear (); |
859 |
952 |
860 // Recompile the prior selection to remove the highlight color |
953 // Recompile the prior selection to remove the highlight color |
861 for (LDObject* obj : paOldSelection) |
954 for (LDObject* obj : oldsel) |
862 recompileObject (obj); |
955 recompileObject (obj); |
863 } |
956 } |
864 |
957 |
865 m_picking = true; |
958 m_picking = true; |
866 |
959 |
972 drawGLScene (); |
1065 drawGLScene (); |
973 swapBuffers (); |
1066 swapBuffers (); |
974 update (); |
1067 update (); |
975 } |
1068 } |
976 |
1069 |
|
1070 // ============================================================================= |
977 void GLRenderer::beginPlaneDraw () { |
1071 void GLRenderer::beginPlaneDraw () { |
978 if (m_camera == Free) |
1072 if (m_camera == Free) |
979 return; |
1073 return; // Cannot draw with the free camera |
980 |
1074 |
981 m_planeDraw = true; |
1075 m_planeDraw = true; |
|
1076 |
|
1077 // Disable the context menu - we need the right mouse button |
|
1078 // for removing vertices. |
|
1079 setContextMenuPolicy (Qt::NoContextMenu); |
|
1080 |
|
1081 // Use the crosshair cursor when plane drawing. |
|
1082 setCursor (Qt::CrossCursor); |
|
1083 |
|
1084 // Clear the selection when beginning to draw onto a plane. |
|
1085 // FIXME: make the selection clearing stuff in ::pick a method and use it |
|
1086 // here! This code doesn't update the GL lists. |
|
1087 g_win->sel ().clear (); |
|
1088 g_win->updateSelection (); |
982 update (); |
1089 update (); |
983 } |
1090 } |
984 |
1091 |
985 // ========================================================================= // |
1092 // ============================================================================= |
986 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
1093 void GLRenderer::endPlaneDraw (bool accept) { |
987 // ========================================================================= // |
1094 // If we accepted, clean the selection and create the object |
|
1095 if (accept) { |
|
1096 vector<vertex>& verts = m_planeDrawVerts; |
|
1097 printf ("accepted (%lu verts)\n", verts.size ()); |
|
1098 |
|
1099 LDObject* obj = null; |
|
1100 |
|
1101 switch (verts.size ()) { |
|
1102 case 1: |
|
1103 { |
|
1104 // 1 vertex - add a vertex object |
|
1105 obj = new LDVertex; |
|
1106 static_cast<LDVertex*> (obj)->vPosition = verts[0]; |
|
1107 obj->dColor = maincolor; |
|
1108 } |
|
1109 break; |
|
1110 |
|
1111 case 2: |
|
1112 { |
|
1113 // 2 verts - make a line |
|
1114 obj = new LDLine; |
|
1115 obj->dColor = edgecolor; |
|
1116 for (ushort i = 0; i < 2; ++i) |
|
1117 obj->vaCoords[i] = verts[i]; |
|
1118 } |
|
1119 break; |
|
1120 |
|
1121 case 3: |
|
1122 case 4: |
|
1123 { |
|
1124 obj = (verts.size () == 3) ? |
|
1125 static_cast<LDObject*> (new LDTriangle) : |
|
1126 static_cast<LDObject*> (new LDQuad); |
|
1127 |
|
1128 obj->dColor = maincolor; |
|
1129 for (ushort i = 0; i < obj->vertices (); ++i) |
|
1130 obj->vaCoords[i] = verts[i]; |
|
1131 } |
|
1132 break; |
|
1133 } |
|
1134 |
|
1135 if (obj) { |
|
1136 g_curfile->addObject (obj); |
|
1137 recompileObject (obj); |
|
1138 g_win->refresh (); |
|
1139 |
|
1140 History::addEntry (new AddHistory ({(ulong) obj->getIndex (g_curfile)}, {obj->clone ()})); |
|
1141 } |
|
1142 } |
|
1143 |
|
1144 m_planeDraw = false; |
|
1145 m_planeDrawVerts.clear (); |
|
1146 |
|
1147 unsetCursor (); |
|
1148 |
|
1149 // Restore the context menu |
|
1150 setContextMenuPolicy (Qt::DefaultContextMenu); |
|
1151 |
|
1152 update (); |
|
1153 } |
|
1154 |
|
1155 // ============================================================================= |
|
1156 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
|
1157 // ============================================================================= |
988 void GLRenderer::recompileObject (LDObject* obj) { |
1158 void GLRenderer::recompileObject (LDObject* obj) { |
989 // Replace the old list with the new one. |
1159 // Replace the old list with the new one. |
990 GLuint uList = glGenLists (1); |
1160 GLuint uList = glGenLists (1); |
991 glNewList (uList, GL_COMPILE); |
1161 glNewList (uList, GL_COMPILE); |
992 |
1162 |