160 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
160 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
161 // ============================================================================= |
161 // ============================================================================= |
162 void GLRenderer::initializeGL () { |
162 void GLRenderer::initializeGL () { |
163 setBackground (); |
163 setBackground (); |
164 |
164 |
165 glEnable (GL_POLYGON_OFFSET_FILL); |
|
166 glPolygonOffset (1.0f, 1.0f); |
|
167 |
|
168 glEnable (GL_DEPTH_TEST); |
|
169 glShadeModel (GL_SMOOTH); |
|
170 glEnable (GL_MULTISAMPLE); |
|
171 |
|
172 glEnable (GL_BLEND); |
|
173 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
174 |
|
175 glEnable (GL_LINE_SMOOTH); |
|
176 glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); |
|
177 |
|
178 glLineWidth (gl_linethickness); |
165 glLineWidth (gl_linethickness); |
179 |
166 |
180 setAutoFillBackground (false); |
167 setAutoFillBackground (false); |
181 setMouseTracking (true); |
168 setMouseTracking (true); |
182 setFocusPolicy (Qt::WheelFocus); |
169 setFocusPolicy (Qt::WheelFocus); |
211 |
198 |
212 // ============================================================================= |
199 // ============================================================================= |
213 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
200 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
214 // ============================================================================= |
201 // ============================================================================= |
215 static vector<short> g_daWarnedColors; |
202 static vector<short> g_daWarnedColors; |
216 void GLRenderer::setObjectColor (LDObject* obj) { |
203 void GLRenderer::setObjectColor (LDObject* obj, const ListType list) { |
217 QColor qcol; |
204 QColor qcol; |
218 |
205 |
219 if (!obj->isColored()) |
206 if (!obj->isColored ()) |
220 return; |
207 return; |
221 |
208 |
222 if (m_picking) { |
209 if (list == GL::PickList) { |
223 // Make the color by the object's index color if we're picking, so we can |
210 // Make the color by the object's index color if we're picking, so we can |
224 // make the index from the color we get from the picking results. |
211 // make the index from the color we get from the picking results. |
225 long i = obj->getIndex (g_curfile); |
212 long i = obj->getIndex (g_curfile); |
226 |
213 |
227 // If we couldn't find the index, this object must not be from this file, |
214 // If we couldn't find the index, this object must not be from this file, |
292 long r = qcol.red (), |
279 long r = qcol.red (), |
293 g = qcol.green (), |
280 g = qcol.green (), |
294 b = qcol.blue (), |
281 b = qcol.blue (), |
295 a = qcol.alpha (); |
282 a = qcol.alpha (); |
296 |
283 |
297 // If it's selected, brighten it up, also pulse flash it if desired. |
284 // Brighten it up for the select list. |
298 if (g_win->isSelected (obj)) { |
285 if (list == GL::SelectList) { |
299 short tick, numTicks; |
286 const uchar add = 51; |
300 |
|
301 if (gl_selflash) { |
|
302 tick = (g_pulseTick < (g_numPulseTicks / 2)) ? g_pulseTick : (g_numPulseTicks - g_pulseTick); |
|
303 numTicks = g_numPulseTicks; |
|
304 } else { |
|
305 tick = 2; |
|
306 numTicks = 5; |
|
307 } |
|
308 |
|
309 const long add = ((tick * 128) / numTicks); |
|
310 r = min (r + add, 255l); |
287 r = min (r + add, 255l); |
311 g = min (g + add, 255l); |
288 g = min (g + add, 255l); |
312 b = min (b + add, 255l); |
289 b = min (b + add, 255l); |
313 |
|
314 // a = 255; |
|
315 } |
290 } |
316 |
291 |
317 glColor4f ( |
292 glColor4f ( |
318 ((double) r) / 255.0f, |
293 ((double) r) / 255.0f, |
319 ((double) g) / 255.0f, |
294 ((double) g) / 255.0f, |
390 |
365 |
391 for (LDObject* obj : g_curfile->m_objs) { |
366 for (LDObject* obj : g_curfile->m_objs) { |
392 if (obj->hidden ()) |
367 if (obj->hidden ()) |
393 continue; // Don't draw hidden objects |
368 continue; // Don't draw hidden objects |
394 |
369 |
395 glCallList (m_picking == false ? obj->uGLList : obj->uGLPickList); |
370 glCallList (obj->glLists[(m_picking) ? PickList : (obj->selected ()) ? SelectList : NormalList]); |
396 } |
371 } |
397 |
372 |
398 if (gl_axes && !m_picking) |
373 if (gl_axes && !m_picking) |
399 glCallList (m_axeslist); |
374 glCallList (m_axeslist); |
400 |
375 |
467 // ============================================================================= |
442 // ============================================================================= |
468 void GLRenderer::paintEvent (QPaintEvent* ev) { |
443 void GLRenderer::paintEvent (QPaintEvent* ev) { |
469 Q_UNUSED (ev) |
444 Q_UNUSED (ev) |
470 m_virtWidth = m_zoom; |
445 m_virtWidth = m_zoom; |
471 m_virtHeight = (m_height * m_virtWidth) / m_width; |
446 m_virtHeight = (m_height * m_virtWidth) / m_width; |
|
447 |
|
448 glEnable (GL_BLEND); |
|
449 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
450 glEnable (GL_POLYGON_OFFSET_FILL); |
|
451 glPolygonOffset (1.0f, 1.0f); |
|
452 |
|
453 glEnable (GL_DEPTH_TEST); |
|
454 glShadeModel (GL_SMOOTH); |
|
455 glEnable (GL_MULTISAMPLE); |
|
456 |
|
457 glEnable (GL_LINE_SMOOTH); |
|
458 glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); |
|
459 |
472 drawGLScene (); |
460 drawGLScene (); |
473 |
461 |
474 QPainter paint (this); |
462 QPainter paint (this); |
475 QFontMetrics metrics = QFontMetrics (QFont ()); |
463 QFontMetrics metrics = QFontMetrics (QFont ()); |
476 paint.setRenderHint (QPainter::Antialiasing); |
464 paint.setRenderHint (QPainter::Antialiasing); |
623 if (!g_curfile) { |
611 if (!g_curfile) { |
624 printf ("renderer: no files loaded, cannot compile anything\n"); |
612 printf ("renderer: no files loaded, cannot compile anything\n"); |
625 return; |
613 return; |
626 } |
614 } |
627 |
615 |
628 for (LDObject* obj : g_curfile->m_objs) { |
616 for (LDObject* obj : g_curfile->m_objs) |
629 GLuint* upaLists[2] = { |
617 compileObject (obj); |
630 &obj->uGLList, |
|
631 &obj->uGLPickList |
|
632 }; |
|
633 |
|
634 for (GLuint* upMemberList : upaLists) { |
|
635 GLuint uList = glGenLists (1); |
|
636 glNewList (uList, GL_COMPILE); |
|
637 |
|
638 m_picking = (upMemberList == &obj->uGLPickList); |
|
639 compileOneObject (obj); |
|
640 m_picking = false; |
|
641 |
|
642 glEndList (); |
|
643 *upMemberList = uList; |
|
644 } |
|
645 } |
|
646 |
618 |
647 // Compile axes |
619 // Compile axes |
648 m_axeslist = glGenLists (1); |
620 m_axeslist = glGenLists (1); |
649 glNewList (m_axeslist, GL_COMPILE); |
621 glNewList (m_axeslist, GL_COMPILE); |
650 glBegin (GL_LINES); |
622 glBegin (GL_LINES); |
672 } |
644 } |
673 |
645 |
674 // ============================================================================= |
646 // ============================================================================= |
675 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
647 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
676 // ============================================================================= |
648 // ============================================================================= |
677 void GLRenderer::compileOneObject (LDObject* obj) { |
649 void GLRenderer::compileList (LDObject* obj, const GLRenderer::ListType list) { |
678 setObjectColor (obj); |
650 setObjectColor (obj, list); |
679 |
651 |
680 switch (obj->getType ()) { |
652 switch (obj->getType ()) { |
681 case LDObject::Line: |
653 case LDObject::Line: |
682 compileSubObject (obj, GL_LINES); |
654 compileSubObject (obj, GL_LINES); |
683 break; |
655 break; |
684 |
656 |
685 case LDObject::CondLine: |
657 case LDObject::CondLine: |
686 glLineStipple (1, 0x6666); |
658 if (list != GL::PickList) { |
687 glEnable (GL_LINE_STIPPLE); |
659 glLineStipple (1, 0x6666); |
|
660 glEnable (GL_LINE_STIPPLE); |
|
661 } |
688 |
662 |
689 compileSubObject (obj, GL_LINES); |
663 compileSubObject (obj, GL_LINES); |
690 |
664 |
691 glDisable (GL_LINE_STIPPLE); |
665 glDisable (GL_LINE_STIPPLE); |
692 break; |
666 break; |
789 const bool wasLeft = (m_lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton); |
763 const bool wasLeft = (m_lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton); |
790 const bool wasRight = (m_lastButtons & Qt::RightButton) && !(ev->buttons() & Qt::RightButton); |
764 const bool wasRight = (m_lastButtons & Qt::RightButton) && !(ev->buttons() & Qt::RightButton); |
791 |
765 |
792 if (wasLeft) { |
766 if (wasLeft) { |
793 if (m_planeDraw) { |
767 if (m_planeDraw) { |
|
768 // If we have 4 verts, stop drawing. |
|
769 if (m_planeDrawVerts.size () >= 4) { |
|
770 endPlaneDraw (true); |
|
771 return; |
|
772 } |
|
773 |
794 // If we picked an already-existing vertex, stop drawing |
774 // If we picked an already-existing vertex, stop drawing |
795 for (vertex& vert : m_planeDrawVerts) { |
775 for (vertex& vert : m_planeDrawVerts) { |
796 if (vert == m_hoverpos) { |
776 if (vert == m_hoverpos) { |
797 endPlaneDraw (true); |
777 endPlaneDraw (true); |
798 return; |
778 return; |
799 } |
779 } |
800 } |
780 } |
801 |
781 |
802 // Also, if have 4 verts, also stop drawing. |
|
803 if (m_planeDrawVerts.size () >= 4) |
|
804 endPlaneDraw (true); |
|
805 |
|
806 m_planeDrawVerts.push_back (m_hoverpos); |
782 m_planeDrawVerts.push_back (m_hoverpos); |
807 |
783 |
808 update (); |
784 update (); |
809 return; |
785 return; |
810 } else { |
786 } else { |
946 } |
922 } |
947 } |
923 } |
948 } |
924 } |
949 |
925 |
950 GLint viewport[4]; |
926 GLint viewport[4]; |
951 LDObject* removedObject = null; |
|
952 |
927 |
953 // Clear the selection if we do not wish to add to it. |
928 // Clear the selection if we do not wish to add to it. |
954 if (!m_addpick) { |
929 if (!m_addpick) { |
955 std::vector<LDObject*> oldsel = g_win->sel (); |
930 std::vector<LDObject*> oldsel = g_win->sel (); |
956 g_win->sel ().clear (); |
931 g_win->sel ().clear (); |
957 |
932 |
958 // Recompile the prior selection to remove the highlight color |
|
959 for (LDObject* obj : oldsel) |
933 for (LDObject* obj : oldsel) |
960 recompileObject (obj); |
934 compileObject (obj); |
961 } |
935 } |
962 |
936 |
963 m_picking = true; |
937 m_picking = true; |
964 |
938 |
965 // Paint the picking scene |
939 // Paint the picking scene |
1007 assert (viewport[3] == m_height); |
981 assert (viewport[3] == m_height); |
1008 |
982 |
1009 // Read pixels from the color buffer. |
983 // Read pixels from the color buffer. |
1010 glReadPixels (x0, viewport[3] - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); |
984 glReadPixels (x0, viewport[3] - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); |
1011 |
985 |
|
986 LDObject* removedObj = null; |
|
987 |
1012 // Go through each pixel read and add them to the selection. |
988 // Go through each pixel read and add them to the selection. |
1013 for (long i = 0; i < numpixels; ++i) { |
989 for (long i = 0; i < numpixels; ++i) { |
1014 uint32 idx = |
990 uint32 idx = |
1015 (*(pixelptr) * 0x10000) + |
991 (*(pixelptr) * 0x10000) + |
1016 (*(pixelptr + 1) * 0x00100) + |
992 (*(pixelptr + 1) * 0x00100) + |
1050 std::sort (sel.begin(), sel.end ()); |
1026 std::sort (sel.begin(), sel.end ()); |
1051 std::vector<LDObject*>::iterator pos = std::unique (sel.begin (), sel.end ()); |
1027 std::vector<LDObject*>::iterator pos = std::unique (sel.begin (), sel.end ()); |
1052 sel.resize (std::distance (sel.begin (), pos)); |
1028 sel.resize (std::distance (sel.begin (), pos)); |
1053 |
1029 |
1054 // Update everything now. |
1030 // Update everything now. |
1055 g_win->buildObjList (); |
1031 g_win->updateSelection (); |
|
1032 |
|
1033 // Recompile the objects now to update their color |
|
1034 for (LDObject* obj : sel) |
|
1035 compileObject (obj); |
1056 |
1036 |
1057 m_picking = false; |
1037 m_picking = false; |
1058 m_rangepick = false; |
1038 m_rangepick = false; |
1059 glEnable (GL_DITHER); |
1039 glEnable (GL_DITHER); |
1060 |
1040 |
1061 setBackground (); |
1041 setBackground (); |
1062 updateSelFlash (); |
1042 updateSelFlash (); |
1063 |
|
1064 for (LDObject* obj : g_win->sel ()) |
|
1065 recompileObject (obj); |
|
1066 |
|
1067 if (removedObject != null) |
|
1068 recompileObject (removedObject); |
|
1069 |
1043 |
1070 drawGLScene (); |
1044 drawGLScene (); |
1071 swapBuffers (); |
1045 swapBuffers (); |
1072 update (); |
1046 update (); |
1073 } |
1047 } |
1156 } |
1130 } |
1157 |
1131 |
1158 // ============================================================================= |
1132 // ============================================================================= |
1159 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
1133 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
1160 // ============================================================================= |
1134 // ============================================================================= |
1161 void GLRenderer::recompileObject (LDObject* obj) { |
1135 void GLRenderer::compileObject (LDObject* obj) { |
1162 // Replace the old list with the new one. |
1136 for (const GL::ListType listType : g_glListTypes) { |
1163 GLuint uList = glGenLists (1); |
1137 GLuint list = glGenLists (1); |
1164 glNewList (uList, GL_COMPILE); |
1138 glNewList (list, GL_COMPILE); |
1165 |
1139 |
1166 compileOneObject (obj); |
1140 obj->glLists[listType] = list; |
1167 |
1141 compileList (obj, listType); |
1168 glEndList (); |
1142 |
1169 obj->uGLList = uList; |
1143 glEndList (); |
|
1144 } |
1170 } |
1145 } |
1171 |
1146 |
1172 // ============================================================================= |
1147 // ============================================================================= |
1173 uchar* GLRenderer::screencap (ushort& w, ushort& h) { |
1148 uchar* GLRenderer::screencap (ushort& w, ushort& h) { |
1174 w = m_width; |
1149 w = m_width; |
1191 // ============================================================================= |
1166 // ============================================================================= |
1192 void GLRenderer::slot_timerUpdate () { |
1167 void GLRenderer::slot_timerUpdate () { |
1193 ++g_pulseTick %= g_numPulseTicks; |
1168 ++g_pulseTick %= g_numPulseTicks; |
1194 |
1169 |
1195 for (LDObject* obj : g_win->sel ()) |
1170 for (LDObject* obj : g_win->sel ()) |
1196 recompileObject (obj); |
1171 compileObject (obj); |
1197 |
1172 |
1198 update (); |
1173 update (); |
1199 } |
1174 } |
1200 |
1175 |
1201 // ============================================================================= |
1176 // ============================================================================= |