src/gldraw.cpp

changeset 191
9bb6a17305ad
parent 189
ac2d3e8dd110
child 192
c414924a647c
equal deleted inserted replaced
190:82f784cf2ce5 191:9bb6a17305ad
29 #include "misc.h" 29 #include "misc.h"
30 #include "history.h" 30 #include "history.h"
31 31
32 static double g_objOffset[3]; 32 static double g_objOffset[3];
33 33
34 static short g_pulseTick = 0;
35 static const short g_numPulseTicks = 8;
36 static const short g_pulseInterval = 65;
37
38 static const struct staticCameraMeta { 34 static const struct staticCameraMeta {
39 const char glrotate[3]; 35 const char glrotate[3];
40 const Axis axisX, axisY; 36 const Axis axisX, axisY;
41 const bool negX, negY; 37 const bool negX, negY;
42 } g_staticCameras[6] = { 38 } g_staticCameras[6] = {
51 cfg (str, gl_bgcolor, "#CCCCD9"); 47 cfg (str, gl_bgcolor, "#CCCCD9");
52 cfg (str, gl_maincolor, "#707078"); 48 cfg (str, gl_maincolor, "#707078");
53 cfg (float, gl_maincolor_alpha, 1.0); 49 cfg (float, gl_maincolor_alpha, 1.0);
54 cfg (int, gl_linethickness, 2); 50 cfg (int, gl_linethickness, 2);
55 cfg (bool, gl_colorbfc, true); 51 cfg (bool, gl_colorbfc, true);
56 cfg (bool, gl_selflash, false);
57 cfg (int, gl_camera, GLRenderer::Free); 52 cfg (int, gl_camera, GLRenderer::Free);
58 cfg (bool, gl_blackedges, true); 53 cfg (bool, gl_blackedges, true);
59 cfg (bool, gl_axes, false); 54 cfg (bool, gl_axes, false);
60 55
61 // CameraIcon::img is a heap-allocated QPixmap because otherwise it gets 56 // CameraIcon::img is a heap-allocated QPixmap because otherwise it gets
96 m_picking = m_rangepick = false; 91 m_picking = m_rangepick = false;
97 m_camera = (GLRenderer::Camera) gl_camera.value; 92 m_camera = (GLRenderer::Camera) gl_camera.value;
98 m_drawToolTip = false; 93 m_drawToolTip = false;
99 m_planeDraw = false; 94 m_planeDraw = false;
100 95
101 m_pulseTimer = new QTimer (this);
102 connect (m_pulseTimer, SIGNAL (timeout ()), this, SLOT (slot_timerUpdate ()));
103
104 m_toolTipTimer = new QTimer (this); 96 m_toolTipTimer = new QTimer (this);
105 m_toolTipTimer->setSingleShot (true); 97 m_toolTipTimer->setSingleShot (true);
106 connect (m_toolTipTimer, SIGNAL (timeout ()), this, SLOT (slot_toolTipTimer ())); 98 connect (m_toolTipTimer, SIGNAL (timeout ()), this, SLOT (slot_toolTipTimer ()));
107 99
108 m_thickBorderPen = QPen (QColor (0, 0, 0, 208), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); 100 m_thickBorderPen = QPen (QColor (0, 0, 0, 208), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
117 CameraIcon* info = &g_CameraIcons[cam]; 109 CameraIcon* info = &g_CameraIcons[cam];
118 info->img = new QPixmap (getIcon (iconname)); 110 info->img = new QPixmap (getIcon (iconname));
119 info->cam = cam; 111 info->cam = cam;
120 } 112 }
121 113
122 calcCameraIconRects (); 114 calcCameraIcons ();
123 } 115 }
124 116
125 // ============================================================================= 117 // =============================================================================
126 GLRenderer::~GLRenderer() { 118 GLRenderer::~GLRenderer() {
127 for (CameraIcon& info : g_CameraIcons) 119 for (CameraIcon& info : g_CameraIcons)
129 } 121 }
130 122
131 // ============================================================================= 123 // =============================================================================
132 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 124 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
133 // ============================================================================= 125 // =============================================================================
134 void GLRenderer::calcCameraIconRects () { 126 void GLRenderer::calcCameraIcons () {
135 ushort i = 0; 127 ushort i = 0;
136 128
137 for (CameraIcon& info : g_CameraIcons) { 129 for (CameraIcon& info : g_CameraIcons) {
138 const long x1 = (m_width - (info.cam != Free ? 48 : 16)) + ((i % 3) * 16) - 1, 130 const long x1 = (m_width - (info.cam != Free ? 48 : 16)) + ((i % 3) * 16) - 1,
139 y1 = ((i / 3) * 16) + 1; 131 y1 = ((i / 3) * 16) + 1;
165 glLineWidth (gl_linethickness); 157 glLineWidth (gl_linethickness);
166 158
167 setAutoFillBackground (false); 159 setAutoFillBackground (false);
168 setMouseTracking (true); 160 setMouseTracking (true);
169 setFocusPolicy (Qt::WheelFocus); 161 setFocusPolicy (Qt::WheelFocus);
170 compileObjects (); 162 compileAllObjects ();
171 } 163 }
172 164
173 // ============================================================================= 165 // =============================================================================
174 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 166 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
175 // ============================================================================= 167 // =============================================================================
197 } 189 }
198 190
199 // ============================================================================= 191 // =============================================================================
200 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 192 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
201 // ============================================================================= 193 // =============================================================================
202 static vector<short> g_daWarnedColors; 194 static vector<short> g_warnedColors;
203 void GLRenderer::setObjectColor (LDObject* obj, const ListType list) { 195 void GLRenderer::setObjectColor (LDObject* obj, const ListType list) {
204 QColor qcol; 196 QColor qcol;
205 197
206 if (!obj->isColored ()) 198 if (!obj->isColored ())
207 return; 199 return;
208 200
209 if (list == GL::PickList) { 201 if (list == GL::PickList) {
210 // Make the color by the object's index color if we're picking, so we can 202 // Make the color by the object's index color if we're picking, so we can
211 // make the index from the color we get from the picking results. 203 // make the index from the color we get from the picking results. Be sure
212 long i = obj->getIndex (g_curfile); 204 // to use the top level parent's index since inlinees don't have an index.
213 205 long i = obj->topLevelParent ()->getIndex (g_curfile);
214 // If we couldn't find the index, this object must not be from this file,
215 // therefore it must be an object inlined from a subfile reference or
216 // decomposed from a radial. Find the top level parent object and use
217 // its index.
218 if (i == -1)
219 i = obj->topLevelParent ()->getIndex (g_curfile);
220 206
221 // We should have the index now. 207 // We should have the index now.
222 assert (i != -1); 208 assert (i != -1);
223 209
224 // Calculate a color based from this index. This method caters for 210 // Calculate a color based from this index. This method caters for
230 216
231 qglColor (QColor (r, g, b, 255)); 217 qglColor (QColor (r, g, b, 255));
232 return; 218 return;
233 } 219 }
234 220
235 #if 0 221 if ((list == BFCFrontList || list == BFCBackList) &&
236 if (gl_colorbfc &&
237 obj->getType () != LDObject::Line && 222 obj->getType () != LDObject::Line &&
238 obj->getType () != LDObject::CondLine) 223 obj->getType () != LDObject::CondLine)
239 { 224 {
240 if (bBackSide) 225 if (list == GL::BFCFrontList)
241 glColor4f (0.9f, 0.0f, 0.0f, 1.0f); 226 qcol = QColor (80, 192, 0);
242 else 227 else
243 glColor4f (0.0f, 0.8f, 0.0f, 1.0f); 228 qcol = QColor (224, 0, 0);
244 return; 229 } else {
245 } 230 if (obj->color == maincolor)
246 #endif
247
248 if (obj->color == maincolor)
249 qcol = getMainColor ();
250 else {
251 color* col = getColor (obj->color);
252 qcol = col->faceColor;
253 }
254
255 if (obj->color == edgecolor) {
256 qcol = Qt::black;
257 color* col;
258
259 if (!gl_blackedges && obj->parent != null && (col = getColor (obj->parent->color)) != null)
260 qcol = col->edgeColor;
261 }
262
263 if (qcol.isValid () == false) {
264 // The color was unknown. Use main color to make the object at least
265 // not appear pitch-black.
266 if (obj->color != edgecolor)
267 qcol = getMainColor (); 231 qcol = getMainColor ();
268 232 else {
269 // Warn about the unknown colors, but only once. 233 color* col = getColor (obj->color);
270 for (short i : g_daWarnedColors) 234 qcol = col->faceColor;
271 if (obj->color == i) 235 }
272 return; 236
273 237 if (obj->color == edgecolor) {
274 printf ("%s: Unknown color %d!\n", __func__, obj->color); 238 qcol = Qt::black;
275 g_daWarnedColors.push_back (obj->color); 239 color* col;
276 return; 240
241 if (!gl_blackedges && obj->parent != null && (col = getColor (obj->parent->color)) != null)
242 qcol = col->edgeColor;
243 }
244
245 if (qcol.isValid () == false) {
246 // The color was unknown. Use main color to make the object at least
247 // not appear pitch-black.
248 if (obj->color != edgecolor)
249 qcol = getMainColor ();
250
251 // Warn about the unknown colors, but only once.
252 for (short i : g_warnedColors)
253 if (obj->color == i)
254 return;
255
256 printf ("%s: Unknown color %d!\n", __func__, obj->color);
257 g_warnedColors.push_back (obj->color);
258 return;
259 }
277 } 260 }
278 261
279 long r = qcol.red (), 262 long r = qcol.red (),
280 g = qcol.green (), 263 g = qcol.green (),
281 b = qcol.blue (), 264 b = qcol.blue (),
282 a = qcol.alpha (); 265 a = qcol.alpha ();
283 266
284 // Brighten it up for the select list. 267 if (obj->topLevelParent ()->selected ()) {
285 if (list == GL::SelectList) { 268 // Brighten it up for the select list.
286 const uchar add = 51; 269 const uchar add = 51;
270
287 r = min (r + add, 255l); 271 r = min (r + add, 255l);
288 g = min (g + add, 255l); 272 g = min (g + add, 255l);
289 b = min (b + add, 255l); 273 b = min (b + add, 255l);
290 } 274 }
291 275
304 swapBuffers (); 288 swapBuffers ();
305 } 289 }
306 290
307 // ============================================================================= 291 // =============================================================================
308 void GLRenderer::hardRefresh () { 292 void GLRenderer::hardRefresh () {
309 compileObjects (); 293 compileAllObjects ();
310 refresh (); 294 refresh ();
311 295
312 glLineWidth (gl_linethickness); 296 glLineWidth (gl_linethickness);
313 } 297 }
314 298
317 // ============================================================================= 301 // =============================================================================
318 void GLRenderer::resizeGL (int w, int h) { 302 void GLRenderer::resizeGL (int w, int h) {
319 m_width = w; 303 m_width = w;
320 m_height = h; 304 m_height = h;
321 305
322 calcCameraIconRects (); 306 calcCameraIcons ();
323 307
324 glViewport (0, 0, w, h); 308 glViewport (0, 0, w, h);
325 glMatrixMode (GL_PROJECTION); 309 glMatrixMode (GL_PROJECTION);
326 glLoadIdentity (); 310 glLoadIdentity ();
327 gluPerspective (45.0f, (double)w / (double)h, 1.0f, 10000.0f); 311 gluPerspective (45.0f, (double)w / (double)h, 1.0f, 10000.0f);
361 glRotatef (m_rotX, 1.0f, 0.0f, 0.0f); 345 glRotatef (m_rotX, 1.0f, 0.0f, 0.0f);
362 glRotatef (m_rotY, 0.0f, 1.0f, 0.0f); 346 glRotatef (m_rotY, 0.0f, 1.0f, 0.0f);
363 glRotatef (m_rotZ, 0.0f, 0.0f, 1.0f); 347 glRotatef (m_rotZ, 0.0f, 0.0f, 1.0f);
364 } 348 }
365 349
366 for (LDObject* obj : g_curfile->m_objs) { 350 if (gl_colorbfc && !m_picking) {
367 if (obj->hidden ()) 351 glEnable (GL_CULL_FACE);
368 continue; // Don't draw hidden objects 352
369 353 for (LDObject* obj : g_curfile->m_objs) {
370 glCallList (obj->glLists[(m_picking) ? PickList : (obj->selected ()) ? SelectList : NormalList]); 354 if (obj->hidden ())
355 continue;
356
357 glCullFace (GL_BACK);
358 glCallList (obj->glLists[BFCFrontList]);
359
360 glCullFace (GL_FRONT);
361 glCallList (obj->glLists[BFCBackList]);
362 }
363
364 glDisable (GL_CULL_FACE);
365 } else {
366 for (LDObject* obj : g_curfile->m_objs) {
367 if (obj->hidden ())
368 continue;
369
370 glCallList (obj->glLists[(m_picking) ? PickList : NormalList]);
371 }
371 } 372 }
372 373
373 if (gl_axes && !m_picking) 374 if (gl_axes && !m_picking)
374 glCallList (m_axeslist); 375 glCallList (m_axeslist);
375 376
596 } 597 }
597 598
598 // ============================================================================= 599 // =============================================================================
599 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 600 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
600 // ============================================================================= 601 // =============================================================================
601 void GLRenderer::compileObjects () { 602 void GLRenderer::compileAllObjects () {
602 if (g_BBox.empty () == false) { 603 if (g_BBox.empty () == false) {
603 g_objOffset[X] = -(g_BBox.v0 ()[X] + g_BBox.v1 ()[X]) / 2; 604 g_objOffset[X] = -(g_BBox.v0 ()[X] + g_BBox.v1 ()[X]) / 2;
604 g_objOffset[Y] = -(g_BBox.v0 ()[Y] + g_BBox.v1 ()[Y]) / 2; 605 g_objOffset[Y] = -(g_BBox.v0 ()[Y] + g_BBox.v1 ()[Y]) / 2;
605 g_objOffset[Z] = -(g_BBox.v0 ()[Z] + g_BBox.v1 ()[Z]) / 2; 606 g_objOffset[Z] = -(g_BBox.v0 ()[Z] + g_BBox.v1 ()[Z]) / 2;
606 } else { 607 } else {
630 } 631 }
631 632
632 // ============================================================================= 633 // =============================================================================
633 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 634 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
634 // ============================================================================= 635 // =============================================================================
636 static bool g_glInvert = false;
637
635 void GLRenderer::compileSubObject (LDObject* obj, const GLenum gltype) { 638 void GLRenderer::compileSubObject (LDObject* obj, const GLenum gltype) {
636 glBegin (gltype); 639 glBegin (gltype);
637 640
638 const short numverts = (obj->getType () != LDObject::CondLine) ? obj->vertices () : 2; 641 const short numverts = (obj->getType () != LDObject::CondLine) ? obj->vertices () : 2;
639 642
640 for (short i = 0; i < numverts; ++i) 643 if (g_glInvert == false)
641 compileVertex (obj->coords[i]); 644 for (short i = 0; i < numverts; ++i)
645 compileVertex (obj->coords[i]);
646 else
647 for (short i = numverts - 1; i >= 0; --i)
648 compileVertex (obj->coords[i]);
642 649
643 glEnd (); 650 glEnd ();
644 } 651 }
645 652
646 // ============================================================================= 653 // =============================================================================
676 case LDObject::Subfile: 683 case LDObject::Subfile:
677 { 684 {
678 LDSubfile* ref = static_cast<LDSubfile*> (obj); 685 LDSubfile* ref = static_cast<LDSubfile*> (obj);
679 vector<LDObject*> objs = ref->inlineContents (true, true); 686 vector<LDObject*> objs = ref->inlineContents (true, true);
680 687
688 bool oldinvert = g_glInvert;
689
690 if (ref->transform.determinant () < 0)
691 g_glInvert = !g_glInvert;
692
693 LDObject* prev = ref->prev ();
694 if (prev->getType () == LDObject::BFC && static_cast<LDBFC*> (prev)->type == LDBFC::InvertNext)
695 g_glInvert = !g_glInvert;
696
681 for (LDObject* obj : objs) { 697 for (LDObject* obj : objs) {
682 compileList (obj, list); 698 compileList (obj, list);
683 delete obj; 699 delete obj;
684 } 700 }
701
702 g_glInvert = oldinvert;
685 } 703 }
686 break; 704 break;
687 705
688 case LDObject::Radial: 706 case LDObject::Radial:
689 { 707 {
690 LDRadial* pRadial = static_cast<LDRadial*> (obj); 708 LDRadial* rad = static_cast<LDRadial*> (obj);
691 std::vector<LDObject*> objs = pRadial->decompose (true); 709 std::vector<LDObject*> objs = rad->decompose (true);
710
711 bool oldinvert = g_glInvert;
712 if (rad->transform.determinant () < 0)
713 g_glInvert = !g_glInvert;
714
715 LDObject* prev = rad->prev ();
716 if (prev->getType () == LDObject::BFC && static_cast<LDBFC*> (prev)->type == LDBFC::InvertNext)
717 g_glInvert = !g_glInvert;
692 718
693 for (LDObject* obj : objs) { 719 for (LDObject* obj : objs) {
694 compileList (obj, list); 720 compileList (obj, list);
695 delete obj; 721 delete obj;
696 } 722 }
723
724 g_glInvert = oldinvert;
697 } 725 }
698 break; 726 break;
699 727
700 #if 0 728 #if 0
701 TODO: find a proper way to draw vertices without having them be affected by zoom. 729 TODO: find a proper way to draw vertices without having them be affected by zoom.
896 } 924 }
897 925
898 // ============================================================================= 926 // =============================================================================
899 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 927 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
900 // ============================================================================= 928 // =============================================================================
901 void GLRenderer::updateSelFlash () {
902 if (gl_selflash && g_win->sel ().size() > 0) {
903 m_pulseTimer->start (g_pulseInterval);
904 g_pulseTick = 0;
905 } else
906 m_pulseTimer->stop ();
907 }
908
909 // =============================================================================
910 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
911 // =============================================================================
912 void GLRenderer::pick (uint mouseX, uint mouseY) { 929 void GLRenderer::pick (uint mouseX, uint mouseY) {
913 // Check if we selected a camera icon 930 // Check if we selected a camera icon
914 if (!m_rangepick) { 931 if (!m_rangepick) {
915 QPoint pos (mouseX, mouseY); 932 QPoint pos (mouseX, mouseY);
916 933
928 // Clear the selection if we do not wish to add to it. 945 // Clear the selection if we do not wish to add to it.
929 if (!m_addpick) { 946 if (!m_addpick) {
930 std::vector<LDObject*> oldsel = g_win->sel (); 947 std::vector<LDObject*> oldsel = g_win->sel ();
931 g_win->sel ().clear (); 948 g_win->sel ().clear ();
932 949
933 for (LDObject* obj : oldsel) 950 for (LDObject* obj : oldsel) {
951 obj->setSelected (false);
934 compileObject (obj); 952 compileObject (obj);
953 }
935 } 954 }
936 955
937 m_picking = true; 956 m_picking = true;
938 957
939 // Paint the picking scene 958 // Paint the picking scene
940 glDisable (GL_DITHER); 959 glDisable (GL_DITHER);
941 glClearColor (1.0f, 1.0f, 1.0f, 1.0f); 960 glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
961
942 drawGLScene (); 962 drawGLScene ();
943 963
944 glGetIntegerv (GL_VIEWPORT, viewport); 964 glGetIntegerv (GL_VIEWPORT, viewport);
945 965
946 short x0 = mouseX, 966 short x0 = mouseX,
1004 bool removed = false; 1024 bool removed = false;
1005 1025
1006 for (ulong i = 0; i < g_win->sel ().size(); ++i) { 1026 for (ulong i = 0; i < g_win->sel ().size(); ++i) {
1007 if (g_win->sel ()[i] == obj) { 1027 if (g_win->sel ()[i] == obj) {
1008 g_win->sel ().erase (g_win->sel ().begin () + i); 1028 g_win->sel ().erase (g_win->sel ().begin () + i);
1029 obj->setSelected (false);
1009 removed = true; 1030 removed = true;
1010 removedObj = obj; 1031 removedObj = obj;
1011 } 1032 }
1012 } 1033 }
1013 1034
1032 1053
1033 // Recompile the objects now to update their color 1054 // Recompile the objects now to update their color
1034 for (LDObject* obj : sel) 1055 for (LDObject* obj : sel)
1035 compileObject (obj); 1056 compileObject (obj);
1036 1057
1058 if (removedObj)
1059 compileObject (removedObj);
1060
1037 m_picking = false; 1061 m_picking = false;
1038 m_rangepick = false; 1062 m_rangepick = false;
1039 glEnable (GL_DITHER); 1063 glEnable (GL_DITHER);
1040 1064
1041 setBackground (); 1065 setBackground ();
1042 updateSelFlash ();
1043
1044 update (); 1066 update ();
1045 } 1067 }
1046 1068
1047 // ============================================================================= 1069 // =============================================================================
1048 void GLRenderer::beginPlaneDraw () { 1070 void GLRenderer::beginPlaneDraw () {
1157 1179
1158 // Restore the background 1180 // Restore the background
1159 setBackground (); 1181 setBackground ();
1160 1182
1161 return cap; 1183 return cap;
1162 }
1163
1164 // =============================================================================
1165 void GLRenderer::slot_timerUpdate () {
1166 ++g_pulseTick %= g_numPulseTicks;
1167
1168 for (LDObject* obj : g_win->sel ())
1169 compileObject (obj);
1170
1171 update ();
1172 } 1184 }
1173 1185
1174 // ============================================================================= 1186 // =============================================================================
1175 void GLRenderer::slot_toolTipTimer () { 1187 void GLRenderer::slot_toolTipTimer () {
1176 // We come here if the cursor has stayed in one place for longer than a 1188 // We come here if the cursor has stayed in one place for longer than a

mercurial