1 /*****************************************************************************
2 * *
3 * Elmer, A Finite Element Software for Multiphysical Problems *
4 * *
5 * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License *
9 * as published by the Free Software Foundation; either version 2 *
10 * of the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program (in file fem/GPL-2); if not, write to the *
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 * *
22 *****************************************************************************/
23
24 /*****************************************************************************
25 * *
26 * ElmerGUI glwidget *
27 * *
28 *****************************************************************************
29 * *
30 * Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *
31 * Email: Juha.Ruokolainen@csc.fi *
32 * Web: http://www.csc.fi/elmer *
33 * Address: CSC - IT Center for Science Ltd. *
34 * Keilaranta 14 *
35 * 02101 Espoo, Finland *
36 * *
37 * Original Date: 15 Mar 2008 *
38 * *
39 *****************************************************************************/
40
41 #include <QtGui>
42 #include <QtOpenGL>
43 #include <QWheelEvent>
44 #include <QKeyEvent>
45 #include <math.h>
46 #include <iostream>
47 #include <stdio.h>
48 #include "glwidget.h"
49 #include "mainwindow.h"
50
51 using namespace std;
52
53 #define MY_PI 3.14159265
54 #define ZSHIFT -5.0
55
56 // Get qreal regardless of whether it's float or double
glGetQrealv(GLenum e,GLfloat * data)57 static inline void glGetQrealv(GLenum e, GLfloat* data) { glGetFloatv(e,data); }
glGetQrealv(GLenum e,GLdouble * data)58 static inline void glGetQrealv(GLenum e, GLdouble* data) { glGetDoublev(e,data); }
glMultMatrixq(const GLdouble * m)59 static inline void glMultMatrixq( const GLdouble *m ) { glMultMatrixd(m); }
glMultMatrixq(const GLfloat * m)60 static inline void glMultMatrixq( const GLfloat *m ) { glMultMatrixf(m); }
61
list_t()62 list_t::list_t()
63 {
64 nature = PDE_UNKNOWN;
65 type = UNKNOWNLIST;
66 index = -1;
67 object = 0;
68 child = -1;
69 parent = -1;
70 selected = false;
71 visible = false;
72 }
73
~list_t()74 list_t::~list_t()
75 {
76 }
77
setNature(int n)78 void list_t::setNature(int n)
79 {
80 this->nature = n;
81 }
82
getNature(void) const83 int list_t::getNature(void) const
84 {
85 return this->nature;
86 }
87
setType(int n)88 void list_t::setType(int n)
89 {
90 this->type = n;
91 }
92
getType(void) const93 int list_t::getType(void) const
94 {
95 return this->type;
96 }
97
setIndex(int n)98 void list_t::setIndex(int n)
99 {
100 this->index = n;
101 }
102
getIndex(void) const103 int list_t::getIndex(void) const
104 {
105 return this->index;
106 }
107
setObject(GLuint n)108 void list_t::setObject(GLuint n)
109 {
110 this->object = n;
111 }
112
getObject(void) const113 GLuint list_t::getObject(void) const
114 {
115 return this->object;
116 }
117
setChild(int n)118 void list_t::setChild(int n)
119 {
120 this->child = n;
121 }
122
getChild(void) const123 int list_t::getChild(void) const
124 {
125 return this->child;
126 }
127
setParent(int n)128 void list_t::setParent(int n)
129 {
130 this->parent = n;
131 }
132
getParent(void) const133 int list_t::getParent(void) const
134 {
135 return this->parent;
136 }
137
setSelected(bool b)138 void list_t::setSelected(bool b)
139 {
140 this->selected = b;
141 }
142
isSelected(void) const143 bool list_t::isSelected(void) const
144 {
145 return this->selected;
146 }
147
setVisible(bool b)148 void list_t::setVisible(bool b)
149 {
150 this->visible = b;
151 }
152
isVisible(void) const153 bool list_t::isVisible(void) const
154 {
155 return this->visible;
156 }
157
158 // Construct glWidget...
159 //-----------------------------------------------------------------------------
GLWidget(QWidget * parent)160 GLWidget::GLWidget(QWidget *parent)
161 : QGLWidget(parent)
162 {
163 backgroundColor = Qt::white;
164 surfaceColor = Qt::cyan;
165 edgeColor = Qt::green;
166 surfaceMeshColor = Qt::black;
167 sharpEdgeColor = Qt::black;
168
169 stateOrtho = false;
170 stateFlatShade = true;
171 stateDrawSurfaceMesh = true;
172 stateDrawVolumeMesh = false;
173 stateDrawSharpEdges = true;
174 stateDrawSurfaceElements = true;
175 stateDrawEdgeElements = true;
176 stateDrawCoordinates = false;
177 stateDrawSurfaceNumbers = false;
178 stateDrawEdgeNumbers = false;
179 stateDrawNodeNumbers = false;
180 stateDrawBoundaryIndex = false;
181 stateDrawBodyIndex = false;
182 stateBcColors = false;
183 stateBodyColors = false;
184
185 currentlySelectedBody = -1;
186
187 drawScale = 1.0;
188 drawTranslate[0] = 0.0;
189 drawTranslate[1] = 0.0;
190 drawTranslate[2] = 0.0;
191
192 mesh = NULL;
193
194 helpers = new Helpers;
195 meshutils = new Meshutils;
196
197 ctrlPressed = false;
198 shiftPressed = false;
199 altPressed = false;
200
201 // Coordinate axis:
202 quadric_axis = gluNewQuadric();
203
204 // Background image:
205 stateUseBgImage = false;
206 stateStretchBgImage = false;
207 stateAlignRightBgImage = false;
208 bgImageFileName = "";
209 bgTexture = 0;
210 bgSizeX = 0;
211 bgSizeY = 0;
212 }
213
214
215 // dtor...
216 //-----------------------------------------------------------------------------
~GLWidget()217 GLWidget::~GLWidget()
218 {
219 }
220
221
222 // Min size hint...
223 //-----------------------------------------------------------------------------
minimumSizeHint() const224 QSize GLWidget::minimumSizeHint() const
225 {
226 return QSize(64, 64);
227 }
228
229
230 // Default size...
231 //-----------------------------------------------------------------------------
sizeHint() const232 QSize GLWidget::sizeHint() const
233 {
234 return QSize(720, 576);
235 }
236
setMesh(mesh_t * m)237 void GLWidget::setMesh(mesh_t *m)
238 {
239 this->mesh = m;
240 }
241
getMesh(void) const242 mesh_t* GLWidget::getMesh(void) const
243 {
244 return this->mesh;
245 }
246
newMesh(void)247 void GLWidget::newMesh(void)
248 {
249 this->mesh = new mesh_t;
250 }
251
deleteMesh(void)252 void GLWidget::deleteMesh(void)
253 {
254 delete this->mesh;
255 }
256
hasMesh(void) const257 bool GLWidget::hasMesh(void) const
258 {
259 if(this->mesh)
260 return true;
261
262 return false;
263 }
264
265 // Init GL...
266 //-----------------------------------------------------------------------------
initializeGL()267 void GLWidget::initializeGL()
268 {
269 cout << "Initialize GL" << endl;
270 cout << "Vendor: " << glGetString(GL_VENDOR) << endl;
271 cout << "Renderer: " << glGetString(GL_RENDERER) << endl;
272 cout << "Version: " << glGetString(GL_VERSION) << endl;
273 cout.flush();
274
275 static GLfloat light_ambient[] = {0.2, 0.2, 0.2, 1.0};
276 static GLfloat light_diffuse[] = {0.6, 0.6, 0.6, 1.0};
277 static GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
278 static GLfloat light_position[] = {0.0, 0.0, 5.0, 0.0};
279
280 static GLfloat mat_ambient[] = {0.2, 0.2, 0.2, 1.0};
281 static GLfloat mat_diffuse[] = {1.0, 1.0, 1.0, 1.0};
282 static GLfloat mat_specular[] = {0.9, 0.9, 0.9, 1.0};
283 static GLfloat high_shininess[] = {20.0};
284
285 glMatrixMode(GL_MODELVIEW);
286 glLoadIdentity();
287
288 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
289 glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0);
290 glEnable(GL_LIGHTING);
291
292 glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,1.0);
293 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
294 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
295 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
296 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
297 glEnable(GL_LIGHT0);
298
299 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
300 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
301 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
302 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, high_shininess);
303 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
304 glEnable(GL_COLOR_MATERIAL);
305
306 glEnable(GL_DEPTH_TEST);
307 glDepthFunc(GL_LESS);
308 // glDepthRange(-10.0, 10.0);
309
310 glShadeModel(GL_SMOOTH);
311 // glEnable(GL_LINE_SMOOTH);
312
313 glEnable(GL_NORMALIZE);
314
315 qglClearColor(backgroundColor);
316
317 glEnable(GL_TEXTURE_2D);
318 }
319
320
321
322 // Paint event...
323 //-----------------------------------------------------------------------------
paintGL()324 void GLWidget::paintGL()
325 {
326 float xabs[3], xrel[3];
327
328 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
329
330 // Background image:
331 if(stateUseBgImage)
332 drawBgImage();
333
334 // FE objects:
335 if(getLists() > 0) {
336
337 for(int i = 0; i < getLists(); i++) {
338 list_t *l = getList(i);
339
340 if(l->isVisible()) {
341 glPushName(i);
342
343 if((l->getType() == SURFACEMESHLIST) && stateDrawSurfaceMesh) {
344 // translate slightly towards viewer
345 glMatrixMode(GL_PROJECTION);
346 glPushMatrix();
347 glTranslated(0, 0, 0.01);
348 glTranslated(0, 0, ZSHIFT);
349 glCallList(l->getObject());
350 glPopMatrix();
351 glMatrixMode(GL_MODELVIEW);
352
353 } else if((l->getType() == VOLUMEMESHLIST) && stateDrawVolumeMesh) {
354 // translate slightly towards viewer
355 glMatrixMode(GL_PROJECTION);
356 glPushMatrix();
357 glTranslated(0, 0, 0.01);
358 glTranslated(0, 0, ZSHIFT);
359 glCallList(l->getObject());
360 glPopMatrix();
361 glMatrixMode(GL_MODELVIEW);
362
363 } else if ((l->getType() == SHARPEDGELIST) && stateDrawSharpEdges) {
364 // translate slightly towards viewer
365 glMatrixMode(GL_PROJECTION);
366 glPushMatrix();
367 glTranslated(0, 0, 0.01);
368 glTranslated(0, 0, ZSHIFT);
369 glCallList(l->getObject());
370 glPopMatrix();
371 glMatrixMode(GL_MODELVIEW);
372
373 } else if((l->getType() == EDGELIST) && stateDrawEdgeElements ) {
374 // translate slightly towards viewer
375 glMatrixMode(GL_PROJECTION);
376 glPushMatrix();
377 glTranslated(0, 0, 0.02);
378 glTranslated(0, 0, ZSHIFT);
379 glCallList(l->getObject());
380 glPopMatrix();
381 glMatrixMode(GL_MODELVIEW);
382
383 } else if((l->getType() == SURFACELIST) && stateDrawSurfaceElements ) {
384 glMatrixMode(GL_PROJECTION);
385 glPushMatrix();
386 glTranslated(0, 0, ZSHIFT);
387 glCallList(l->getObject());
388 glPopMatrix();
389 glMatrixMode(GL_MODELVIEW);
390
391 } else {
392 glMatrixMode(GL_PROJECTION);
393 glPushMatrix();
394 glTranslated(0, 0, ZSHIFT);
395 glCallList(l->getObject());
396 glPopMatrix();
397 glMatrixMode(GL_MODELVIEW);
398 }
399
400 glPopName();
401 }
402 }
403 }
404
405 if(stateDrawCoordinates) {
406 // push a dummy name
407 glPushName(DUMMY_NAME);
408 drawCoordinates();
409 glPopName();
410 }
411
412 if(mesh) {
413 if(stateDrawSurfaceNumbers) {
414 glMatrixMode(GL_PROJECTION);
415 glPushMatrix();
416 glTranslated(0, 0, ZSHIFT);
417 glTranslated(0, 0, 0.1);
418 glColor3d(0.5, 0, 0);
419
420 for(int i=0; i < mesh->getSurfaces(); i++) {
421 surface_t *surface = mesh->getSurface(i);
422 int nodes = surface->getCode() / 100;
423
424 xabs[0] = xabs[1] = xabs[2] = 0.0;
425
426 for(int j = 0; j < nodes; j++) {
427 int ind = surface->getNodeIndex(j);
428 xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
429 xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
430 xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
431 }
432
433 xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
434 xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
435 xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
436
437 renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
438 }
439
440 glPopMatrix();
441 glMatrixMode(GL_MODELVIEW);
442 }
443
444 if(stateDrawEdgeNumbers) {
445 glMatrixMode(GL_PROJECTION);
446 glPushMatrix();
447 glTranslated(0, 0, ZSHIFT);
448 glTranslated(0, 0, 0.1);
449 glColor3d(0.0, 0.5, 0);
450
451 for(int i=0; i < mesh->getEdges(); i++) {
452 edge_t *edge = mesh->getEdge(i);
453 int nodes = edge->getCode() / 100;
454
455 xabs[0] = xabs[1] = xabs[2] = 0.0;
456
457 for(int j = 0; j < nodes; j++) {
458 int ind = edge->getNodeIndex(j);
459 xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
460 xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
461 xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
462 }
463 xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
464 xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
465 xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
466
467 renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
468 }
469
470 glPopMatrix();
471 glMatrixMode(GL_MODELVIEW);
472 }
473
474 if(stateDrawNodeNumbers) {
475 glMatrixMode(GL_PROJECTION);
476 glPushMatrix();
477 glTranslated(0, 0, ZSHIFT);
478 glTranslated(0, 0, 0.1);
479 glColor3d(0, 0, 0.5);
480
481 for(int i = 0; i < mesh->getNodes(); i++) {
482 xabs[0] = mesh->getNode(i)->getX(0);
483 xabs[1] = mesh->getNode(i)->getX(1);
484 xabs[2] = mesh->getNode(i)->getX(2);
485
486 xrel[0] = (xabs[0] - drawTranslate[0]) / drawScale;
487 xrel[1] = (xabs[1] - drawTranslate[1]) / drawScale;
488 xrel[2] = (xabs[2] - drawTranslate[2]) / drawScale;
489
490 renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
491 }
492
493 glPopMatrix();
494 glMatrixMode(GL_MODELVIEW);
495 }
496
497 if(stateDrawBoundaryIndex || stateDrawBodyIndex) {
498 glMatrixMode(GL_PROJECTION);
499 glPushMatrix();
500 glTranslated(0, 0, ZSHIFT);
501 glTranslated(0, 0, 0.1);
502 glColor3d(0.5, 0, 0);
503
504 for(int i = 0; i < mesh->getEdges(); i++) {
505 edge_t *edge = mesh->getEdge(i);
506 int nodes = edge->getCode() / 100;
507
508 xabs[0] = xabs[1] = xabs[2] = 0.0;
509
510 for(int j = 0; j < nodes;j++) {
511 int ind = edge->getNodeIndex(j);
512 xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
513 xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
514 xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
515 }
516
517 xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
518 xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
519 xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
520
521 if(stateDrawBoundaryIndex && (edge->getNature() == PDE_BOUNDARY))
522 renderText(xrel[0], xrel[1], xrel[2], QString::number(edge->getIndex()));
523
524 if(stateDrawBodyIndex && (edge->getNature() == PDE_BULK))
525 renderText(xrel[0], xrel[1], xrel[2], QString::number(edge->getIndex()));
526 }
527
528 for(int i = 0; i < mesh->getSurfaces(); i++) {
529 surface_t *surface = mesh->getSurface(i);
530 int nodes = surface->getCode() / 100;
531
532 xabs[0] = xabs[1] = xabs[2] = 0.0;
533
534 for(int j = 0; j < nodes; j++) {
535 int ind = surface->getNodeIndex(j);
536 xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
537 xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
538 xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
539 }
540
541 xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
542 xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
543 xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
544
545 if(stateDrawBoundaryIndex && (surface->getNature() == PDE_BOUNDARY))
546 renderText(xrel[0], xrel[1], xrel[2], QString::number(surface->getIndex()));
547
548 if(stateDrawBodyIndex && (surface->getNature() == PDE_BULK))
549 renderText(xrel[0], xrel[1], xrel[2], QString::number(surface->getIndex()));
550
551 // case 3d:
552 if(stateDrawBodyIndex && (surface->getNature() == PDE_BOUNDARY)) {
553 for(int i = 0; i < surface->getElements(); i++) {
554 int j = surface->getElementIndex(i);
555 if(j >= 0) {
556 element_t *element = mesh->getElement(j);
557 renderText(xrel[0], xrel[1], xrel[2], QString::number(element->getIndex()));
558 }
559 }
560 }
561
562 }
563
564 glPopMatrix();
565 glMatrixMode(GL_MODELVIEW);
566 }
567 }
568 }
569
570
571 // Change projection...
572 //-----------------------------------------------------------------------------
changeProjection()573 void GLWidget::changeProjection()
574 {
575 GLint viewport[4];
576 glGetIntegerv(GL_VIEWPORT, viewport);
577
578 int width = viewport[2];
579 int height = viewport[3];
580 double top = 1.0;
581 double bottom = -1.0;
582 double left = -(double)width / (double)height;
583 double right = (double)width / (double)height;
584 double _near = -10.0;
585 double _far = 10.0;
586
587 if(stateOrtho) {
588 glViewport(0, 0, (GLint)width, (GLint)height);
589 glMatrixMode(GL_PROJECTION);
590 glLoadIdentity();
591 glOrtho(left, right, bottom, top, _near, _far);
592 glMatrixMode(GL_MODELVIEW);
593 } else {
594 glViewport(0, 0, (GLint)width, (GLint)height);
595 glMatrixMode(GL_PROJECTION);
596 glLoadIdentity();
597 gluPerspective(54.0, (float)width/(float)height, 0.1, 10.0);
598 glMatrixMode(GL_MODELVIEW);
599 }
600 }
601
602 // Resize window...
603 //-----------------------------------------------------------------------------
resizeGL(int width,int height)604 void GLWidget::resizeGL(int width, int height)
605 {
606 double top = 1.0;
607 double bottom = -1.0;
608 double left = -(double)width / (double)height;
609 double right = (double)width / (double)height;
610 double _near = -10.0;
611 double _far = 10.0;
612
613 if(stateOrtho) {
614 glViewport(0, 0, (GLint)width, (GLint)height);
615 glMatrixMode(GL_PROJECTION);
616 glLoadIdentity();
617 glOrtho(left, right, bottom, top, _near, _far);
618 glMatrixMode(GL_MODELVIEW);
619 } else {
620 glViewport(0, 0, (GLint)width, (GLint)height);
621 glMatrixMode(GL_PROJECTION);
622 glLoadIdentity();
623 gluPerspective(45.0, (float)width/(float)height, 0.1, 10.0);
624 glMatrixMode(GL_MODELVIEW);
625 }
626 }
627
628
629 // Focus in event...
630 //-----------------------------------------------------------------------------
focusInEvent(QFocusEvent * event)631 void GLWidget::focusInEvent(QFocusEvent *event)
632 {
633 Q_UNUSED(event)
634
635 // Should we check the key pressed status here?
636 }
637
638
639 // Key pressed...
640 //-----------------------------------------------------------------------------
keyPressEvent(QKeyEvent * event)641 void GLWidget::keyPressEvent(QKeyEvent *event)
642 {
643 if(event->key() == Qt::Key_Control)
644 ctrlPressed = true;
645
646 if(event->key() == Qt::Key_Shift)
647 shiftPressed = true;
648
649 if((event->key() == Qt::Key_Alt) || (event->key() == Qt::Key_AltGr))
650 altPressed = true;
651
652 if(event->key() == Qt::Key_Escape)
653 emit(escPressed());
654 }
655
656
657 // Key released...
658 //-----------------------------------------------------------------------------
keyReleaseEvent(QKeyEvent * event)659 void GLWidget::keyReleaseEvent(QKeyEvent *event)
660 {
661 if(event->key() == Qt::Key_Control)
662 ctrlPressed = false;
663
664 if(event->key() == Qt::Key_Shift)
665 shiftPressed = false;
666
667 if(event->key() == Qt::Key_Alt)
668 altPressed = false;
669 }
670
671
672
673 // Mouse button clicked...
674 //-----------------------------------------------------------------------------
mousePressEvent(QMouseEvent * event)675 void GLWidget::mousePressEvent(QMouseEvent *event)
676 {
677 lastPos = event->pos();
678 setFocus(); // for tracing keyboard events
679 }
680
681
682
683 // Mouse wheel rotates...
684 //-----------------------------------------------------------------------------
wheelEvent(QWheelEvent * event)685 void GLWidget::wheelEvent(QWheelEvent *event)
686 {
687 double s = exp((double)(event->delta())*0.001);
688 glScaled(s, s, s);
689 updateGL();
690 lastPos = event->pos();
691 getMatrix();
692 }
693
694
695
696 // Mouse moves...
697 //-----------------------------------------------------------------------------
mouseMoveEvent(QMouseEvent * event)698 void GLWidget::mouseMoveEvent(QMouseEvent *event)
699 {
700 GLint viewport[4];
701 glGetIntegerv(GL_VIEWPORT, viewport);
702
703 int dx = event->x() - lastPos.x();
704 int dy = event->y() - lastPos.y();
705
706 dy = -dy;
707
708 if (((event->buttons() & Qt::LeftButton) &&
709 (event->buttons() & Qt::MidButton)) ) {
710
711 // Scale:
712 double s = exp(dy*0.01);
713 glScaled(s, s, s);
714 updateGL();
715
716 } else if (event->buttons() & Qt::LeftButton) {
717
718 // Rotation:
719 double ax = -(double)dy;
720 double ay = (double)dx;
721 double az = 0.0;
722
723 double s = 180.0*sqrt(ax*ax+ay*ay+az*az)/(double)(viewport[3]+1);
724 double bx = invmatrix[0]*ax + invmatrix[4]*ay + invmatrix[8]*az;
725 double by = invmatrix[1]*ax + invmatrix[5]*ay + invmatrix[9]*az;
726 double bz = invmatrix[2]*ax + invmatrix[6]*ay + invmatrix[10]*az;
727 glRotated(s, bx, by, bz);
728 updateGL();
729
730 } else if (event->buttons() & Qt::MidButton) {
731
732 // Translation:
733 double s = 2.0/(double)(viewport[3]+1);
734 double ax = s*dx;
735 double ay = s*dy;
736 double az = 0.0;
737 glLoadIdentity();
738 glTranslated(ax, ay, az);
739 glMultMatrixq(matrix);
740 updateGL();
741 }
742
743 lastPos = event->pos();
744 getMatrix();
745 }
746
747
748
749 // Mouse button double clicked...
750 //-----------------------------------------------------------------------------
mouseDoubleClickEvent(QMouseEvent * event)751 void GLWidget::mouseDoubleClickEvent(QMouseEvent *event)
752 {
753 if(getLists() == 0)
754 return;
755
756 static list_t dummylist;
757 static GLuint buffer[1024];
758 const int bufferSize = sizeof(buffer)/sizeof(GLuint);
759
760 GLint viewport[4];
761 GLdouble projection[16];
762
763 GLint hits;
764 GLint i, j;
765
766 updateGL();
767
768 glSelectBuffer(bufferSize, buffer);
769 glRenderMode(GL_SELECT);
770 glInitNames();
771
772 glMatrixMode(GL_PROJECTION);
773 glPushMatrix();
774 glGetIntegerv(GL_VIEWPORT, viewport);
775 glGetDoublev(GL_PROJECTION_MATRIX, projection);
776 glLoadIdentity();
777
778 GLdouble x = event->x();
779 GLdouble y = (double)viewport[3]-event->y()-1;
780
781 GLdouble deltaX = 3.0;
782 GLdouble deltaY = 3.0;
783
784 gluPickMatrix(x, y, deltaX, deltaY, viewport);
785 glMultMatrixd(projection);
786
787 glMatrixMode(GL_MODELVIEW);
788
789 updateGL();
790 // paintGL();
791
792 hits = glRenderMode(GL_RENDER);
793
794 bool badDriver = true;
795 GLuint smallestz = DUMMY_NAME;
796 GLuint nearest = DUMMY_NAME;
797
798 if(hits != 0) {
799 for (i=0, j=0; i<hits; i++) {
800 GLuint minz = buffer[j+1];
801 GLuint resultz = buffer[j+3];
802
803 badDriver = (badDriver && (minz == 0x80000000));
804
805 if(minz < smallestz) {
806 nearest = resultz;
807 smallestz = minz;
808 }
809
810 j += 3 + buffer[j];
811 }
812 }
813
814 glMatrixMode(GL_PROJECTION);
815 glPopMatrix();
816 glMatrixMode(GL_MODELVIEW);
817
818 if(badDriver) {
819 cerr << "Detected bad GL-context or broken graphics driver" << endl;
820 cerr.flush();
821 cout << "glRenderMode(GL_RENDER) produces bad z-values" << endl;
822 cout << "Unable to reliably select objects" << endl;
823 cout << "Vendor: " << glGetString(GL_VENDOR) << endl;
824 cout << "Renderer: " << glGetString(GL_RENDERER) << endl;
825 cout << "Version: " << glGetString(GL_VERSION) << endl;
826 cout.flush();
827 }
828
829 // highlight the selected boundary:
830 if(nearest != DUMMY_NAME) {
831 list_t *l = getList(nearest);
832
833 // skip sharp edge lists
834 if(l->getType() == SHARPEDGELIST)
835 return;
836
837 // substitute surfacemeshlist with the parent surfacelist:
838 if(l->getType() == SURFACEMESHLIST)
839 l = getList(l->getParent());
840
841 // if not ctrl pressed, rebuild all selected lists except this one:
842 if(!ctrlPressed) {
843 for(i = 0; i < getLists(); i++) {
844 list_t *l2 = getList(i);
845 if(l2->isSelected() && (l2->getIndex() != l->getIndex())) {
846 glDeleteLists(l2->getObject(), 1);
847 l2->setSelected(false);
848 if(l2->getType() == SURFACELIST) {
849 for( int j = 0; j < mesh->getSurfaces(); j++ ) {
850 surface_t *surf = mesh->getSurface(j);
851 if ( surf->getIndex() == l2->getIndex() )
852 surf->setSelected(l2->isSelected());
853 }
854 l2->setObject(generateSurfaceList(l2->getIndex(), surfaceColor)); // cyan
855 } else if(l2->getType() == EDGELIST) {
856 for( int j=0; j < mesh->getEdges(); j++ ) {
857 edge_t *edge = mesh->getEdge(j);
858 if ( edge->getIndex() == l2->getIndex() )
859 edge->setSelected(l2->isSelected());
860 }
861 l2->setObject(generateEdgeList(l2->getIndex(), edgeColor)); // green
862 }
863 }
864 }
865 }
866
867 // Toggle selection:
868 l->setSelected(!l->isSelected());
869
870 glDeleteLists(l->getObject(), 1);
871
872 // Highlight current selection:
873 if(l->getType() == SURFACELIST) {
874 if(l->isSelected()) {
875 l->setObject(generateSurfaceList(l->getIndex(), Qt::red)); // red
876 } else {
877 l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
878 }
879
880 for( int i=0; i<mesh->getSurfaces(); i++ ) {
881 surface_t *surf = mesh->getSurface(i);
882 if ( surf->getIndex() == l->getIndex() ) surf->setSelected(l->isSelected());
883 }
884
885 } else if(l->getType() == EDGELIST) {
886 if(l->isSelected()) {
887 l->setObject(generateEdgeList(l->getIndex(), Qt::red)); // red
888 } else {
889 l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
890 }
891 for( int i=0; i < mesh->getEdges(); i++ ) {
892 edge_t *edge = mesh->getEdge(i);
893 if ( edge->getIndex() == l->getIndex() ) edge->setSelected(l->isSelected());
894 }
895 }
896
897 // body selection:
898 //----------------
899 currentlySelectedBody = -1;
900 if(shiftPressed || bodyEditActive) {
901
902 // determine the max bulk index
903 int MAX_BULK_INDEX = -1;
904
905 for(int i = 0; i < mesh->getElements(); i++) {
906 element_t *elem = mesh->getElement(i);
907 if(elem->getNature() != PDE_BULK)
908 break;
909 if(elem->getIndex() > MAX_BULK_INDEX)
910 MAX_BULK_INDEX = elem->getIndex();
911 }
912
913 for(int i = 0; i < mesh->getSurfaces(); i++) {
914 surface_t *surf = mesh->getSurface(i);
915 if(surf->getNature() != PDE_BULK)
916 break;
917 if(surf->getIndex() > MAX_BULK_INDEX)
918 MAX_BULK_INDEX = surf->getIndex();
919 }
920
921 for(int i = 0; i < mesh->getEdges(); i++) {
922 edge_t *edge = mesh->getEdge(i);
923 if(edge->getNature() != PDE_BULK)
924 break;
925 if(edge->getIndex() > MAX_BULK_INDEX)
926 MAX_BULK_INDEX = edge->getIndex();
927 }
928
929 MAX_BULK_INDEX++;
930 if(MAX_BULK_INDEX == 0) {
931 cout << "Error in body selection: "
932 "There are no legal body indiced from which to choose" << endl;
933 cout.flush();
934 goto body_selection_finished;
935 }
936
937 // allocate temp arrays:
938 bool *tmp1 = new bool[MAX_BULK_INDEX];
939 bool *tmp2 = new bool[MAX_BULK_INDEX];
940
941 for(int i = 0; i < MAX_BULK_INDEX; i++) {
942 tmp1[i] = true;
943 tmp2[i] = false;
944 }
945
946 // check if the selected lists uniquely determine a bulk body:
947 for(int i = 0; i < getLists(); i++) {
948 list_t *l2 = getList(i);
949
950 if(l2->isSelected() && (l2->getNature() == PDE_BULK)) {
951 for(int j = 0; j < MAX_BULK_INDEX; j++) {
952 if(j != l2->getIndex())
953 tmp1[j] = false;
954 }
955 }
956
957 if(l2->isSelected() && (l2->getNature() == PDE_BOUNDARY) &&
958 (l2->getType() == SURFACELIST)) {
959 for(int j = 0; j < mesh->getSurfaces(); j++) {
960 surface_t *surf = mesh->getSurface(j);
961 if(surf->getIndex() == l2->getIndex()) {
962 for(int k = 0; k < surf->getElements(); k++) {
963 int l = surf->getElementIndex(k);
964 if(l < 0)
965 break;
966 element_t *elem = mesh->getElement(l);
967 if((elem->getIndex() < 0) || (elem->getIndex() >= MAX_BULK_INDEX))
968 break;
969 tmp2[elem->getIndex()] = true;
970 }
971 for(int k = 0; k < MAX_BULK_INDEX; k++) {
972 tmp1[k] &= tmp2[k];
973 tmp2[k] = false;
974 }
975 }
976 }
977 }
978 }
979
980 // array "tmp1" should contain only one entry with value "true"
981 int count = 0;
982 int found = -1;
983 for(int i = 0; i < MAX_BULK_INDEX; i++) {
984 if( tmp1[i] ) {
985 count++;
986 found = i;
987 }
988 }
989
990 if((count == 1) && (found >= 0))
991 currentlySelectedBody = found;
992
993 delete [] tmp1;
994 delete [] tmp2;
995 }
996 body_selection_finished:
997
998 // Emit result to mainwindow:
999 emit(signalBoundarySelected(l));
1000
1001 } else {
1002
1003 // Emit "nothing selected":
1004 dummylist.setNature(-1);
1005 dummylist.setType(-1);
1006 dummylist.setIndex(-1);
1007 emit(signalBoundarySelected(&dummylist));
1008
1009 }
1010
1011 updateGL();
1012 }
1013
1014
1015
1016 // Get current matrix and its inverse...
1017 //-----------------------------------------------------------------------------
getMatrix()1018 void GLWidget::getMatrix()
1019 {
1020 glGetQrealv(GL_MODELVIEW_MATRIX, matrix);
1021 helpers->invertMatrix(matrix, invmatrix);
1022 }
1023
1024
1025
1026 // Rebuild lists...
1027 //-----------------------------------------------------------------------------
rebuildLists()1028 void GLWidget::rebuildLists()
1029 {
1030 double *bb = mesh->boundingBox();
1031
1032 drawTranslate[0] = bb[6]; // x-center
1033 drawTranslate[1] = bb[7]; // y-center
1034 drawTranslate[2] = bb[8]; // z-center
1035 drawScale = bb[9]; // scaling
1036
1037 delete [] bb;
1038
1039 if(getLists() > 0) {
1040 for(int i=0; i < getLists(); i++) {
1041 list_t *l = getList(i);
1042 glDeleteLists(l->getObject(), 1);
1043 }
1044 }
1045
1046 makeLists();
1047
1048 updateGL();
1049 }
1050
1051 // Compose GL surface lists...
1052 //-----------------------------------------------------------------------------
rebuildSurfaceLists()1053 void GLWidget::rebuildSurfaceLists()
1054 {
1055 for( int i = 0; i < getLists(); i++ )
1056 {
1057 list_t *l = getList(i);
1058 if( l->getType() == SURFACELIST )
1059 {
1060 glDeleteLists( l->getObject(), 1 );
1061 if(l->isSelected()) {
1062 l->setObject(generateSurfaceList(l->getIndex(), Qt::red)); // red
1063 } else {
1064 l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
1065 }
1066 }
1067 }
1068 }
1069
1070 // Compose GL edge lists...
1071 //-----------------------------------------------------------------------------
rebuildEdgeLists()1072 void GLWidget::rebuildEdgeLists()
1073 {
1074 for( int i = 0; i < getLists(); i++ )
1075 {
1076 list_t *l = getList(i);
1077 if ( l->getType() == EDGELIST )
1078 {
1079 glDeleteLists( l->getObject(), 1 );
1080 if(l->isSelected()) {
1081 l->setObject(generateEdgeList(l->getIndex(), Qt::red)); // red
1082 } else {
1083 l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
1084 }
1085 }
1086 }
1087 }
1088
1089
1090
1091 // Compose GL object lists...
1092 //-----------------------------------------------------------------------------
makeLists()1093 GLuint GLWidget::makeLists()
1094 {
1095 int i;
1096 list_t *l;
1097
1098 if((mesh == NULL) || mesh->isUndefined())
1099 return 0;
1100
1101 // The rule for composing lists to display is the following:
1102 //---------------------------------------------------------------------------
1103 // - All surface elements with index >= 0 will be drawn - one list/index
1104 // (list->type = SURFACELIST)
1105 // - For each surface element list, one auxiliary list will be drawn
1106 // (list->type = SURFACEMESHLIST)
1107 // - All edge elements with index >= 0 will be drawn - one list/index
1108 // (list->type = EDGELIST)
1109 // - All point elements with index >= 0 will be drawn - one list/index
1110 // (list->type = POINTLIST)
1111 // - A list of sharp edges will always be drawn (even if it is empty)
1112 //---------------------------------------------------------------------------
1113
1114 // Simultaneously, populate hash for mapping body & boundary incides:
1115 //--------------------------------------------------------------------
1116 boundaryMap.clear();
1117 bodyMap.clear();
1118 int boundaryCount = 0;
1119 int bodyCount = 0;
1120
1121 // Scan volume elements to determine the number of material indices:
1122 //-------------------------------------------------------------------
1123 QMap<int, int> bodyNatures;
1124
1125 for(i = 0; i < mesh->getElements(); i++) {
1126 element_t *element = mesh->getElement(i);
1127 int index = element->getIndex();
1128
1129 if(index >= 0) {
1130 int nature = element->getNature();
1131
1132 if(!bodyNatures.contains(index))
1133 bodyNatures.insert(index, nature);
1134 }
1135 }
1136
1137 QMapIterator<int, int> itrBody(bodyNatures);
1138 while (itrBody.hasNext()) {
1139 itrBody.next();
1140 int index = itrBody.key();
1141 int nature = itrBody.value();
1142
1143 if(nature == PDE_BULK)
1144 bodyMap.insert(index, bodyCount++);
1145 }
1146
1147 // Scan surface elements to determine the number of bcs. / mat. indices:
1148 //-----------------------------------------------------------------------
1149 int surface_bcs = 0;
1150
1151 QMap<int, int> surfaceNatures;
1152
1153 for(i = 0; i < mesh->getSurfaces(); i++) {
1154 surface_t *surface = mesh->getSurface(i);
1155 int index = surface->getIndex();
1156
1157 if(index > 0) {
1158 int nature = surface->getNature();
1159
1160 if(!surfaceNatures.contains(index))
1161 surfaceNatures.insert(index, nature);
1162 }
1163 }
1164
1165 QMapIterator<int, int> itrSurface(surfaceNatures);
1166 while (itrSurface.hasNext()) {
1167 itrSurface.next();
1168 int index = itrSurface.key();
1169 int nature = itrSurface.value();
1170
1171 if(nature > 0) {
1172 surface_bcs++;
1173
1174 if(nature == PDE_BULK)
1175 bodyMap.insert(index, bodyCount++);
1176
1177 if(nature == PDE_BOUNDARY)
1178 boundaryMap.insert(index, boundaryCount++);
1179 }
1180 }
1181
1182 cout << "Bcs/materials on surface elements: " << surface_bcs << endl;
1183 cout.flush();
1184
1185 // Scan edge elements to determine the number of bcs. / mat. indices:
1186 //--------------------------------------------------------------------
1187 int edge_bcs = 0;
1188
1189 QMap<int, int> edgeNatures;
1190
1191 for(i = 0; i < mesh->getEdges(); i++) {
1192 edge_t *edge = mesh->getEdge(i);
1193 int index = edge->getIndex();
1194
1195 if(index > 0) {
1196 int nature = edge->getNature();
1197
1198 if(!edgeNatures.contains(index))
1199 edgeNatures.insert(index, nature);
1200 }
1201 }
1202
1203 QMapIterator<int, int> itrEdge(edgeNatures);
1204 while (itrEdge.hasNext()) {
1205 itrEdge.next();
1206 int index = itrEdge.key();
1207 int nature = itrEdge.value();
1208
1209 if(nature > 0) {
1210 edge_bcs++;
1211
1212 if(nature == PDE_BULK)
1213 bodyMap.insert(index, bodyCount++);
1214
1215 if(nature == PDE_BOUNDARY)
1216 boundaryMap.insert(index, boundaryCount++);
1217 }
1218 }
1219
1220 cout << "Bcs/materials on edge elements: " << edge_bcs << endl;
1221 cout.flush();
1222
1223 // Scan point elements to determine the number of bcs. / mat. indices:
1224 //---------------------------------------------------------------------
1225 int point_bcs = 0;
1226
1227 // TODO
1228
1229 cout << "Bcs/materials on point elements: " << point_bcs << endl;
1230 cout.flush();
1231
1232 // Generate lists:
1233 //---------------------------------------------------------------------
1234 for(i = 0; i < getLists(); i++)
1235 delete list.at(i);
1236
1237 list.clear();
1238
1239 cout << "Generating lists to display" << endl;
1240 cout.flush();
1241
1242 // Surface lists:
1243 //----------------
1244 for(i = 0; i < mesh->getSurfaces(); i++)
1245 mesh->getSurface(i)->setSelected(false);
1246
1247 itrSurface.toFront();
1248 while (itrSurface.hasNext()) {
1249 itrSurface.next();
1250 int index = itrSurface.key();
1251 int nature = itrSurface.value();
1252
1253 if(nature > 0) {
1254 l = new list_t;
1255 list.push_back(l);
1256
1257 l->setNature(nature);
1258 l->setType(SURFACELIST);
1259 l->setIndex(index);
1260 l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
1261 l->setChild(getLists());
1262 l->setParent(-1);
1263 l->setSelected(false);
1264 l->setVisible(stateDrawSurfaceElements);
1265
1266 // edges of surface elements (just for visual):
1267 l = new list_t;
1268 list.push_back(l);
1269
1270 l->setNature(PDE_UNKNOWN);
1271 l->setType(SURFACEMESHLIST);
1272 l->setIndex(index);
1273 l->setObject(generateSurfaceMeshList(l->getIndex(), surfaceMeshColor)); // black
1274 l->setChild(-1);
1275 l->setParent(getLists() - 2);
1276 l->setSelected(false);
1277 l->setVisible(stateDrawSurfaceMesh);
1278 }
1279 }
1280
1281 // Edge lists (only PDE_BOUNDARY):
1282 //---------------------------------
1283 for(i = 0; i < mesh->getEdges(); i++)
1284 mesh->getEdge(i)->setSelected(false);
1285
1286 itrEdge.toFront();
1287 while (itrEdge.hasNext()) {
1288 itrEdge.next();
1289 int index = itrEdge.key();
1290 int nature = itrEdge.value();
1291
1292 if(nature > 0) {
1293 l = new list_t;
1294 list.push_back(l);
1295
1296 l->setNature(nature);
1297 l->setType(EDGELIST);
1298 l->setIndex(index);
1299 l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
1300 l->setChild(-1);
1301 l->setParent(-1);
1302 l->setSelected(false);
1303 l->setVisible(stateDrawEdgeElements);
1304 }
1305 }
1306
1307 // Point lists: TODO
1308
1309 // Sharp edges (just for visual):
1310 //--------------------------------
1311 l = new list_t;
1312 list.push_back(l);
1313
1314 l->setNature(PDE_UNKNOWN);
1315 l->setType(SHARPEDGELIST);
1316 l->setIndex(-1);
1317 l->setObject(generateSharpEdgeList(sharpEdgeColor)); // black
1318 l->setChild(-1);
1319 l->setParent(-1);
1320 l->setSelected(false);
1321 l->setVisible(stateDrawSharpEdges);
1322
1323 // Volume mesh (visual only):
1324 //----------------------------
1325 l = new list_t;
1326 list.push_back(l);
1327
1328 l->setNature(PDE_UNKNOWN);
1329 l->setType(VOLUMEMESHLIST);
1330 l->setIndex(-1);
1331 l->setObject(generateVolumeMeshList(Qt::black)); // black
1332 l->setChild(-1);
1333 l->setParent(-1);
1334 l->setSelected(false);
1335 l->setVisible(stateDrawVolumeMesh);
1336
1337 // Clean up:
1338 //-----------
1339 edgeNatures.clear();
1340 surfaceNatures.clear();
1341 bodyNatures.clear();
1342
1343 updateGL();
1344 getMatrix();
1345
1346 cout << "Generated " << getLists() << " lists" << endl;
1347 cout.flush();
1348
1349 return getLists();
1350 }
1351
1352
1353 // Generate volume mesh list...
1354 //-----------------------------------------------------------------------------
generateVolumeMeshList(QColor qColor)1355 GLuint GLWidget::generateVolumeMeshList(QColor qColor)
1356 {
1357 static int tetmap[6][2] = {{0, 1}, {0, 2}, {0, 3},
1358 {1, 2}, {1, 3}, {2, 3}};
1359
1360 static int wedgemap[9][2] = {{0, 1}, {1, 2}, {2, 0},
1361 {0, 3}, {1, 4}, {2, 5},
1362 {3, 4}, {4, 5}, {5, 3}};
1363
1364
1365 static int hexmap[12][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0},
1366 {0, 4}, {1, 5}, {2, 6}, {3, 7},
1367 {4, 5}, {5, 6}, {6, 7}, {7, 4}};
1368
1369 double R = qColor.red() / 255.0;
1370 double G = qColor.green() / 255.0;
1371 double B = qColor.blue() / 255.0;
1372
1373 GLuint current = glGenLists(1);
1374 glNewList(current, GL_COMPILE);
1375
1376 glBegin(GL_LINES);
1377
1378 for(int i = 0; i < mesh->getElements(); i++) {
1379 element_t *element = mesh->getElement(i);
1380
1381 glColor3d(R, G, B);
1382
1383 int nofEdges = 0;
1384 int *edgeMap = 0;
1385
1386 switch((int)(element->getCode() / 100)) {
1387 case 5:
1388 nofEdges = 6;
1389 edgeMap = &tetmap[0][0];
1390 break;
1391 case 7:
1392 nofEdges = 9;
1393 edgeMap = &wedgemap[0][0];
1394 break;
1395 case 8:
1396 nofEdges = 12;
1397 edgeMap = &hexmap[0][0];
1398 break;
1399 }
1400
1401 // draw edges:
1402 for(int j = 0; j < nofEdges; j++) {
1403 int p0 = *edgeMap++;
1404 int p1 = *edgeMap++;
1405
1406 int q0 = element->getNodeIndex(p0);
1407 int q1 = element->getNodeIndex(p1);
1408
1409 node_t *n0 = mesh->getNode(q0);
1410 node_t *n1 = mesh->getNode(q1);
1411
1412 double x0 = ( n0->getX(0) - drawTranslate[0] ) / drawScale;
1413 double y0 = ( n0->getX(1) - drawTranslate[1] ) / drawScale;
1414 double z0 = ( n0->getX(2) - drawTranslate[2] ) / drawScale;
1415
1416 double x1 = ( n1->getX(0) - drawTranslate[0] ) / drawScale;
1417 double y1 = ( n1->getX(1) - drawTranslate[1] ) / drawScale;
1418 double z1 = ( n1->getX(2) - drawTranslate[2] ) / drawScale;
1419
1420 glVertex3d(x0, y0, z0);
1421 glVertex3d(x1, y1, z1);
1422 }
1423 }
1424
1425 glEnd();
1426
1427 glEndList();
1428
1429 return current;
1430 }
1431
1432
1433
1434 // Generate surface list...
1435 //-----------------------------------------------------------------------------
generateSurfaceList(int index,QColor qColor)1436 GLuint GLWidget::generateSurfaceList(int index, QColor qColor)
1437 {
1438 double x0[3], x1[3], x2[3], x3[3], u[3];
1439
1440 double R = qColor.red() / 255.0;
1441 double G = qColor.green() / 255.0;
1442 double B = qColor.blue() / 255.0;
1443
1444 GLuint current = glGenLists(1);
1445 glNewList(current, GL_COMPILE);
1446
1447 // Draw triangles:
1448 //-----------------
1449 glBegin(GL_TRIANGLES);
1450
1451 for(int i=0; i < mesh->getSurfaces(); i++) {
1452 surface_t *surface = mesh->getSurface(i);
1453
1454 if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 3)) {
1455
1456 glColor3d(R, G, B);
1457
1458 if(stateBcColors && (surface->getNature() == PDE_BOUNDARY)) {
1459 double c[3];
1460 indexColors(c, index);
1461 glColor3d(c[0], c[1], c[2]);
1462 }
1463
1464 if(stateBodyColors) {
1465 int bodyIndex = surface->getIndex();
1466 if(surface->getNature() == PDE_BOUNDARY) {
1467 int parentIndex = surface->getElementIndex(0);
1468 element_t *parent = mesh->getElement(parentIndex);
1469 bodyIndex = parent->getIndex();
1470 }
1471 double c[3];
1472 indexColors(c, bodyIndex);
1473 glColor3d(c[0], c[1], c[2]);
1474 }
1475
1476 // change normal direction:
1477 changeNormalDirection(u, surface->getNormalVec());
1478 glNormal3dv(u);
1479
1480 int n0 = surface->getNodeIndex(0);
1481 int n1 = surface->getNodeIndex(1);
1482 int n2 = surface->getNodeIndex(2);
1483
1484 x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1485 x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1486 x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1487
1488 x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1489 x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1490 x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1491
1492 x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1493 x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1494 x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1495
1496 changeNormalDirection(u, surface->getVertexNormalVec(0));
1497 if ( !stateFlatShade ) glNormal3dv(u);
1498 glVertex3dv(x0);
1499
1500 changeNormalDirection(u, surface->getVertexNormalVec(1));
1501 if ( !stateFlatShade ) glNormal3dv(u);
1502 glVertex3dv(x1);
1503
1504 changeNormalDirection(u, surface->getVertexNormalVec(2));
1505 if ( !stateFlatShade ) glNormal3dv(u);
1506 glVertex3dv(x2);
1507 }
1508 }
1509
1510 glEnd();
1511
1512 // Draw quads:
1513 //------------
1514 glBegin(GL_QUADS);
1515
1516 for(int i=0; i < mesh->getSurfaces(); i++) {
1517 surface_t *surface = mesh->getSurface(i);
1518
1519 if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 4)) {
1520
1521 glColor3d(R, G, B);
1522
1523 if(stateBcColors && (surface->getNature() == PDE_BOUNDARY)) {
1524 double c[3];
1525 indexColors(c, index);
1526 glColor3d(c[0], c[1], c[2]);
1527 }
1528
1529 if(stateBodyColors) {
1530 int bodyIndex = surface->getIndex();
1531 if(surface->getNature() == PDE_BOUNDARY) {
1532 int parentIndex = surface->getElementIndex(0);
1533 element_t *parent = mesh->getElement(parentIndex);
1534 bodyIndex = parent->getIndex();
1535 }
1536 double c[3];
1537 indexColors(c, bodyIndex);
1538 glColor3d(c[0], c[1], c[2]);
1539 }
1540
1541 // change normal direction:
1542 changeNormalDirection(u, surface->getNormalVec());
1543 glNormal3dv(u);
1544
1545 int n0 = surface->getNodeIndex(0);
1546 int n1 = surface->getNodeIndex(1);
1547 int n2 = surface->getNodeIndex(2);
1548 int n3 = surface->getNodeIndex(3);
1549
1550 x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1551 x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1552 x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1553
1554 x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1555 x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1556 x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1557
1558 x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1559 x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1560 x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1561
1562 x3[0] = (mesh->getNode(n3)->getX(0) - drawTranslate[0]) / drawScale;
1563 x3[1] = (mesh->getNode(n3)->getX(1) - drawTranslate[1]) / drawScale;
1564 x3[2] = (mesh->getNode(n3)->getX(2) - drawTranslate[2]) / drawScale;
1565
1566 changeNormalDirection(u, surface->getVertexNormalVec(0));
1567 if ( !stateFlatShade ) glNormal3dv(u);
1568 glVertex3dv(x0);
1569
1570 changeNormalDirection(u, surface->getVertexNormalVec(1));
1571 if ( !stateFlatShade ) glNormal3dv(u);
1572 glVertex3dv(x1);
1573
1574 changeNormalDirection(u, surface->getVertexNormalVec(2));
1575 if ( !stateFlatShade ) glNormal3dv(u);
1576 glVertex3dv(x2);
1577
1578 changeNormalDirection(u, surface->getVertexNormalVec(3));
1579 if ( !stateFlatShade ) glNormal3dv(u);
1580 glVertex3dv(x3);
1581 }
1582 }
1583
1584 glEnd();
1585 glEndList();
1586
1587 return current;
1588 }
1589
1590
1591
1592 // Generate surface edge list...
1593 //-----------------------------------------------------------------------------
generateSurfaceMeshList(int index,QColor qColor)1594 GLuint GLWidget::generateSurfaceMeshList(int index, QColor qColor)
1595 {
1596 double x0[3], x1[3], x2[3], x3[3];
1597
1598 double R = qColor.red() / 255.0;
1599 double G = qColor.green() / 255.0;
1600 double B = qColor.blue() / 255.0;
1601
1602 GLuint current = glGenLists(1);
1603 glNewList(current, GL_COMPILE);
1604
1605 // Draw lines:
1606 //------------
1607 glLineWidth(1.0);
1608 glDisable(GL_LIGHTING);
1609 glColor3d(R, G, B);
1610 glBegin(GL_LINES);
1611
1612 for(int i=0; i < mesh->getSurfaces(); i++) {
1613 surface_t *surface = mesh->getSurface(i);
1614
1615 if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 3)) {
1616 int n0 = surface->getNodeIndex(0);
1617 int n1 = surface->getNodeIndex(1);
1618 int n2 = surface->getNodeIndex(2);
1619
1620 x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1621 x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1622 x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1623
1624 x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1625 x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1626 x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1627
1628 x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1629 x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1630 x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1631
1632 glVertex3dv(x0);
1633 glVertex3dv(x1);
1634
1635 glVertex3dv(x1);
1636 glVertex3dv(x2);
1637
1638 glVertex3dv(x2);
1639 glVertex3dv(x0);
1640 }
1641 }
1642
1643 for(int i=0; i < mesh->getSurfaces(); i++) {
1644 surface_t *surface = mesh->getSurface(i);
1645
1646 if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 4)) {
1647 int n0 = surface->getNodeIndex(0);
1648 int n1 = surface->getNodeIndex(1);
1649 int n2 = surface->getNodeIndex(2);
1650 int n3 = surface->getNodeIndex(3);
1651
1652 x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1653 x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1654 x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1655
1656 x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1657 x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1658 x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1659
1660 x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1661 x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1662 x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1663
1664 x3[0] = (mesh->getNode(n3)->getX(0) - drawTranslate[0]) / drawScale;
1665 x3[1] = (mesh->getNode(n3)->getX(1) - drawTranslate[1]) / drawScale;
1666 x3[2] = (mesh->getNode(n3)->getX(2) - drawTranslate[2]) / drawScale;
1667
1668 glVertex3dv(x0);
1669 glVertex3dv(x1);
1670
1671 glVertex3dv(x1);
1672 glVertex3dv(x2);
1673
1674 glVertex3dv(x2);
1675 glVertex3dv(x3);
1676
1677 glVertex3dv(x3);
1678 glVertex3dv(x0);
1679 }
1680 }
1681 glEnd();
1682
1683 glEnable(GL_LIGHTING);
1684 glEndList();
1685
1686 return current;
1687 }
1688
1689
1690 // Generate edge list...
1691 //-----------------------------------------------------------------------------
generateEdgeList(int index,QColor qColor)1692 GLuint GLWidget::generateEdgeList(int index, QColor qColor)
1693 {
1694 double x0[3], x1[3];
1695
1696 double R = qColor.red() / 255.0;
1697 double G = qColor.green() / 255.0;
1698 double B = qColor.blue() / 255.0;
1699
1700 GLuint current = glGenLists(1);
1701 glNewList(current, GL_COMPILE);
1702 glColor3d(R, G, B);
1703 glLineWidth(4.0);
1704 glDisable(GL_LIGHTING);
1705 glBegin(GL_LINES);
1706
1707 for(int i=0; i < mesh->getEdges(); i++) {
1708 edge_t *edge = mesh->getEdge(i);
1709
1710 if(edge->getIndex() == index) {
1711 int n0 = edge->getNodeIndex(0);
1712 int n1 = edge->getNodeIndex(1);
1713
1714 x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1715 x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1716 x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1717
1718 x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1719 x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1720 x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1721
1722 glVertex3dv(x0);
1723 glVertex3dv(x1);
1724 }
1725 }
1726
1727 glEnd();
1728
1729 glEnable(GL_LIGHTING);
1730 glEndList();
1731
1732 return current;
1733 }
1734
1735
1736
1737 // Generate sharp edge list...
1738 //-----------------------------------------------------------------------------
generateSharpEdgeList(QColor qColor)1739 GLuint GLWidget::generateSharpEdgeList(QColor qColor)
1740 {
1741 double x0[3], x1[3];
1742
1743 double R = qColor.red() / 255.0;
1744 double G = qColor.green() / 255.0;
1745 double B = qColor.blue() / 255.0;
1746
1747 GLuint current = glGenLists(1);
1748 glNewList(current, GL_COMPILE);
1749
1750 glColor3d(R, G, B);
1751 glLineWidth(1.0);
1752 glDisable(GL_LIGHTING);
1753 glBegin(GL_LINES);
1754
1755 for(int i=0; i < mesh->getEdges(); i++) {
1756 edge_t *edge = mesh->getEdge(i);
1757
1758 if(edge->isSharp()) {
1759 int n0 = edge->getNodeIndex(0);
1760 int n1 = edge->getNodeIndex(1);
1761
1762 x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1763 x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1764 x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1765
1766 x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1767 x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1768 x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1769
1770 glVertex3dv(x0);
1771 glVertex3dv(x1);
1772 }
1773 }
1774
1775 glEnd();
1776 glEnable(GL_LIGHTING);
1777 glEndList();
1778
1779 return current;
1780 }
1781
1782
1783 // Draw coordinates:
1784 //-----------------------------------------------------------------------------
drawCoordinates()1785 void GLWidget::drawCoordinates()
1786 {
1787 glMatrixMode(GL_PROJECTION);
1788 glPushMatrix();
1789
1790 // glTranslated(-0.8, -0.8, 5.0);
1791 glTranslated(-0.8, -0.8, ZSHIFT);
1792
1793 glMatrixMode(GL_MODELVIEW);
1794
1795 // z-axis
1796 glColor3d(0, 0, 1);
1797 gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1798 renderText(0.0, 0.0, 0.25, "Z");
1799
1800 // x-axis
1801 glColor3d(1, 0, 0);
1802 glRotated(90, 0, 1, 0);
1803 gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1804 renderText(0.0, 0.0, 0.25, "X");
1805 glRotated(-90, 0, 1, 0);
1806
1807 // y-axis
1808 glColor3d(0, 1, 0);
1809 glRotated(-90, 1, 0, 0);
1810 gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1811 renderText(0.0, 0.0, 0.25, "Y");
1812 glRotated(90, 1, 0, 0);
1813
1814 glMatrixMode(GL_PROJECTION);
1815 glPopMatrix();
1816
1817 glMatrixMode(GL_MODELVIEW);
1818
1819 return;
1820 }
1821
toggleCoordinates()1822 bool GLWidget::toggleCoordinates()
1823 {
1824 stateDrawCoordinates = !stateDrawCoordinates;
1825 updateGL();
1826 return stateDrawCoordinates;
1827 }
1828
1829 // Draw background image...
1830 //-----------------------------------------------------------------------------
drawBgImage()1831 void GLWidget::drawBgImage()
1832 {
1833 GLint viewport[4];
1834
1835 if(!bgTexture) {
1836 #if WITH_QT5
1837 cout << "Bind texture " << string(bgImageFileName.toLatin1()) << "... ";
1838 #else
1839 cout << "Bind texture " << string(bgImageFileName.toAscii()) << "... ";
1840 #endif
1841 QPixmap pixmap(bgImageFileName);
1842 bgSizeX = pixmap.width();
1843 bgSizeY = pixmap.height();
1844 bgTexture = bindTexture(pixmap, GL_TEXTURE_2D);
1845 cout << "done" << endl;
1846 }
1847
1848 if(!bgTexture) {
1849 cout << "Failed to bind texture" << endl;
1850 stateUseBgImage = false;
1851 return;
1852 }
1853
1854 glGetIntegerv(GL_VIEWPORT, viewport);
1855
1856 double relativeSizeX = (double)viewport[2] / (double)viewport[3];
1857 double relativeSizeY = 1.0;
1858
1859 double bgRelativeSizeX = (double)bgSizeX / (double)viewport[3];
1860 double bgRelativeSizeY = (double)bgSizeY / (double)viewport[3];
1861
1862 double width = 1.0;
1863 double height = 1.0;
1864 double depth = 9.9;
1865 double xshift = 0.0;
1866 double yshift = 0.0;
1867
1868 if(stateAlignRightBgImage) {
1869 width = bgRelativeSizeX;
1870 height = bgRelativeSizeY;
1871 xshift = relativeSizeX - bgRelativeSizeX;
1872 yshift = bgRelativeSizeY - relativeSizeY;
1873 }
1874
1875 if(stateStretchBgImage) {
1876 width = (double)viewport[2] / (double)viewport[3];
1877 height = 1.0;
1878 xshift = 0.0;
1879 yshift = 0.0;
1880 }
1881
1882 glDisable(GL_DEPTH_TEST);
1883 glPushMatrix();
1884 glLoadIdentity();
1885 glColor3d(1, 1, 1);
1886 glDisable(GL_LIGHTING);
1887 glEnable(GL_TEXTURE_2D);
1888 glBindTexture(GL_TEXTURE_2D, bgTexture);
1889
1890 glBegin(GL_QUADS);
1891 glTexCoord2d(0, 0);
1892 glVertex3d(-width+xshift, -height+yshift, -depth);
1893 glTexCoord2d(1, 0);
1894 glVertex3d(+width+xshift, -height+yshift, -depth);
1895 glTexCoord2d(1, 1);
1896 glVertex3d(+width+xshift, +height+yshift, -depth);
1897 glTexCoord2d(0, 1);
1898 glVertex3d(-width+xshift, +height+yshift, -depth);
1899 glEnd();
1900
1901 glDisable(GL_TEXTURE_2D);
1902 glEnable(GL_LIGHTING);
1903 glPopMatrix();
1904 glEnable(GL_DEPTH_TEST);
1905 }
1906
1907
1908 // Auxiliary function for changing the direction of a vector...
1909 //---------------------------------------------------------------------------
changeNormalDirection(double * u,double * v)1910 void GLWidget::changeNormalDirection(double *u, double *v)
1911 {
1912 u[0] = -v[0];
1913 u[1] = -v[1];
1914 u[2] = -v[2];
1915 }
1916
getList(int i) const1917 list_t* GLWidget::getList(int i) const
1918 {
1919 return list.at(i);
1920 }
1921
getLists() const1922 int GLWidget::getLists() const
1923 {
1924 return list.count();
1925 }
1926
1927 // Set 'c' to an RGB color corresponding to index 'i'.
1928 // 'c' should be pre-allocated to a length of at least 3.
indexColors(double * c,int i)1929 void GLWidget::indexColors(double *c, int i)
1930 {
1931 c[0] = 0.5 + 0.5 * sin(1.0 * i);
1932 c[1] = 0.5 + 0.5 * cos(2.0 * i);
1933 c[2] = 0.5 + 0.5 * cos(3.0 * i);
1934 }
1935
indexColors(int * c,int i)1936 void GLWidget::indexColors(int *c, int i)
1937 {
1938 double tmp[3];
1939
1940 indexColors(tmp, i);
1941 for (int j = 0; j < 3; j++) c[j] = int(tmp[j]*255 + 0.5);
1942 }
1943