Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/Application/src/glwidget.cpp
3203 views
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: [email protected] *
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
57
static inline void glGetQrealv(GLenum e, GLfloat* data) { glGetFloatv(e,data); }
58
static inline void glGetQrealv(GLenum e, GLdouble* data) { glGetDoublev(e,data); }
59
static inline void glMultMatrixq( const GLdouble *m ) { glMultMatrixd(m); }
60
static inline void glMultMatrixq( const GLfloat *m ) { glMultMatrixf(m); }
61
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
74
list_t::~list_t()
75
{
76
}
77
78
void list_t::setNature(int n)
79
{
80
this->nature = n;
81
}
82
83
int list_t::getNature(void) const
84
{
85
return this->nature;
86
}
87
88
void list_t::setType(int n)
89
{
90
this->type = n;
91
}
92
93
int list_t::getType(void) const
94
{
95
return this->type;
96
}
97
98
void list_t::setIndex(int n)
99
{
100
this->index = n;
101
}
102
103
int list_t::getIndex(void) const
104
{
105
return this->index;
106
}
107
108
void list_t::setObject(GLuint n)
109
{
110
this->object = n;
111
}
112
113
GLuint list_t::getObject(void) const
114
{
115
return this->object;
116
}
117
118
void list_t::setChild(int n)
119
{
120
this->child = n;
121
}
122
123
int list_t::getChild(void) const
124
{
125
return this->child;
126
}
127
128
void list_t::setParent(int n)
129
{
130
this->parent = n;
131
}
132
133
int list_t::getParent(void) const
134
{
135
return this->parent;
136
}
137
138
void list_t::setSelected(bool b)
139
{
140
this->selected = b;
141
}
142
143
bool list_t::isSelected(void) const
144
{
145
return this->selected;
146
}
147
148
void list_t::setVisible(bool b)
149
{
150
this->visible = b;
151
}
152
153
bool list_t::isVisible(void) const
154
{
155
return this->visible;
156
}
157
158
// Construct glWidget...
159
//-----------------------------------------------------------------------------
160
#if WITH_QT6
161
GLWidget::GLWidget(QWidget *parent)
162
: QOpenGLWidget(parent)
163
#else
164
GLWidget::GLWidget(QWidget *parent)
165
: QGLWidget(parent)
166
#endif
167
{
168
backgroundColor = Qt::white;
169
surfaceColor = Qt::cyan;
170
edgeColor = Qt::green;
171
surfaceMeshColor = Qt::black;
172
sharpEdgeColor = Qt::black;
173
selectionColor = Qt::red;
174
175
stateOrtho = false;
176
stateFlatShade = true;
177
stateDrawSurfaceMesh = true;
178
stateDrawVolumeMesh = false;
179
stateDrawSharpEdges = true;
180
stateDrawSurfaceElements = true;
181
stateDrawEdgeElements = true;
182
stateDrawCoordinates = false;
183
stateDrawSurfaceNumbers = false;
184
stateDrawEdgeNumbers = false;
185
stateDrawNodeNumbers = false;
186
stateDrawBoundaryIndex = false;
187
stateDrawBodyIndex = false;
188
stateBcColors = false;
189
stateBodyColors = false;
190
191
currentlySelectedBody = -1;
192
193
drawScale = 1.0;
194
drawTranslate[0] = 0.0;
195
drawTranslate[1] = 0.0;
196
drawTranslate[2] = 0.0;
197
198
mesh = NULL;
199
200
helpers = new Helpers;
201
meshutils = new Meshutils;
202
203
// Coordinate axis:
204
quadric_axis = gluNewQuadric();
205
206
// Background image:
207
stateUseBgImage = false;
208
stateStretchBgImage = false;
209
stateAlignRightBgImage = false;
210
bgImageFileName = "";
211
bgTexture = 0;
212
bgSizeX = 0;
213
bgSizeY = 0;
214
}
215
216
217
// dtor...
218
//-----------------------------------------------------------------------------
219
GLWidget::~GLWidget()
220
{
221
}
222
223
224
// Min size hint...
225
//-----------------------------------------------------------------------------
226
QSize GLWidget::minimumSizeHint() const
227
{
228
return QSize(64, 64);
229
}
230
231
232
// Default size...
233
//-----------------------------------------------------------------------------
234
QSize GLWidget::sizeHint() const
235
{
236
return QSize(720, 576);
237
}
238
239
void GLWidget::setMesh(mesh_t *m)
240
{
241
this->mesh = m;
242
}
243
244
mesh_t* GLWidget::getMesh(void) const
245
{
246
return this->mesh;
247
}
248
249
void GLWidget::newMesh(void)
250
{
251
this->mesh = new mesh_t;
252
}
253
254
void GLWidget::deleteMesh(void)
255
{
256
delete this->mesh;
257
}
258
259
bool GLWidget::hasMesh(void) const
260
{
261
if(this->mesh)
262
return true;
263
264
return false;
265
}
266
267
// Init GL...
268
//-----------------------------------------------------------------------------
269
void GLWidget::initializeGL()
270
{
271
cout << "Initialize GL" << endl;
272
273
#if WITH_QT6
274
initializeOpenGLFunctions();
275
#endif
276
277
cout << "Vendor: " << glGetString(GL_VENDOR) << endl;
278
cout << "Renderer: " << glGetString(GL_RENDERER) << endl;
279
cout << "Version: " << glGetString(GL_VERSION) << endl;
280
cout.flush();
281
282
static GLfloat light_ambient[] = {0.2, 0.2, 0.2, 1.0};
283
static GLfloat light_diffuse[] = {0.6, 0.6, 0.6, 1.0};
284
static GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
285
static GLfloat light_position[] = {0.0, 0.0, 5.0, 0.0};
286
287
static GLfloat mat_ambient[] = {0.2, 0.2, 0.2, 1.0};
288
static GLfloat mat_diffuse[] = {1.0, 1.0, 1.0, 1.0};
289
static GLfloat mat_specular[] = {0.9, 0.9, 0.9, 1.0};
290
static GLfloat high_shininess[] = {20.0};
291
292
glMatrixMode(GL_MODELVIEW);
293
glLoadIdentity();
294
295
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
296
glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0);
297
glEnable(GL_LIGHTING);
298
299
glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,1.0);
300
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
301
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
302
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
303
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
304
glEnable(GL_LIGHT0);
305
306
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
307
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
308
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
309
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, high_shininess);
310
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
311
glEnable(GL_COLOR_MATERIAL);
312
313
glEnable(GL_DEPTH_TEST);
314
glDepthFunc(GL_LESS);
315
// glDepthRange(-10.0, 10.0);
316
317
glShadeModel(GL_SMOOTH);
318
// glEnable(GL_LINE_SMOOTH);
319
320
glEnable(GL_NORMALIZE);
321
322
#if WITH_QT6
323
glClearColor( backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), backgroundColor.alphaF());
324
#else
325
qglClearColor(backgroundColor);
326
#endif
327
328
glEnable(GL_TEXTURE_2D);
329
}
330
331
332
333
// Paint event...
334
//-----------------------------------------------------------------------------
335
void GLWidget::paintGL()
336
{
337
#if WITH_QT6
338
glClearColor( backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), backgroundColor.alphaF());
339
#endif
340
float xabs[3], xrel[3];
341
342
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
343
344
// Background image:
345
if(stateUseBgImage)
346
drawBgImage();
347
348
// FE objects:
349
if(getLists() > 0) {
350
351
for(int i = 0; i < getLists(); i++) {
352
list_t *l = getList(i);
353
354
if(l->isVisible()) {
355
glPushName(i);
356
357
if((l->getType() == SURFACEMESHLIST) && stateDrawSurfaceMesh) {
358
// translate slightly towards viewer
359
glMatrixMode(GL_PROJECTION);
360
glPushMatrix();
361
glTranslated(0, 0, 0.01);
362
glTranslated(0, 0, ZSHIFT);
363
glCallList(l->getObject());
364
glPopMatrix();
365
glMatrixMode(GL_MODELVIEW);
366
367
} else if((l->getType() == VOLUMEMESHLIST) && stateDrawVolumeMesh) {
368
// translate slightly towards viewer
369
glMatrixMode(GL_PROJECTION);
370
glPushMatrix();
371
glTranslated(0, 0, 0.01);
372
glTranslated(0, 0, ZSHIFT);
373
glCallList(l->getObject());
374
glPopMatrix();
375
glMatrixMode(GL_MODELVIEW);
376
377
} else if ((l->getType() == SHARPEDGELIST) && stateDrawSharpEdges) {
378
// translate slightly towards viewer
379
glMatrixMode(GL_PROJECTION);
380
glPushMatrix();
381
glTranslated(0, 0, 0.01);
382
glTranslated(0, 0, ZSHIFT);
383
glCallList(l->getObject());
384
glPopMatrix();
385
glMatrixMode(GL_MODELVIEW);
386
387
} else if((l->getType() == EDGELIST) && stateDrawEdgeElements ) {
388
// translate slightly towards viewer
389
glMatrixMode(GL_PROJECTION);
390
glPushMatrix();
391
glTranslated(0, 0, 0.02);
392
glTranslated(0, 0, ZSHIFT);
393
glCallList(l->getObject());
394
glPopMatrix();
395
glMatrixMode(GL_MODELVIEW);
396
397
} else if((l->getType() == SURFACELIST) && stateDrawSurfaceElements ) {
398
glMatrixMode(GL_PROJECTION);
399
glPushMatrix();
400
glTranslated(0, 0, ZSHIFT);
401
glCallList(l->getObject());
402
glPopMatrix();
403
glMatrixMode(GL_MODELVIEW);
404
405
} else {
406
glMatrixMode(GL_PROJECTION);
407
glPushMatrix();
408
glTranslated(0, 0, ZSHIFT);
409
glCallList(l->getObject());
410
glPopMatrix();
411
glMatrixMode(GL_MODELVIEW);
412
}
413
414
glPopName();
415
}
416
}
417
}
418
419
if(stateDrawCoordinates) {
420
// push a dummy name
421
glPushName(DUMMY_NAME);
422
drawCoordinates();
423
glPopName();
424
}
425
426
if(mesh) {
427
if(stateDrawSurfaceNumbers) {
428
glMatrixMode(GL_PROJECTION);
429
glPushMatrix();
430
glTranslated(0, 0, ZSHIFT);
431
glTranslated(0, 0, 0.1);
432
glColor3d(0.5, 0, 0);
433
434
for(int i=0; i < mesh->getSurfaces(); i++) {
435
surface_t *surface = mesh->getSurface(i);
436
int nodes = surface->getCode() / 100;
437
438
xabs[0] = xabs[1] = xabs[2] = 0.0;
439
440
for(int j = 0; j < nodes; j++) {
441
int ind = surface->getNodeIndex(j);
442
xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
443
xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
444
xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
445
}
446
447
xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
448
xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
449
xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
450
451
renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
452
}
453
454
glPopMatrix();
455
glMatrixMode(GL_MODELVIEW);
456
}
457
458
if(stateDrawEdgeNumbers) {
459
glMatrixMode(GL_PROJECTION);
460
glPushMatrix();
461
glTranslated(0, 0, ZSHIFT);
462
glTranslated(0, 0, 0.1);
463
glColor3d(0.0, 0.5, 0);
464
465
for(int i=0; i < mesh->getEdges(); i++) {
466
edge_t *edge = mesh->getEdge(i);
467
int nodes = edge->getCode() / 100;
468
469
xabs[0] = xabs[1] = xabs[2] = 0.0;
470
471
for(int j = 0; j < nodes; j++) {
472
int ind = edge->getNodeIndex(j);
473
xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
474
xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
475
xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
476
}
477
xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
478
xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
479
xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
480
481
renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
482
}
483
484
glPopMatrix();
485
glMatrixMode(GL_MODELVIEW);
486
}
487
488
if(stateDrawNodeNumbers) {
489
glMatrixMode(GL_PROJECTION);
490
glPushMatrix();
491
glTranslated(0, 0, ZSHIFT);
492
glTranslated(0, 0, 0.1);
493
glColor3d(0, 0, 0.5);
494
495
for(int i = 0; i < mesh->getNodes(); i++) {
496
xabs[0] = mesh->getNode(i)->getX(0);
497
xabs[1] = mesh->getNode(i)->getX(1);
498
xabs[2] = mesh->getNode(i)->getX(2);
499
500
xrel[0] = (xabs[0] - drawTranslate[0]) / drawScale;
501
xrel[1] = (xabs[1] - drawTranslate[1]) / drawScale;
502
xrel[2] = (xabs[2] - drawTranslate[2]) / drawScale;
503
504
renderText(xrel[0], xrel[1], xrel[2], QString::number(i+1) );
505
}
506
507
glPopMatrix();
508
glMatrixMode(GL_MODELVIEW);
509
}
510
511
if(stateDrawBoundaryIndex || stateDrawBodyIndex) {
512
glMatrixMode(GL_PROJECTION);
513
glPushMatrix();
514
glTranslated(0, 0, ZSHIFT);
515
glTranslated(0, 0, 0.1);
516
glColor3d(0.5, 0, 0);
517
518
for(int i = 0; i < mesh->getEdges(); i++) {
519
edge_t *edge = mesh->getEdge(i);
520
int nodes = edge->getCode() / 100;
521
522
xabs[0] = xabs[1] = xabs[2] = 0.0;
523
524
for(int j = 0; j < nodes;j++) {
525
int ind = edge->getNodeIndex(j);
526
xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
527
xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
528
xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
529
}
530
531
xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
532
xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
533
xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
534
535
if(stateDrawBoundaryIndex && (edge->getNature() == PDE_BOUNDARY))
536
renderText(xrel[0], xrel[1], xrel[2], QString::number(edge->getIndex()));
537
538
if(stateDrawBodyIndex && (edge->getNature() == PDE_BULK))
539
renderText(xrel[0], xrel[1], xrel[2], QString::number(edge->getIndex()));
540
}
541
542
for(int i = 0; i < mesh->getSurfaces(); i++) {
543
surface_t *surface = mesh->getSurface(i);
544
int nodes = surface->getCode() / 100;
545
546
xabs[0] = xabs[1] = xabs[2] = 0.0;
547
548
for(int j = 0; j < nodes; j++) {
549
int ind = surface->getNodeIndex(j);
550
xabs[0] = xabs[0] + mesh->getNode(ind)->getX(0);
551
xabs[1] = xabs[1] + mesh->getNode(ind)->getX(1);
552
xabs[2] = xabs[2] + mesh->getNode(ind)->getX(2);
553
}
554
555
xrel[0] = (xabs[0]/nodes - drawTranslate[0]) / drawScale;
556
xrel[1] = (xabs[1]/nodes - drawTranslate[1]) / drawScale;
557
xrel[2] = (xabs[2]/nodes - drawTranslate[2]) / drawScale;
558
559
if(stateDrawBoundaryIndex && (surface->getNature() == PDE_BOUNDARY))
560
renderText(xrel[0], xrel[1], xrel[2], QString::number(surface->getIndex()));
561
562
if(stateDrawBodyIndex && (surface->getNature() == PDE_BULK))
563
renderText(xrel[0], xrel[1], xrel[2], QString::number(surface->getIndex()));
564
565
// case 3d:
566
if(stateDrawBodyIndex && (surface->getNature() == PDE_BOUNDARY)) {
567
for(int i = 0; i < surface->getElements(); i++) {
568
int j = surface->getElementIndex(i);
569
if(j >= 0) {
570
element_t *element = mesh->getElement(j);
571
renderText(xrel[0], xrel[1], xrel[2], QString::number(element->getIndex()));
572
}
573
}
574
}
575
576
}
577
578
glPopMatrix();
579
glMatrixMode(GL_MODELVIEW);
580
}
581
}
582
}
583
584
585
// Change projection...
586
//-----------------------------------------------------------------------------
587
void GLWidget::changeProjection()
588
{
589
GLint viewport[4];
590
glGetIntegerv(GL_VIEWPORT, viewport);
591
592
int width = viewport[2];
593
int height = viewport[3];
594
double top = 1.0;
595
double bottom = -1.0;
596
double left = -(double)width / (double)height;
597
double right = (double)width / (double)height;
598
double _near = -10.0;
599
double _far = 10.0;
600
601
if(stateOrtho) {
602
glViewport(0, 0, (GLint)width, (GLint)height);
603
glMatrixMode(GL_PROJECTION);
604
glLoadIdentity();
605
glOrtho(left, right, bottom, top, _near, _far);
606
glMatrixMode(GL_MODELVIEW);
607
} else {
608
glViewport(0, 0, (GLint)width, (GLint)height);
609
glMatrixMode(GL_PROJECTION);
610
glLoadIdentity();
611
gluPerspective(54.0, (float)width/(float)height, 0.1, 10.0);
612
glMatrixMode(GL_MODELVIEW);
613
}
614
}
615
616
// Resize window...
617
//-----------------------------------------------------------------------------
618
void GLWidget::resizeGL(int width, int height)
619
{
620
double top = 1.0;
621
double bottom = -1.0;
622
double left = -(double)width / (double)height;
623
double right = (double)width / (double)height;
624
double _near = -10.0;
625
double _far = 10.0;
626
627
if(stateOrtho) {
628
glViewport(0, 0, (GLint)width, (GLint)height);
629
glMatrixMode(GL_PROJECTION);
630
glLoadIdentity();
631
glOrtho(left, right, bottom, top, _near, _far);
632
glMatrixMode(GL_MODELVIEW);
633
} else {
634
glViewport(0, 0, (GLint)width, (GLint)height);
635
glMatrixMode(GL_PROJECTION);
636
glLoadIdentity();
637
gluPerspective(45.0, (float)width/(float)height, 0.1, 10.0);
638
glMatrixMode(GL_MODELVIEW);
639
}
640
}
641
642
643
// Focus in event...
644
//-----------------------------------------------------------------------------
645
void GLWidget::focusInEvent(QFocusEvent *event)
646
{
647
Q_UNUSED(event)
648
649
// Should we check the key pressed status here?
650
}
651
652
653
// Key pressed...
654
//-----------------------------------------------------------------------------
655
void GLWidget::keyPressEvent(QKeyEvent *event)
656
{
657
if(event->key() == Qt::Key_Escape)
658
emit(escPressed());
659
}
660
661
662
// Key released...
663
//-----------------------------------------------------------------------------
664
void GLWidget::keyReleaseEvent(QKeyEvent *event)
665
{
666
}
667
668
669
670
// Mouse button pressed...
671
//-----------------------------------------------------------------------------
672
void GLWidget::mousePressEvent(QMouseEvent *event)
673
{
674
lastPos = event->pos();
675
lastPressPos = event->pos();
676
setFocus(); // for tracing keyboard events
677
}
678
679
// Mouse button released...
680
//-----------------------------------------------------------------------------
681
void GLWidget::mouseReleaseEvent(QMouseEvent *event)
682
{
683
if((event->button() == Qt::RightButton) && (event->pos() == lastPressPos)) {
684
#if WITH_QT6
685
((MainWindow*)parent())->showContextMenu(event->globalPosition().toPoint());
686
#else
687
((MainWindow*)parent())->showContextMenu(event->globalPos());
688
#endif
689
}
690
}
691
692
// Mouse wheel rotates...
693
//-----------------------------------------------------------------------------
694
void GLWidget::wheelEvent(QWheelEvent *event)
695
{
696
#if WITH_QT6
697
makeCurrent();
698
double s = exp((double)(event->angleDelta().y())*0.001);
699
#else
700
double s = exp((double)(event->delta())*0.001);
701
#endif
702
glScaled(s, s, s);
703
updateGL();
704
#if WITH_QT6
705
lastPos = event->position().toPoint();
706
#else
707
lastPos = event->pos();
708
#endif
709
getMatrix();
710
}
711
712
713
714
// Mouse moves...
715
//-----------------------------------------------------------------------------
716
void GLWidget::mouseMoveEvent(QMouseEvent *event)
717
{
718
#if WITH_QT6
719
makeCurrent();
720
#endif
721
722
GLint viewport[4];
723
glGetIntegerv(GL_VIEWPORT, viewport);
724
725
#if WITH_QT6
726
int dx = event->position().x() - lastPos.x();
727
int dy = event->position().y() - lastPos.y();
728
#else
729
int dx = event->x() - lastPos.x();
730
int dy = event->y() - lastPos.y();
731
#endif
732
733
dy = -dy;
734
735
if (
736
#if WITH_QT6
737
((event->buttons() & Qt::LeftButton) && (event->buttons() & Qt::MiddleButton))
738
#else
739
((event->buttons() & Qt::LeftButton) && (event->buttons() & Qt::MidButton))
740
#endif
741
||
742
event->buttons() == Qt::RightButton // added for easy scaling
743
) {
744
745
// Scale:
746
double s = exp(dy*0.01);
747
glScaled(s, s, s);
748
updateGL();
749
750
} else if (event->buttons() == Qt::LeftButton) {
751
752
// Rotation:
753
double ax = -(double)dy;
754
double ay = (double)dx;
755
double az = 0.0;
756
757
double s = 180.0*sqrt(ax*ax+ay*ay+az*az)/(double)(viewport[3]+1);
758
double bx = invmatrix[0]*ax + invmatrix[4]*ay + invmatrix[8]*az;
759
double by = invmatrix[1]*ax + invmatrix[5]*ay + invmatrix[9]*az;
760
double bz = invmatrix[2]*ax + invmatrix[6]*ay + invmatrix[10]*az;
761
glRotated(s, bx, by, bz);
762
updateGL();
763
764
} else if (
765
#if WITH_QT6
766
(event->buttons() == Qt::MiddleButton)
767
#else
768
(event->buttons() == Qt::MidButton)
769
#endif
770
771
||
772
(event->buttons() == (Qt::LeftButton | Qt::RightButton)) // added for 2 button mouse
773
){
774
775
// Translation:
776
double s = 2.0/(double)(viewport[3]+1);
777
double ax = s*dx;
778
double ay = s*dy;
779
double az = 0.0;
780
glLoadIdentity();
781
glTranslated(ax, ay, az);
782
glMultMatrixq(matrix);
783
updateGL();
784
}
785
786
lastPos = event->pos();
787
getMatrix();
788
}
789
790
791
792
// Mouse button double clicked...
793
//-----------------------------------------------------------------------------
794
void GLWidget::mouseDoubleClickEvent(QMouseEvent *event)
795
{
796
#if WITH_QT6
797
makeCurrent();
798
#endif
799
if(getLists() == 0)
800
return;
801
802
/*
803
To avoid segmentation fault in MSYS2 environment, compass, numbers and indexes are hidden.
804
These will be restored at the end of this function. Do not return before restoring these.
805
*/
806
bool prevStateDrawCoordinates = stateDrawCoordinates;
807
bool prevStateDrawSurfaceNumbers = stateDrawSurfaceNumbers;
808
bool prevStateDrawEdgeNumbers = stateDrawEdgeNumbers;
809
bool prevStateDrawNodeNumbers = stateDrawNodeNumbers;
810
bool prevStateDrawBoundaryIndex = stateDrawBoundaryIndex;
811
bool prevStateDrawBodyIndex = stateDrawBodyIndex;
812
stateDrawCoordinates = false;
813
stateDrawSurfaceNumbers = false;
814
stateDrawEdgeNumbers = false;
815
stateDrawNodeNumbers = false;
816
stateDrawBoundaryIndex = false;
817
stateDrawBodyIndex = false;
818
819
820
static list_t dummylist;
821
static GLuint buffer[1024];
822
const int bufferSize = sizeof(buffer)/sizeof(GLuint);
823
824
GLint viewport[4];
825
GLdouble projection[16];
826
827
GLint hits;
828
GLint i, j;
829
830
updateGL();
831
#if WITH_QT6
832
makeCurrent();
833
#endif
834
835
glSelectBuffer(bufferSize, buffer);
836
glRenderMode(GL_SELECT);
837
glInitNames();
838
839
glMatrixMode(GL_PROJECTION);
840
glPushMatrix();
841
glGetIntegerv(GL_VIEWPORT, viewport);
842
glGetDoublev(GL_PROJECTION_MATRIX, projection);
843
glLoadIdentity();
844
845
#if WITH_QT6
846
GLdouble x = event->position().x();
847
GLdouble y = (double)viewport[3]-event->position().y()-1;
848
#else
849
GLdouble x = event->x();
850
GLdouble y = (double)viewport[3]-event->y()-1;
851
#endif
852
853
GLdouble deltaX = 3.0;
854
GLdouble deltaY = 3.0;
855
856
gluPickMatrix(x, y, deltaX, deltaY, viewport);
857
glMultMatrixd(projection);
858
859
glMatrixMode(GL_MODELVIEW);
860
861
862
/*This is to avoid segmentation fault in Linux with old hardware*/
863
setMeshVisibility(false, false, false);
864
865
#if WITH_QT6
866
paintGL();
867
#else
868
updateGL();
869
#endif
870
871
/*Again, this is to avoid segmentation fault in Linux with old hardware and to suppress blinking*/
872
setMeshVisibility(stateDrawSurfaceMesh, stateDrawVolumeMesh, stateDrawSharpEdges);
873
874
hits = glRenderMode(GL_RENDER);
875
876
bool badDriver = true;
877
GLuint smallestz = DUMMY_NAME;
878
GLuint nearest = DUMMY_NAME;
879
880
if(hits != 0) {
881
for (i=0, j=0; i<hits; i++) {
882
GLuint minz = buffer[j+1];
883
GLuint resultz = buffer[j+3];
884
885
badDriver = (badDriver && (minz == 0x80000000));
886
887
if(minz < smallestz) {
888
nearest = resultz;
889
smallestz = minz;
890
}
891
892
j += 3 + buffer[j];
893
}
894
}
895
896
glMatrixMode(GL_PROJECTION);
897
glPopMatrix();
898
glMatrixMode(GL_MODELVIEW);
899
900
if(badDriver) {
901
cerr << "Detected bad GL-context or broken graphics driver" << endl;
902
cerr.flush();
903
cout << "glRenderMode(GL_RENDER) produces bad z-values" << endl;
904
cout << "Unable to reliably select objects" << endl;
905
cout << "Vendor: " << glGetString(GL_VENDOR) << endl;
906
cout << "Renderer: " << glGetString(GL_RENDERER) << endl;
907
cout << "Version: " << glGetString(GL_VERSION) << endl;
908
cout.flush();
909
}
910
911
// highlight the selected boundary:
912
if(nearest != DUMMY_NAME) {
913
list_t *l = getList(nearest);
914
915
// skip sharp edge lists
916
if(l->getType() == SHARPEDGELIST) {
917
918
/*
919
Restoration of view settings. These were adjusted at the beginning of this function.
920
*/
921
stateDrawCoordinates = prevStateDrawCoordinates;
922
stateDrawSurfaceNumbers = prevStateDrawSurfaceNumbers;
923
stateDrawEdgeNumbers = prevStateDrawEdgeNumbers;
924
stateDrawNodeNumbers = prevStateDrawNodeNumbers;
925
stateDrawBoundaryIndex = prevStateDrawBoundaryIndex;
926
stateDrawBodyIndex = prevStateDrawBodyIndex;
927
928
929
updateGL();
930
return;
931
}
932
933
// substitute surfacemeshlist with the parent surfacelist:
934
if(l->getType() == SURFACEMESHLIST)
935
l = getList(l->getParent());
936
937
// if not ctrl pressed, rebuild all selected lists except this one:
938
if(!(event->modifiers() & Qt::ControlModifier)) {
939
for(i = 0; i < getLists(); i++) {
940
list_t *l2 = getList(i);
941
if(l2->isSelected() && (l2->getIndex() != l->getIndex())) {
942
glDeleteLists(l2->getObject(), 1);
943
l2->setSelected(false);
944
if(l2->getType() == SURFACELIST) {
945
for( int j = 0; j < mesh->getSurfaces(); j++ ) {
946
surface_t *surf = mesh->getSurface(j);
947
if ( surf->getIndex() == l2->getIndex() )
948
surf->setSelected(l2->isSelected());
949
}
950
l2->setObject(generateSurfaceList(l2->getIndex(), surfaceColor)); // cyan
951
} else if(l2->getType() == EDGELIST) {
952
for( int j=0; j < mesh->getEdges(); j++ ) {
953
edge_t *edge = mesh->getEdge(j);
954
if ( edge->getIndex() == l2->getIndex() )
955
edge->setSelected(l2->isSelected());
956
}
957
l2->setObject(generateEdgeList(l2->getIndex(), edgeColor)); // green
958
}
959
}
960
}
961
}
962
963
// Toggle selection:
964
l->setSelected(!l->isSelected());
965
966
glDeleteLists(l->getObject(), 1);
967
968
// Highlight current selection:
969
if(l->getType() == SURFACELIST) {
970
if(l->isSelected()) {
971
l->setObject(generateSurfaceList(l->getIndex(), selectionColor)); // red
972
} else {
973
l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
974
}
975
976
for( int i=0; i<mesh->getSurfaces(); i++ ) {
977
surface_t *surf = mesh->getSurface(i);
978
if ( surf->getIndex() == l->getIndex() ) surf->setSelected(l->isSelected());
979
}
980
981
} else if(l->getType() == EDGELIST) {
982
if(l->isSelected()) {
983
l->setObject(generateEdgeList(l->getIndex(), selectionColor)); // red
984
} else {
985
l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
986
}
987
for( int i=0; i < mesh->getEdges(); i++ ) {
988
edge_t *edge = mesh->getEdge(i);
989
if ( edge->getIndex() == l->getIndex() ) edge->setSelected(l->isSelected());
990
}
991
}
992
993
// body selection:
994
//----------------
995
currentlySelectedBody = -1;
996
if( (event->modifiers() & Qt::ShiftModifier) || bodyEditActive) {
997
998
// determine the max bulk index
999
int MAX_BULK_INDEX = -1;
1000
1001
for(int i = 0; i < mesh->getElements(); i++) {
1002
element_t *elem = mesh->getElement(i);
1003
if(elem->getNature() != PDE_BULK)
1004
break;
1005
if(elem->getIndex() > MAX_BULK_INDEX)
1006
MAX_BULK_INDEX = elem->getIndex();
1007
}
1008
1009
for(int i = 0; i < mesh->getSurfaces(); i++) {
1010
surface_t *surf = mesh->getSurface(i);
1011
if(surf->getNature() != PDE_BULK)
1012
break;
1013
if(surf->getIndex() > MAX_BULK_INDEX)
1014
MAX_BULK_INDEX = surf->getIndex();
1015
}
1016
1017
for(int i = 0; i < mesh->getEdges(); i++) {
1018
edge_t *edge = mesh->getEdge(i);
1019
if(edge->getNature() != PDE_BULK)
1020
break;
1021
if(edge->getIndex() > MAX_BULK_INDEX)
1022
MAX_BULK_INDEX = edge->getIndex();
1023
}
1024
1025
MAX_BULK_INDEX++;
1026
if(MAX_BULK_INDEX == 0) {
1027
cout << "Error in body selection: "
1028
"There are no legal body indices from which to choose" << endl;
1029
cout.flush();
1030
goto body_selection_finished;
1031
}
1032
1033
// allocate temp arrays:
1034
bool *tmp1 = new bool[MAX_BULK_INDEX];
1035
bool *tmp2 = new bool[MAX_BULK_INDEX];
1036
1037
for(int i = 0; i < MAX_BULK_INDEX; i++) {
1038
tmp1[i] = true;
1039
tmp2[i] = false;
1040
}
1041
1042
// check if the selected lists uniquely determine a bulk body:
1043
for(int i = 0; i < getLists(); i++) {
1044
list_t *l2 = getList(i);
1045
1046
if(l2->isSelected() && (l2->getNature() == PDE_BULK)) {
1047
for(int j = 0; j < MAX_BULK_INDEX; j++) {
1048
if(j != l2->getIndex())
1049
tmp1[j] = false;
1050
}
1051
}
1052
1053
if(l2->isSelected() && (l2->getNature() == PDE_BOUNDARY) &&
1054
(l2->getType() == SURFACELIST)) {
1055
for(int j = 0; j < mesh->getSurfaces(); j++) {
1056
surface_t *surf = mesh->getSurface(j);
1057
if(surf->getIndex() == l2->getIndex()) {
1058
for(int k = 0; k < surf->getElements(); k++) {
1059
int l = surf->getElementIndex(k);
1060
if(l < 0)
1061
break;
1062
element_t *elem = mesh->getElement(l);
1063
if((elem->getIndex() < 0) || (elem->getIndex() >= MAX_BULK_INDEX))
1064
break;
1065
tmp2[elem->getIndex()] = true;
1066
}
1067
for(int k = 0; k < MAX_BULK_INDEX; k++) {
1068
tmp1[k] &= tmp2[k];
1069
tmp2[k] = false;
1070
}
1071
}
1072
}
1073
}
1074
}
1075
1076
// array "tmp1" should contain only one entry with value "true"
1077
int count = 0;
1078
int found = -1;
1079
for(int i = 0; i < MAX_BULK_INDEX; i++) {
1080
if( tmp1[i] ) {
1081
count++;
1082
found = i;
1083
}
1084
// cout << i << ": tmp1,2= " << tmp1[i] << "," << tmp2[i] << endl;
1085
}
1086
1087
if((count == 1) && (found >= 0))
1088
currentlySelectedBody = found;
1089
else if((count > 1)){
1090
int m = mostVisibleBody(MAX_BULK_INDEX, tmp1);
1091
if(m >=0) currentlySelectedBody = m;
1092
}
1093
1094
delete [] tmp1;
1095
delete [] tmp2;
1096
}
1097
body_selection_finished:
1098
1099
// Emit result to mainwindow:
1100
emit(signalBoundarySelected(l, event->modifiers()));
1101
1102
} else {
1103
1104
// Emit "nothing selected":
1105
dummylist.setNature(-1);
1106
dummylist.setType(-1);
1107
dummylist.setIndex(-1);
1108
emit(signalBoundarySelected(&dummylist, event->modifiers()));
1109
1110
}
1111
1112
/*
1113
Restoration of view settings. These were adjusted at the beginning of this function.
1114
*/
1115
stateDrawCoordinates = prevStateDrawCoordinates;
1116
stateDrawSurfaceNumbers = prevStateDrawSurfaceNumbers;
1117
stateDrawEdgeNumbers = prevStateDrawEdgeNumbers;
1118
stateDrawNodeNumbers = prevStateDrawNodeNumbers;
1119
stateDrawBoundaryIndex = prevStateDrawBoundaryIndex;
1120
stateDrawBodyIndex = prevStateDrawBodyIndex;
1121
1122
1123
updateGL();
1124
}
1125
1126
1127
1128
// Get current matrix and its inverse...
1129
//-----------------------------------------------------------------------------
1130
void GLWidget::getMatrix()
1131
{
1132
glGetQrealv(GL_MODELVIEW_MATRIX, matrix);
1133
helpers->invertMatrix(matrix, invmatrix);
1134
}
1135
1136
1137
1138
// Rebuild lists...
1139
//-----------------------------------------------------------------------------
1140
void GLWidget::rebuildLists()
1141
{
1142
#if WITH_QT6
1143
makeCurrent();
1144
#endif
1145
double *bb = mesh->boundingBox();
1146
1147
drawTranslate[0] = bb[6]; // x-center
1148
drawTranslate[1] = bb[7]; // y-center
1149
drawTranslate[2] = bb[8]; // z-center
1150
drawScale = bb[9]; // scaling
1151
1152
delete [] bb;
1153
1154
if(getLists() > 0) {
1155
for(int i=0; i < getLists(); i++) {
1156
list_t *l = getList(i);
1157
glDeleteLists(l->getObject(), 1);
1158
}
1159
}
1160
1161
makeLists();
1162
1163
updateGL();
1164
}
1165
1166
// Compose GL surface lists...
1167
//-----------------------------------------------------------------------------
1168
void GLWidget::rebuildSurfaceLists()
1169
{
1170
for( int i = 0; i < getLists(); i++ )
1171
{
1172
list_t *l = getList(i);
1173
if( l->getType() == SURFACELIST )
1174
{
1175
glDeleteLists( l->getObject(), 1 );
1176
if(l->isSelected()) {
1177
l->setObject(generateSurfaceList(l->getIndex(), selectionColor)); // red
1178
} else {
1179
l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
1180
}
1181
}
1182
}
1183
}
1184
1185
// Compose GL edge lists...
1186
//-----------------------------------------------------------------------------
1187
void GLWidget::rebuildEdgeLists()
1188
{
1189
for( int i = 0; i < getLists(); i++ )
1190
{
1191
list_t *l = getList(i);
1192
if ( l->getType() == EDGELIST )
1193
{
1194
glDeleteLists( l->getObject(), 1 );
1195
if(l->isSelected()) {
1196
l->setObject(generateEdgeList(l->getIndex(), selectionColor)); // red
1197
} else {
1198
l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
1199
}
1200
}
1201
}
1202
}
1203
1204
1205
1206
// Compose GL object lists...
1207
//-----------------------------------------------------------------------------
1208
GLuint GLWidget::makeLists()
1209
{
1210
#if WITH_QT6
1211
makeCurrent();
1212
#endif
1213
1214
int i;
1215
list_t *l;
1216
1217
if((mesh == NULL) || mesh->isUndefined())
1218
return 0;
1219
1220
// The rule for composing lists to display is the following:
1221
//---------------------------------------------------------------------------
1222
// - All surface elements with index >= 0 will be drawn - one list/index
1223
// (list->type = SURFACELIST)
1224
// - For each surface element list, one auxiliary list will be drawn
1225
// (list->type = SURFACEMESHLIST)
1226
// - All edge elements with index >= 0 will be drawn - one list/index
1227
// (list->type = EDGELIST)
1228
// - All point elements with index >= 0 will be drawn - one list/index
1229
// (list->type = POINTLIST)
1230
// - A list of sharp edges will always be drawn (even if it is empty)
1231
//---------------------------------------------------------------------------
1232
1233
// Simultaneously, populate hash for mapping body & boundary indices:
1234
//--------------------------------------------------------------------
1235
boundaryMap.clear();
1236
bodyMap.clear();
1237
int boundaryCount = 0;
1238
int bodyCount = 0;
1239
1240
// Scan volume elements to determine the number of material indices:
1241
//-------------------------------------------------------------------
1242
QMap<int, int> bodyNatures;
1243
1244
for(i = 0; i < mesh->getElements(); i++) {
1245
element_t *element = mesh->getElement(i);
1246
int index = element->getIndex();
1247
1248
if(index >= 0) {
1249
int nature = element->getNature();
1250
1251
if(!bodyNatures.contains(index))
1252
bodyNatures.insert(index, nature);
1253
}
1254
}
1255
1256
QMapIterator<int, int> itrBody(bodyNatures);
1257
while (itrBody.hasNext()) {
1258
itrBody.next();
1259
int index = itrBody.key();
1260
int nature = itrBody.value();
1261
1262
if(nature == PDE_BULK)
1263
bodyMap.insert(index, bodyCount++);
1264
}
1265
1266
// Scan surface elements to determine the number of bcs. / mat. indices:
1267
//-----------------------------------------------------------------------
1268
int surface_bcs = 0;
1269
1270
QMap<int, int> surfaceNatures;
1271
1272
for(i = 0; i < mesh->getSurfaces(); i++) {
1273
surface_t *surface = mesh->getSurface(i);
1274
int index = surface->getIndex();
1275
1276
if(index > 0) {
1277
int nature = surface->getNature();
1278
1279
if(!surfaceNatures.contains(index))
1280
surfaceNatures.insert(index, nature);
1281
}
1282
}
1283
1284
QMapIterator<int, int> itrSurface(surfaceNatures);
1285
while (itrSurface.hasNext()) {
1286
itrSurface.next();
1287
int index = itrSurface.key();
1288
int nature = itrSurface.value();
1289
1290
if(nature > 0) {
1291
surface_bcs++;
1292
1293
if(nature == PDE_BULK)
1294
bodyMap.insert(index, bodyCount++);
1295
1296
if(nature == PDE_BOUNDARY)
1297
boundaryMap.insert(index, boundaryCount++);
1298
}
1299
}
1300
1301
cout << "Bcs/materials on surface elements: " << surface_bcs << endl;
1302
cout.flush();
1303
1304
// Scan edge elements to determine the number of bcs. / mat. indices:
1305
//--------------------------------------------------------------------
1306
int edge_bcs = 0;
1307
1308
QMap<int, int> edgeNatures;
1309
1310
for(i = 0; i < mesh->getEdges(); i++) {
1311
edge_t *edge = mesh->getEdge(i);
1312
int index = edge->getIndex();
1313
1314
if(index > 0) {
1315
int nature = edge->getNature();
1316
1317
if(!edgeNatures.contains(index))
1318
edgeNatures.insert(index, nature);
1319
}
1320
}
1321
1322
QMapIterator<int, int> itrEdge(edgeNatures);
1323
while (itrEdge.hasNext()) {
1324
itrEdge.next();
1325
int index = itrEdge.key();
1326
int nature = itrEdge.value();
1327
1328
if(nature > 0) {
1329
edge_bcs++;
1330
1331
if(nature == PDE_BULK)
1332
bodyMap.insert(index, bodyCount++);
1333
1334
if(nature == PDE_BOUNDARY)
1335
boundaryMap.insert(index, boundaryCount++);
1336
}
1337
}
1338
1339
cout << "Bcs/materials on edge elements: " << edge_bcs << endl;
1340
cout.flush();
1341
1342
// Scan point elements to determine the number of bcs. / mat. indices:
1343
//---------------------------------------------------------------------
1344
int point_bcs = 0;
1345
1346
// TODO
1347
1348
cout << "Bcs/materials on point elements: " << point_bcs << endl;
1349
cout.flush();
1350
1351
// Generate lists:
1352
//---------------------------------------------------------------------
1353
for(i = 0; i < getLists(); i++)
1354
delete list.at(i);
1355
1356
list.clear();
1357
1358
cout << "Generating lists to display" << endl;
1359
cout.flush();
1360
1361
// Surface lists:
1362
//----------------
1363
for(i = 0; i < mesh->getSurfaces(); i++)
1364
mesh->getSurface(i)->setSelected(false);
1365
1366
itrSurface.toFront();
1367
while (itrSurface.hasNext()) {
1368
itrSurface.next();
1369
int index = itrSurface.key();
1370
int nature = itrSurface.value();
1371
1372
if(nature > 0) {
1373
l = new list_t;
1374
list.push_back(l);
1375
1376
l->setNature(nature);
1377
l->setType(SURFACELIST);
1378
l->setIndex(index);
1379
l->setObject(generateSurfaceList(l->getIndex(), surfaceColor)); // cyan
1380
l->setChild(getLists());
1381
l->setParent(-1);
1382
l->setSelected(false);
1383
l->setVisible(stateDrawSurfaceElements);
1384
1385
// edges of surface elements (just for visual):
1386
l = new list_t;
1387
list.push_back(l);
1388
1389
l->setNature(PDE_UNKNOWN);
1390
l->setType(SURFACEMESHLIST);
1391
l->setIndex(index);
1392
l->setObject(generateSurfaceMeshList(l->getIndex(), surfaceMeshColor)); // black
1393
l->setChild(-1);
1394
l->setParent(getLists() - 2);
1395
l->setSelected(false);
1396
l->setVisible(stateDrawSurfaceMesh);
1397
}
1398
}
1399
1400
// Edge lists (only PDE_BOUNDARY):
1401
//---------------------------------
1402
for(i = 0; i < mesh->getEdges(); i++)
1403
mesh->getEdge(i)->setSelected(false);
1404
1405
itrEdge.toFront();
1406
while (itrEdge.hasNext()) {
1407
itrEdge.next();
1408
int index = itrEdge.key();
1409
int nature = itrEdge.value();
1410
1411
if(nature > 0) {
1412
l = new list_t;
1413
list.push_back(l);
1414
1415
l->setNature(nature);
1416
l->setType(EDGELIST);
1417
l->setIndex(index);
1418
l->setObject(generateEdgeList(l->getIndex(), edgeColor)); // green
1419
l->setChild(-1);
1420
l->setParent(-1);
1421
l->setSelected(false);
1422
l->setVisible(stateDrawEdgeElements);
1423
}
1424
}
1425
1426
// Point lists: TODO
1427
1428
// Sharp edges (just for visual):
1429
//--------------------------------
1430
l = new list_t;
1431
list.push_back(l);
1432
1433
l->setNature(PDE_UNKNOWN);
1434
l->setType(SHARPEDGELIST);
1435
l->setIndex(-1);
1436
l->setObject(generateSharpEdgeList(sharpEdgeColor)); // black
1437
l->setChild(-1);
1438
l->setParent(-1);
1439
l->setSelected(false);
1440
l->setVisible(stateDrawSharpEdges);
1441
1442
// Volume mesh (visual only):
1443
//----------------------------
1444
l = new list_t;
1445
list.push_back(l);
1446
1447
l->setNature(PDE_UNKNOWN);
1448
l->setType(VOLUMEMESHLIST);
1449
l->setIndex(-1);
1450
l->setObject(generateVolumeMeshList(Qt::black)); // black
1451
l->setChild(-1);
1452
l->setParent(-1);
1453
l->setSelected(false);
1454
l->setVisible(stateDrawVolumeMesh);
1455
1456
// Clean up:
1457
//-----------
1458
edgeNatures.clear();
1459
surfaceNatures.clear();
1460
bodyNatures.clear();
1461
1462
updateGL();
1463
getMatrix();
1464
1465
cout << "Generated " << getLists() << " lists" << endl;
1466
cout.flush();
1467
1468
return getLists();
1469
}
1470
1471
1472
// Generate volume mesh list...
1473
//-----------------------------------------------------------------------------
1474
GLuint GLWidget::generateVolumeMeshList(QColor qColor)
1475
{
1476
static int tetmap[6][2] = {{0, 1}, {0, 2}, {0, 3},
1477
{1, 2}, {1, 3}, {2, 3}};
1478
1479
static int wedgemap[9][2] = {{0, 1}, {1, 2}, {2, 0},
1480
{0, 3}, {1, 4}, {2, 5},
1481
{3, 4}, {4, 5}, {5, 3}};
1482
1483
1484
static int hexmap[12][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0},
1485
{0, 4}, {1, 5}, {2, 6}, {3, 7},
1486
{4, 5}, {5, 6}, {6, 7}, {7, 4}};
1487
1488
double R = qColor.red() / 255.0;
1489
double G = qColor.green() / 255.0;
1490
double B = qColor.blue() / 255.0;
1491
1492
GLuint current = glGenLists(1);
1493
glNewList(current, GL_COMPILE);
1494
1495
glBegin(GL_LINES);
1496
1497
for(int i = 0; i < mesh->getElements(); i++) {
1498
element_t *element = mesh->getElement(i);
1499
1500
glColor3d(R, G, B);
1501
1502
int nofEdges = 0;
1503
int *edgeMap = 0;
1504
1505
switch((int)(element->getCode() / 100)) {
1506
case 5:
1507
nofEdges = 6;
1508
edgeMap = &tetmap[0][0];
1509
break;
1510
case 7:
1511
nofEdges = 9;
1512
edgeMap = &wedgemap[0][0];
1513
break;
1514
case 8:
1515
nofEdges = 12;
1516
edgeMap = &hexmap[0][0];
1517
break;
1518
}
1519
1520
// draw edges:
1521
for(int j = 0; j < nofEdges; j++) {
1522
int p0 = *edgeMap++;
1523
int p1 = *edgeMap++;
1524
1525
int q0 = element->getNodeIndex(p0);
1526
int q1 = element->getNodeIndex(p1);
1527
1528
node_t *n0 = mesh->getNode(q0);
1529
node_t *n1 = mesh->getNode(q1);
1530
1531
double x0 = ( n0->getX(0) - drawTranslate[0] ) / drawScale;
1532
double y0 = ( n0->getX(1) - drawTranslate[1] ) / drawScale;
1533
double z0 = ( n0->getX(2) - drawTranslate[2] ) / drawScale;
1534
1535
double x1 = ( n1->getX(0) - drawTranslate[0] ) / drawScale;
1536
double y1 = ( n1->getX(1) - drawTranslate[1] ) / drawScale;
1537
double z1 = ( n1->getX(2) - drawTranslate[2] ) / drawScale;
1538
1539
glVertex3d(x0, y0, z0);
1540
glVertex3d(x1, y1, z1);
1541
}
1542
}
1543
1544
glEnd();
1545
1546
glEndList();
1547
1548
return current;
1549
}
1550
1551
1552
1553
// Generate surface list...
1554
//-----------------------------------------------------------------------------
1555
GLuint GLWidget::generateSurfaceList(int index, QColor qColor)
1556
{
1557
double x0[3], x1[3], x2[3], x3[3], u[3];
1558
1559
double R = qColor.red() / 255.0;
1560
double G = qColor.green() / 255.0;
1561
double B = qColor.blue() / 255.0;
1562
1563
GLuint current = glGenLists(1);
1564
glNewList(current, GL_COMPILE);
1565
1566
// Draw triangles:
1567
//-----------------
1568
glBegin(GL_TRIANGLES);
1569
1570
for(int i=0; i < mesh->getSurfaces(); i++) {
1571
surface_t *surface = mesh->getSurface(i);
1572
1573
if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 3)) {
1574
1575
glColor3d(R, G, B);
1576
1577
if(stateBcColors && (surface->getNature() == PDE_BOUNDARY)) {
1578
double c[3];
1579
indexColors(c, index);
1580
glColor3d(c[0], c[1], c[2]);
1581
}
1582
1583
if(stateBodyColors) {
1584
int bodyIndex = surface->getIndex();
1585
if(surface->getNature() == PDE_BOUNDARY) {
1586
int parentIndex = surface->getElementIndex(0);
1587
element_t *parent = mesh->getElement(parentIndex);
1588
bodyIndex = parent->getIndex();
1589
}
1590
double c[3];
1591
indexColors(c, bodyIndex);
1592
glColor3d(c[0], c[1], c[2]);
1593
}
1594
1595
// change normal direction:
1596
changeNormalDirection(u, surface->getNormalVec());
1597
glNormal3dv(u);
1598
1599
int n0 = surface->getNodeIndex(0);
1600
int n1 = surface->getNodeIndex(1);
1601
int n2 = surface->getNodeIndex(2);
1602
1603
x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1604
x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1605
x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1606
1607
x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1608
x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1609
x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1610
1611
x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1612
x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1613
x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1614
1615
changeNormalDirection(u, surface->getVertexNormalVec(0));
1616
if ( !stateFlatShade ) glNormal3dv(u);
1617
glVertex3dv(x0);
1618
1619
changeNormalDirection(u, surface->getVertexNormalVec(1));
1620
if ( !stateFlatShade ) glNormal3dv(u);
1621
glVertex3dv(x1);
1622
1623
changeNormalDirection(u, surface->getVertexNormalVec(2));
1624
if ( !stateFlatShade ) glNormal3dv(u);
1625
glVertex3dv(x2);
1626
}
1627
}
1628
1629
glEnd();
1630
1631
// Draw quads:
1632
//------------
1633
glBegin(GL_QUADS);
1634
1635
for(int i=0; i < mesh->getSurfaces(); i++) {
1636
surface_t *surface = mesh->getSurface(i);
1637
1638
if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 4)) {
1639
1640
glColor3d(R, G, B);
1641
1642
if(stateBcColors && (surface->getNature() == PDE_BOUNDARY)) {
1643
double c[3];
1644
indexColors(c, index);
1645
glColor3d(c[0], c[1], c[2]);
1646
}
1647
1648
if(stateBodyColors) {
1649
int bodyIndex = surface->getIndex();
1650
if(surface->getNature() == PDE_BOUNDARY) {
1651
int parentIndex = surface->getElementIndex(0);
1652
element_t *parent = mesh->getElement(parentIndex);
1653
bodyIndex = parent->getIndex();
1654
}
1655
double c[3];
1656
indexColors(c, bodyIndex);
1657
glColor3d(c[0], c[1], c[2]);
1658
}
1659
1660
// change normal direction:
1661
changeNormalDirection(u, surface->getNormalVec());
1662
glNormal3dv(u);
1663
1664
int n0 = surface->getNodeIndex(0);
1665
int n1 = surface->getNodeIndex(1);
1666
int n2 = surface->getNodeIndex(2);
1667
int n3 = surface->getNodeIndex(3);
1668
1669
x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1670
x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1671
x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1672
1673
x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1674
x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1675
x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1676
1677
x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1678
x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1679
x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1680
1681
x3[0] = (mesh->getNode(n3)->getX(0) - drawTranslate[0]) / drawScale;
1682
x3[1] = (mesh->getNode(n3)->getX(1) - drawTranslate[1]) / drawScale;
1683
x3[2] = (mesh->getNode(n3)->getX(2) - drawTranslate[2]) / drawScale;
1684
1685
changeNormalDirection(u, surface->getVertexNormalVec(0));
1686
if ( !stateFlatShade ) glNormal3dv(u);
1687
glVertex3dv(x0);
1688
1689
changeNormalDirection(u, surface->getVertexNormalVec(1));
1690
if ( !stateFlatShade ) glNormal3dv(u);
1691
glVertex3dv(x1);
1692
1693
changeNormalDirection(u, surface->getVertexNormalVec(2));
1694
if ( !stateFlatShade ) glNormal3dv(u);
1695
glVertex3dv(x2);
1696
1697
changeNormalDirection(u, surface->getVertexNormalVec(3));
1698
if ( !stateFlatShade ) glNormal3dv(u);
1699
glVertex3dv(x3);
1700
}
1701
}
1702
1703
glEnd();
1704
glEndList();
1705
1706
return current;
1707
}
1708
1709
1710
1711
// Generate surface edge list...
1712
//-----------------------------------------------------------------------------
1713
GLuint GLWidget::generateSurfaceMeshList(int index, QColor qColor)
1714
{
1715
double x0[3], x1[3], x2[3], x3[3];
1716
1717
double R = qColor.red() / 255.0;
1718
double G = qColor.green() / 255.0;
1719
double B = qColor.blue() / 255.0;
1720
1721
GLuint current = glGenLists(1);
1722
glNewList(current, GL_COMPILE);
1723
1724
// Draw lines:
1725
//------------
1726
glLineWidth(1.0);
1727
glDisable(GL_LIGHTING);
1728
glColor3d(R, G, B);
1729
glBegin(GL_LINES);
1730
1731
for(int i=0; i < mesh->getSurfaces(); i++) {
1732
surface_t *surface = mesh->getSurface(i);
1733
1734
if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 3)) {
1735
int n0 = surface->getNodeIndex(0);
1736
int n1 = surface->getNodeIndex(1);
1737
int n2 = surface->getNodeIndex(2);
1738
1739
x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1740
x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1741
x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1742
1743
x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1744
x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1745
x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1746
1747
x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1748
x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1749
x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1750
1751
glVertex3dv(x0);
1752
glVertex3dv(x1);
1753
1754
glVertex3dv(x1);
1755
glVertex3dv(x2);
1756
1757
glVertex3dv(x2);
1758
glVertex3dv(x0);
1759
}
1760
}
1761
1762
for(int i=0; i < mesh->getSurfaces(); i++) {
1763
surface_t *surface = mesh->getSurface(i);
1764
1765
if((surface->getIndex() == index) && ((int)(surface->getCode() / 100) == 4)) {
1766
int n0 = surface->getNodeIndex(0);
1767
int n1 = surface->getNodeIndex(1);
1768
int n2 = surface->getNodeIndex(2);
1769
int n3 = surface->getNodeIndex(3);
1770
1771
x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1772
x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1773
x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1774
1775
x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1776
x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1777
x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1778
1779
x2[0] = (mesh->getNode(n2)->getX(0) - drawTranslate[0]) / drawScale;
1780
x2[1] = (mesh->getNode(n2)->getX(1) - drawTranslate[1]) / drawScale;
1781
x2[2] = (mesh->getNode(n2)->getX(2) - drawTranslate[2]) / drawScale;
1782
1783
x3[0] = (mesh->getNode(n3)->getX(0) - drawTranslate[0]) / drawScale;
1784
x3[1] = (mesh->getNode(n3)->getX(1) - drawTranslate[1]) / drawScale;
1785
x3[2] = (mesh->getNode(n3)->getX(2) - drawTranslate[2]) / drawScale;
1786
1787
glVertex3dv(x0);
1788
glVertex3dv(x1);
1789
1790
glVertex3dv(x1);
1791
glVertex3dv(x2);
1792
1793
glVertex3dv(x2);
1794
glVertex3dv(x3);
1795
1796
glVertex3dv(x3);
1797
glVertex3dv(x0);
1798
}
1799
}
1800
glEnd();
1801
1802
glEnable(GL_LIGHTING);
1803
glEndList();
1804
1805
return current;
1806
}
1807
1808
1809
// Generate edge list...
1810
//-----------------------------------------------------------------------------
1811
GLuint GLWidget::generateEdgeList(int index, QColor qColor)
1812
{
1813
double x0[3], x1[3];
1814
1815
double R = qColor.red() / 255.0;
1816
double G = qColor.green() / 255.0;
1817
double B = qColor.blue() / 255.0;
1818
1819
GLuint current = glGenLists(1);
1820
glNewList(current, GL_COMPILE);
1821
glColor3d(R, G, B);
1822
glLineWidth(4.0);
1823
glDisable(GL_LIGHTING);
1824
glBegin(GL_LINES);
1825
1826
for(int i=0; i < mesh->getEdges(); i++) {
1827
edge_t *edge = mesh->getEdge(i);
1828
1829
if(edge->getIndex() == index) {
1830
int n0 = edge->getNodeIndex(0);
1831
int n1 = edge->getNodeIndex(1);
1832
1833
x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1834
x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1835
x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1836
1837
x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1838
x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1839
x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1840
1841
glVertex3dv(x0);
1842
glVertex3dv(x1);
1843
}
1844
}
1845
1846
glEnd();
1847
1848
glEnable(GL_LIGHTING);
1849
glEndList();
1850
1851
return current;
1852
}
1853
1854
1855
1856
// Generate sharp edge list...
1857
//-----------------------------------------------------------------------------
1858
GLuint GLWidget::generateSharpEdgeList(QColor qColor)
1859
{
1860
double x0[3], x1[3];
1861
1862
double R = qColor.red() / 255.0;
1863
double G = qColor.green() / 255.0;
1864
double B = qColor.blue() / 255.0;
1865
1866
GLuint current = glGenLists(1);
1867
glNewList(current, GL_COMPILE);
1868
1869
glColor3d(R, G, B);
1870
glLineWidth(1.0);
1871
glDisable(GL_LIGHTING);
1872
glBegin(GL_LINES);
1873
1874
for(int i=0; i < mesh->getEdges(); i++) {
1875
edge_t *edge = mesh->getEdge(i);
1876
1877
if(edge->isSharp()) {
1878
int n0 = edge->getNodeIndex(0);
1879
int n1 = edge->getNodeIndex(1);
1880
1881
x0[0] = (mesh->getNode(n0)->getX(0) - drawTranslate[0]) / drawScale;
1882
x0[1] = (mesh->getNode(n0)->getX(1) - drawTranslate[1]) / drawScale;
1883
x0[2] = (mesh->getNode(n0)->getX(2) - drawTranslate[2]) / drawScale;
1884
1885
x1[0] = (mesh->getNode(n1)->getX(0) - drawTranslate[0]) / drawScale;
1886
x1[1] = (mesh->getNode(n1)->getX(1) - drawTranslate[1]) / drawScale;
1887
x1[2] = (mesh->getNode(n1)->getX(2) - drawTranslate[2]) / drawScale;
1888
1889
glVertex3dv(x0);
1890
glVertex3dv(x1);
1891
}
1892
}
1893
1894
glEnd();
1895
glEnable(GL_LIGHTING);
1896
glEndList();
1897
1898
return current;
1899
}
1900
1901
1902
// Draw coordinates:
1903
//-----------------------------------------------------------------------------
1904
void GLWidget::drawCoordinates()
1905
{
1906
glMatrixMode(GL_PROJECTION);
1907
glPushMatrix();
1908
1909
// glTranslated(-0.8, -0.8, 5.0);
1910
glTranslated(-0.8, -0.8, ZSHIFT);
1911
1912
glMatrixMode(GL_MODELVIEW);
1913
1914
// z-axis
1915
glColor3d(0, 0, 1);
1916
gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1917
renderText(0.0, 0.0, 0.25, "Z");
1918
1919
// x-axis
1920
glColor3d(1, 0, 0);
1921
glRotated(90, 0, 1, 0);
1922
gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1923
renderText(0.0, 0.0, 0.25, "X");
1924
glRotated(-90, 0, 1, 0);
1925
1926
// y-axis
1927
glColor3d(0, 1, 0);
1928
glRotated(-90, 1, 0, 0);
1929
gluCylinder(quadric_axis, 0.02, 0.0, 0.2, 8, 8);
1930
renderText(0.0, 0.0, 0.25, "Y");
1931
glRotated(90, 1, 0, 0);
1932
1933
glMatrixMode(GL_PROJECTION);
1934
glPopMatrix();
1935
1936
glMatrixMode(GL_MODELVIEW);
1937
1938
return;
1939
}
1940
1941
bool GLWidget::toggleCoordinates()
1942
{
1943
#if WITH_QT6
1944
makeCurrent();
1945
#endif
1946
stateDrawCoordinates = !stateDrawCoordinates;
1947
updateGL();
1948
return stateDrawCoordinates;
1949
}
1950
1951
// Draw background image...
1952
//-----------------------------------------------------------------------------
1953
void GLWidget::drawBgImage()
1954
{
1955
GLint viewport[4];
1956
1957
if(!bgTexture) {
1958
#if WITH_QT5 || WITH_QT6
1959
cout << "Bind texture " << string(bgImageFileName.toLatin1()) << "... ";
1960
QOpenGLTexture texture(QImage(bgImageFileName).mirrored());
1961
bgSizeX = texture.width();
1962
bgSizeY = texture.height();
1963
bgTexture = texture.textureId();
1964
cout << "done" << endl;
1965
#else
1966
cout << "Bind texture " << string(bgImageFileName.toAscii()) << "... ";
1967
QPixmap pixmap(bgImageFileName);
1968
bgSizeX = pixmap.width();
1969
bgSizeY = pixmap.height();
1970
bgTexture = bindTexture(pixmap, GL_TEXTURE_2D);
1971
cout << "done" << endl;
1972
#endif
1973
}
1974
1975
if(!bgTexture) {
1976
cout << "Failed to bind texture" << endl;
1977
stateUseBgImage = false;
1978
return;
1979
}
1980
1981
glGetIntegerv(GL_VIEWPORT, viewport);
1982
1983
double relativeSizeX = (double)viewport[2] / (double)viewport[3];
1984
double relativeSizeY = 1.0;
1985
1986
double bgRelativeSizeX = (double)bgSizeX / (double)viewport[3];
1987
double bgRelativeSizeY = (double)bgSizeY / (double)viewport[3];
1988
1989
double width = 1.0;
1990
double height = 1.0;
1991
double depth = 9.9;
1992
double xshift = 0.0;
1993
double yshift = 0.0;
1994
1995
if(stateAlignRightBgImage) {
1996
width = bgRelativeSizeX;
1997
height = bgRelativeSizeY;
1998
xshift = relativeSizeX - bgRelativeSizeX;
1999
yshift = bgRelativeSizeY - relativeSizeY;
2000
}
2001
2002
if(stateStretchBgImage) {
2003
width = (double)viewport[2] / (double)viewport[3];
2004
height = 1.0;
2005
xshift = 0.0;
2006
yshift = 0.0;
2007
}
2008
2009
glDisable(GL_DEPTH_TEST);
2010
glPushMatrix();
2011
glLoadIdentity();
2012
glColor3d(1, 1, 1);
2013
glDisable(GL_LIGHTING);
2014
glEnable(GL_TEXTURE_2D);
2015
glBindTexture(GL_TEXTURE_2D, bgTexture);
2016
2017
glBegin(GL_QUADS);
2018
glTexCoord2d(0, 0);
2019
glVertex3d(-width+xshift, -height+yshift, -depth);
2020
glTexCoord2d(1, 0);
2021
glVertex3d(+width+xshift, -height+yshift, -depth);
2022
glTexCoord2d(1, 1);
2023
glVertex3d(+width+xshift, +height+yshift, -depth);
2024
glTexCoord2d(0, 1);
2025
glVertex3d(-width+xshift, +height+yshift, -depth);
2026
glEnd();
2027
2028
glDisable(GL_TEXTURE_2D);
2029
glEnable(GL_LIGHTING);
2030
glPopMatrix();
2031
glEnable(GL_DEPTH_TEST);
2032
}
2033
2034
2035
// Auxiliary function for changing the direction of a vector...
2036
//---------------------------------------------------------------------------
2037
void GLWidget::changeNormalDirection(double *u, double *v)
2038
{
2039
u[0] = -v[0];
2040
u[1] = -v[1];
2041
u[2] = -v[2];
2042
}
2043
2044
list_t* GLWidget::getList(int i) const
2045
{
2046
return list.at(i);
2047
}
2048
2049
int GLWidget::getLists() const
2050
{
2051
return list.count();
2052
}
2053
2054
// Set 'c' to an RGB color corresponding to index 'i'.
2055
// 'c' should be pre-allocated to a length of at least 3.
2056
void GLWidget::indexColors(double *c, int i)
2057
{
2058
c[0] = 0.5 + 0.5 * sin(1.0 * i);
2059
c[1] = 0.5 + 0.5 * cos(2.0 * i);
2060
c[2] = 0.5 + 0.5 * cos(3.0 * i);
2061
}
2062
2063
void GLWidget::indexColors(int *c, int i)
2064
{
2065
double tmp[3];
2066
2067
indexColors(tmp, i);
2068
for (int j = 0; j < 3; j++) c[j] = int(tmp[j]*255 + 0.5);
2069
}
2070
2071
2072
void GLWidget::setMeshVisibility(bool stateDrawSurfaceMesh, bool stateDrawVolumeMesh, bool stateDrawSharpEdges){
2073
/*
2074
This function is used in mouseDoubleClickEvent(mouseEvent event) to avoid segmentation fault observed Linux
2075
environment with old hardware.
2076
*/
2077
2078
mesh_t *mesh = getMesh();
2079
int lists = getLists();
2080
2081
if (mesh == NULL) {
2082
return;
2083
}
2084
2085
2086
for (int i = 0; i < lists; i++) {
2087
list_t *l = getList(i);
2088
int type = l->getType();
2089
if (type == SURFACEMESHLIST) {
2090
l->setVisible(stateDrawSurfaceMesh);
2091
2092
// do not set visible if the parent surface list is hidden
2093
int p = l->getParent();
2094
if (p >= 0) {
2095
list_t *lp = getList(p);
2096
if (!lp->isVisible())
2097
l->setVisible(false);
2098
}
2099
}else if (type == VOLUMEMESHLIST) {
2100
l->setVisible(stateDrawVolumeMesh);
2101
}else if (type == SHARPEDGELIST) {
2102
l->setVisible(stateDrawSharpEdges);
2103
}
2104
}
2105
}
2106
2107
int GLWidget::mostVisibleBody(int n, bool* tmp1){
2108
/*
2109
This function is called in GLWidget::mouseDoubleClickEvent(QMouseEvent *event) to
2110
identify the most visible body when the double-clicked surface is shared by multiple bodies.
2111
This is a public function to be called from ObjectBrowser.
2112
*/
2113
2114
long *nElement = new long[n];
2115
long *nVisibleElement = new long[n];
2116
for(int i = 0; i < n; i++){
2117
nElement[i] = 0;
2118
nVisibleElement[i] = 0;
2119
}
2120
2121
for(int i = 0; i < getLists(); i++) {
2122
list_t *l2 = getList(i);
2123
if(l2->getNature() == PDE_BOUNDARY && l2->getType() == SURFACELIST) {
2124
for(int j = 0; j < mesh->getSurfaces(); j++) {
2125
surface_t *surf = mesh->getSurface(j);
2126
if(surf->getIndex() == l2->getIndex()) {
2127
for(int k = 0; k < surf->getElements(); k++) {
2128
int l = surf->getElementIndex(k);
2129
if(l < 0)
2130
break;
2131
element_t *elem = mesh->getElement(l);
2132
if((elem->getIndex() < 0) || (elem->getIndex() >= n))
2133
break;
2134
nElement[elem->getIndex()]++;
2135
if(l2->isVisible())nVisibleElement[elem->getIndex()]++;
2136
}
2137
}
2138
}
2139
}
2140
}
2141
2142
double max = -1.0;
2143
int selected = -1;
2144
double visibility = -2.0;
2145
for(int i = 0; i < n; i++){
2146
if(tmp1[i] && nElement[i] > 0){
2147
visibility = ((double) nVisibleElement[i]) / nElement[i];
2148
//cout << i << " visibility=" << visibility << " (" << nVisibleElement[i] << "/" << nElement[i] << ")" << endl;
2149
if(visibility > max){
2150
max = visibility;
2151
selected = i;
2152
}
2153
}
2154
}
2155
delete[] nElement;
2156
delete[] nVisibleElement;
2157
//cout << "selected: " << selected << endl;
2158
return selected;
2159
}
2160
2161
#if WITH_QT6
2162
void GLWidget::updateGL()
2163
{
2164
update();
2165
}
2166
2167
2168
2169
/*
2170
Reference http://stackoverflow.com/questions/28216001/how-to-render-text-with-qopenglwidget/33674071#33674071
2171
*/
2172
void GLWidget::renderText(double x, double y, double z, const QString & str, const QFont & font/* = QFont()*/, int listBase /*= 2000*/)
2173
{
2174
int width = this->width();
2175
int height = this->height();
2176
2177
GLdouble model[4][4], proj[4][4];
2178
GLint view[4];
2179
glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]);
2180
glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]);
2181
glGetIntegerv(GL_VIEWPORT, &view[0]);
2182
GLdouble textPosX = 0, textPosY = 0, textPosZ = 0;
2183
2184
project(x, y, z,
2185
&model[0][0], &proj[0][0], &view[0],
2186
&textPosX, &textPosY, &textPosZ);
2187
2188
textPosY = height - textPosY; // y is inverted
2189
2190
QPainter painter(this);
2191
painter.setPen(Qt::black);
2192
painter.setFont(font);
2193
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
2194
painter.drawText(textPosX, textPosY, str); // z = pointT4.z + distOverOp / 4
2195
painter.end();
2196
}
2197
2198
inline GLint GLWidget::project(GLdouble objx, GLdouble objy, GLdouble objz,
2199
const GLdouble model[16], const GLdouble proj[16],
2200
const GLint viewport[4],
2201
GLdouble * winx, GLdouble * winy, GLdouble * winz)
2202
{
2203
GLdouble in[4], out[4];
2204
2205
in[0] = objx;
2206
in[1] = objy;
2207
in[2] = objz;
2208
in[3] = 1.0;
2209
transformPoint(out, model, in);
2210
transformPoint(in, proj, out);
2211
2212
if (in[3] == 0.0)
2213
return GL_FALSE;
2214
2215
in[0] /= in[3];
2216
in[1] /= in[3];
2217
in[2] /= in[3];
2218
2219
*winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
2220
*winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
2221
2222
*winz = (1 + in[2]) / 2;
2223
return GL_TRUE;
2224
}
2225
2226
inline void GLWidget::transformPoint(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
2227
{
2228
#define M(row,col) m[col*4+row]
2229
out[0] =
2230
M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
2231
out[1] =
2232
M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
2233
out[2] =
2234
M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
2235
out[3] =
2236
M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
2237
#undef M
2238
}
2239
2240
#endif
2241
2242