Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYOpenGLRenderer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2024> <EDF-DTG> <FRANCE>
3  * This file is part of Code_TYMPAN (R).
4  * Code_TYMPAN (R) is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * Code_TYMPAN (R) is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * See the GNU General Public License for more details.
12  * You should have received a copy of the GNU General Public License along
13  * with Code_TYMPAN (R). If not, see <https://www.gnu.org/licenses/>.
14  */
15 
23 #include <memory>
24 #include <qmatrix4x4.h>
25 #include <qopenglbuffer.h>
26 #include <qopenglcontext.h>
27 #include <qopenglfunctions_4_3_core.h>
28 #include <qopenglshaderprogram.h>
29 #include <qopengltexture.h>
30 #include <qopenglvertexarrayobject.h>
31 #include <qtransform.h>
32 #include <qvector2d.h>
33 #include <qvector3d.h>
34 #include <stdexcept>
35 #include <vector>
36 
37 #include "TYOpenGLRenderer.h"
40 #include "gui/tools/OGLArrayMesh.h"
41 #include "gui/tools/OGLBoxMesh.h"
42 #include "gui/tools/OGLMesh.h"
47 
48 #if TY_USE_IHM
52  #include <QOpenGLFunctions_4_3_Core>
53 #endif
58 
59 void TYOpenGLRenderer::addBoundingBoxMeshInstances(std::vector<OGLMeshInstance>& meshInstances,
60  TYElementGraphic* element)
61 {
62  const OBox boundingBox = element->boundingBox();
63 
64  QMatrix4x4 globalMatrix = element->globalMatrix();
65  QMatrix4x4 bboxTranslation;
66  bboxTranslation.translate(QVector3D((boundingBox._min._x + boundingBox._max._x),
67  (boundingBox._min._y + boundingBox._max._y),
68  (boundingBox._min._z + boundingBox._max._z)) /
69  2);
70 
71  QVector3D bboxDimensions(boundingBox._max._x - boundingBox._min._x,
72  boundingBox._max._y - boundingBox._min._y,
73  boundingBox._max._z - boundingBox._min._z);
74  QMatrix4x4 modelMatrix = globalMatrix * bboxTranslation * _boundingBoxScaleMatrix;
75 
76  // Box mesh
77  std::shared_ptr<OGLMesh> bboxMesh = std::make_shared<OGLBoxMesh>(bboxDimensions);
78  bboxMesh->setMaterial(OGLSimpleMaterial::BOUNDING_BOX);
79  meshInstances.emplace_back(bboxMesh, modelMatrix);
80 
81  // Vertices mesh
82  std::shared_ptr<OGLArrayMesh> points = std::make_shared<OGLArrayMesh>();
83  points->fromMeshVertices(*bboxMesh);
84  points->setMaterial(OGLSimpleMaterial::BOUNDING_BOX);
85  meshInstances.emplace_back(points, modelMatrix);
86 }
87 
89  std::vector<OGLMeshInstance>& meshInstances,
90  TYRenderContext* renderContext)
91 {
92  if (elementGraphic != nullptr)
93  {
94  if (elementGraphic->getModified() && dynamic_cast<TYAltimetrieGraphic*>(elementGraphic) == nullptr)
95  {
96  elementGraphic->update();
97  }
98 
99  if (elementGraphic->isBoundingBoxVisible())
100  {
101  addBoundingBoxMeshInstances(meshInstances, elementGraphic);
102  }
103  bool showGeometry = true;
104  // Only test _visible value on high level graphic elements as its value is not consistent on children
105  if (dynamic_cast<TYSiteNodeGraphic*>(elementGraphic) != nullptr ||
106  dynamic_cast<TYAcousticVolumeNodeGraphic*>(elementGraphic) != nullptr ||
107  dynamic_cast<TYCourbeNiveauGraphic*>(elementGraphic) != nullptr ||
108  dynamic_cast<TYAcousticLineGraphic*>(elementGraphic) != nullptr ||
109  dynamic_cast<TYAltimetrieGraphic*>(elementGraphic) != nullptr)
110  {
111  showGeometry = elementGraphic->getVisible();
112  }
113 
114  elementGraphic->setVisible(showGeometry);
115 
116  if (showGeometry)
117  {
118  elementGraphic->collectMeshInstances(meshInstances, renderContext);
119  // recurse
120  TYListPtrTYElementGraphic children;
121  elementGraphic->getChilds(children, false);
122  for (auto child : children)
123  {
124  collectMeshInstances(child, meshInstances, renderContext);
125  }
126  }
127  }
128 }
129 
130 void drawMeshInstance(const OGLMeshInstance& meshInstance, QOpenGLShaderProgram* shaderProgram,
131  const QMatrix4x4& view, const QMatrix4x4& projection)
132 {
133  const OGLMesh& mesh = *meshInstance.mesh();
134  QOpenGLFunctions_4_3_Core gl;
135  gl.initializeOpenGLFunctions();
136 
137  QOpenGLVertexArrayObject vao;
138  vao.create();
139  vao.bind();
140 
141  // Bind position
142  QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer);
143  positionBuffer.create();
144  positionBuffer.bind();
145  positionBuffer.allocate(mesh.vertices().data(), mesh.vertices().size() * sizeof(QVector3D));
146 
147  int vertexLocation = shaderProgram->attributeLocation("vPosition");
148  shaderProgram->enableAttributeArray(vertexLocation);
149  shaderProgram->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, 0);
150 
151  // Bind vertices colors
152  QOpenGLBuffer colorsBuffer(QOpenGLBuffer::VertexBuffer);
153  int colorsLocation = shaderProgram->attributeLocation("vColor");
154  if (mesh.verticesColors().size() == mesh.vertices().size() * 4)
155  {
156  colorsBuffer.create();
157  colorsBuffer.bind();
158  colorsBuffer.allocate(mesh.verticesColors().data(), mesh.verticesColors().size() * sizeof(float));
159 
160  shaderProgram->enableAttributeArray(colorsLocation);
161  shaderProgram->setAttributeBuffer(colorsLocation, GL_FLOAT, 0, 4, 0);
162  }
163  else
164  {
165  shaderProgram->disableAttributeArray(colorsLocation);
166  shaderProgram->setAttributeValue(colorsLocation, mesh.material().color);
167  }
168 
169  // Bind texture coordinates
170  QOpenGLBuffer textureCoordinatesBuffer(QOpenGLBuffer::VertexBuffer);
171  int textureCoordinatesLocation = shaderProgram->attributeLocation("vTextureCoordinates");
172  if (mesh.textureCoordinates().size() == mesh.vertices().size())
173  {
174  textureCoordinatesBuffer.create();
175  textureCoordinatesBuffer.bind();
176  textureCoordinatesBuffer.allocate(mesh.textureCoordinates().data(),
177  mesh.textureCoordinates().size() * sizeof(QVector2D));
178 
179  shaderProgram->enableAttributeArray(textureCoordinatesLocation);
180  shaderProgram->setAttributeBuffer(textureCoordinatesLocation, GL_FLOAT, 0, 2, 0);
181  }
182  else
183  {
184  shaderProgram->disableAttributeArray(textureCoordinatesLocation);
185  shaderProgram->setAttributeValue(textureCoordinatesLocation, QVector2D(0.5, 0.5));
186  }
187 
188  // Bind texture coordinates
189  QOpenGLBuffer normalBuffer(QOpenGLBuffer::VertexBuffer);
190  int normalLocation = shaderProgram->attributeLocation("vNormal");
191  if (mesh.normals().size() == mesh.vertices().size())
192  {
193  normalBuffer.create();
194  normalBuffer.bind();
195  normalBuffer.allocate(mesh.normals().data(), mesh.normals().size() * sizeof(QVector3D));
196 
197  shaderProgram->enableAttributeArray(normalLocation);
198  shaderProgram->setAttributeBuffer(normalLocation, GL_FLOAT, 0, 3, 0);
199  }
200  else
201  {
202  shaderProgram->disableAttributeArray(normalLocation);
203  shaderProgram->setAttributeValue(normalLocation, QVector3D(0.0, 0.0, 1.0));
204  }
205 
206  int modelLocation = shaderProgram->uniformLocation("uModel");
207  shaderProgram->setUniformValue(modelLocation, meshInstance.globalMatrix());
208  int viewLocation = shaderProgram->uniformLocation("uView");
209  shaderProgram->setUniformValue(viewLocation, view);
210  int projectionLocation = shaderProgram->uniformLocation("uProjection");
211  shaderProgram->setUniformValue(projectionLocation, projection);
212 
213  int textureBlendLocation = shaderProgram->uniformLocation("uTextureBlend");
214  shaderProgram->setUniformValue(textureBlendLocation, (GLuint)mesh.material().textureBlend);
215 
216  int lightingModeLocation = shaderProgram->uniformLocation("uLightingMode");
217  shaderProgram->setUniformValue(lightingModeLocation, (GLuint)mesh.material().lightingMode);
218 
219  int texLocation = shaderProgram->uniformLocation("uTexture");
220  auto image = mesh.material().image;
221  auto textureManager = OGLTextureManager::instance(QOpenGLContext::currentContext());
222  auto texture = image == nullptr ? textureManager->whiteTexture() : textureManager->getTexture(image);
223  texture->bind(0);
224  shaderProgram->setUniformValue(texLocation, 0);
225 
226  QOpenGLBuffer indexBuffer(QOpenGLBuffer::IndexBuffer);
227  indexBuffer.create();
228  indexBuffer.bind();
229  indexBuffer.allocate(mesh.indices().data(), mesh.indices().size() * sizeof(unsigned int));
230 
231  switch (meshInstance.mesh()->primitiveType())
232  {
234  glDrawElements(GL_LINES, mesh.indices().size(), GL_UNSIGNED_INT, 0);
235  break;
237  glDrawElements(GL_LINE_STRIP, mesh.indices().size(), GL_UNSIGNED_INT, 0);
238  break;
240  glDrawElements(GL_LINE_LOOP, mesh.indices().size(), GL_UNSIGNED_INT, 0);
241  break;
243  glDrawElements(GL_POINTS, mesh.indices().size(), GL_UNSIGNED_INT, 0);
244  break;
246  glDrawElements(GL_TRIANGLES, mesh.indices().size(), GL_UNSIGNED_INT, 0);
247  break;
249 
250  glDrawElements(GL_QUADS, mesh.indices().size(), GL_UNSIGNED_INT, 0);
251  break;
252  }
253  gl.glBindTexture(GL_TEXTURE_2D, 0);
254 
255  indexBuffer.destroy();
256 
257  if (mesh.normals().size() == mesh.vertices().size())
258  {
259  normalBuffer.destroy();
260  }
261  if (mesh.textureCoordinates().size() == mesh.vertices().size())
262  {
263  textureCoordinatesBuffer.destroy();
264  }
265  positionBuffer.release(QOpenGLBuffer::VertexBuffer);
266  positionBuffer.destroy();
267 
268  vao.release();
269  vao.destroy();
270 }
271 
273 {
274  _displayList = 0; // az++
275  _displayListOverlay = 0; // az++
276  _pActiveCamera = nullptr;
277  _pBackgroundColor = new double[3];
278  m_renderType = 0;
280 
281  _boundingBoxScaleMatrix = QMatrix4x4();
282  _boundingBoxScaleMatrix.scale(1.1);
283 }
284 
286 {
287  if (_displayList) // az++
288  {
289  glDeleteLists(_displayList, 1);
290  }
291  if (_displayListOverlay) // az++
292  {
293  glDeleteLists(_displayListOverlay, 1);
294  }
295  delete[] _pBackgroundColor;
296 }
297 
299 {
300  _displayList = glGenLists(1);
301  _displayListOverlay = glGenLists(1);
302 }
303 
305 {
306  // glClearColor(1.0, 1.0, 1.0, 1.0);
307  glClearColor(_pBackgroundColor[0], _pBackgroundColor[1], _pBackgroundColor[2], 1.0);
308  glColor3f(1.0, 0.0, 0.0);
309 
311  {
312  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
313  }
315  {
316  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
317  }
319  {
320  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
321  }
323  {
324  glShadeModel(GL_FLAT);
325  }
327  {
328  glShadeModel(GL_SMOOTH);
329  }
330 
331  // Lights
332  glEnable(GL_LIGHTING);
333  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
334 
335  static GLfloat ambient[] = {0.1f, 0.1f, 0.1f, 1.0f};
336  static GLfloat ambientBIS[] = {0.8f, 0.8f, 0.8f, 0.8f};
337  static GLfloat diffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
338  static GLfloat specular[] = {0.8f, 0.8f, 0.8f, 1.0f};
339  static GLfloat shininess = 50.;
340  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientBIS);
341  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
342  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
343  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
344  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
345 
346  glMatrixMode(GL_PROJECTION);
347  glLoadIdentity();
348 }
349 
351 {
352  _renderMode = mode;
353 }
354 
356 {
357  return _renderMode;
358 }
359 
361  TYGeometryNode* pDansCeRepere)
362 {
363  if (pElement)
364  {
365  // Chercher le GeoNode correspondant a pElement (le repere dans lequel est exprime pElement)
366  TYGeometryNode* pGeoNode = pElement;
367  if (pElement->isA("TYGeometryNode"))
368  {
369  pGeoNode = (TYGeometryNode*)pElement;
370  }
371  else
372  {
373  pGeoNode = (TYGeometryNode*)pElement->GetGeoNodeParent();
374  }
375 
376  if (pGeoNode)
377  {
378  LPTYElementGraphic pTYElementGraphic = pGeoNode->getGraphicObject();
379  TYGeometryNodeGraphic* pGeoNodeGraphic =
380  (TYGeometryNodeGraphic*)pTYElementGraphic.getRealPointer();
381  pGeoNodeGraphic->displayPushingParentMatrix(renderContext, pDansCeRepere);
382  }
383  }
384 }
385 
387 {
389 }
390 
392 {
393  if (!_sceneRenderCacheIsDirty) // az++
394  {
395  glCallList(_displayList);
396  return;
397  }
398  else
399  {
400  // Affectation de la displayList principale:
401  glNewList(_displayList, GL_COMPILE_AND_EXECUTE);
402  drawElement(renderContext);
403  glEndList();
404  _sceneRenderCacheIsDirty = false;
405  }
406 }
407 
408 void TYOpenGLRenderer::OpenGLRender(TYRenderContext& renderContext, int x /* = 0*/, int y /* = 0*/)
409 {
410  GLint polygon_mode[2];
411  glGetIntegerv(GL_POLYGON_MODE, polygon_mode);
412 
413  // do the render library specific stuff
414  const OGLCamera* currentCamera = renderContext.viewport.camera();
415  if (currentCamera)
416  {
417  glMatrixMode(GL_PROJECTION);
418  glLoadMatrixf(currentCamera->projectionMatrix().constData());
419  glMatrixMode(GL_MODELVIEW);
420  glLoadMatrixf(currentCamera->viewMatrix().constData());
421  }
422 
423  // set matrix mode for actors
424  glMatrixMode(GL_MODELVIEW);
425 
426  // Gestion des lumieres
427  if (currentCamera)
428  {
429  // place la lumiere 0 sur la camera
430  double xc, yc, zc;
431  currentCamera->getPosition(xc, yc, zc);
432  _tabLights[0]->setPosition(OPoint3D(xc, yc, zc));
433  }
434  for (int il = 0; il < _tabLights.size(); il++)
435  {
436  _tabLights[il]->render();
437  }
438 
439  // Materials
440  float colorSpec[] = {0.0, 0.0, 0.0, 1.0};
441  float colorShine[] = {127.0};
442  glMaterialfv(GL_FRONT, GL_SPECULAR, colorSpec);
443  glMaterialfv(GL_FRONT, GL_SHININESS, colorShine);
444  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
445  glEnable(GL_COLOR_MATERIAL);
446 
447  // Antialiasing
448  glEnable(GL_MULTISAMPLE);
449  glEnable(GL_BLEND);
450  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
451 
452  glEnable(GL_NORMALIZE);
453  glEnable(GL_DEPTH_TEST);
454  glDepthRange(0, 1);
455 
456  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
457 
458  if (renderContext.type == TYRenderType::Picking)
459  {
460  GLint viewport[4];
461  GLfloat proj[16];
462 
463  glGetFloatv(GL_PROJECTION_MATRIX, proj);
464 
465  glGetIntegerv(GL_VIEWPORT, viewport);
466 
467  glMatrixMode(GL_PROJECTION);
468  glPushMatrix();
469  glLoadIdentity();
470  gluPickMatrix((GLdouble)x, (GLdouble)y, 5, 5, viewport);
471  glMultMatrixf(proj);
472 
473  glMatrixMode(GL_MODELVIEW);
474  glPushMatrix();
475  drawElement(renderContext);
476  glPopMatrix();
477  glMatrixMode(GL_PROJECTION);
478  glPopMatrix();
479  }
480  else /* renderType == TYOpenGLRenderer::DisplayRenderer */
481  {
482  // CLM-NT35: Init la liste avant d'ajouter les elements
483  // display overlay text for selected elements (localized)
484 
485  renderContext.pass = TYRenderPass::Overlay;
486 
487  glNewList(_displayListOverlay, GL_COMPILE);
488  std::vector<TYElement*>::iterator iterElements;
489  for (iterElements = _tabSelectedElements.begin(); iterElements < _tabSelectedElements.end();
490  iterElements++)
491  {
492  TYGeometryNode* pGeoNode = TYGeometryNode::GetGeoNode(*iterElements);
493  TYGeometryNode* pRootGeometryNode = TYGeometryNode::GetGeoNode(renderContext.modelerElement);
494  // For elements without GeoNode like TYPointControl, display in GL_COMPILE mode the
495  // correponding graphic object
496  if (!pGeoNode)
497  {
498  if (*iterElements != nullptr)
499  {
500  LPTYElementGraphic pTYElementGraphic = (*iterElements)->getGraphicObject();
501  if (pTYElementGraphic != nullptr)
502  {
503  pTYElementGraphic->display(renderContext);
504  }
505  }
506  }
507  updateDisplayListOverlay(renderContext, pGeoNode, pRootGeometryNode);
508  }
509  glEndList();
510  renderContext.pass = TYRenderPass::Default;
511  }
512 
513  glMatrixMode(GL_MODELVIEW);
514  if (renderContext.type == TYRenderType::Display)
515  {
516  // Render mesh instances (new pipeline)
517  std::vector<OGLMeshInstance> meshInstances;
518  if (renderContext.modelerElement != nullptr)
519  {
520  std::vector<OGLMeshInstance> meshInstancesInProjectSpace;
521  collectMeshInstances(renderContext.modelerElement->getGraphicObject().getRealPointer(),
522  meshInstancesInProjectSpace, &renderContext);
523  std::vector<OGLMeshInstance> meshInstancesInModelerSpace;
524  for (auto& meshInstance : meshInstancesInProjectSpace)
525  {
526  meshInstances.emplace_back(meshInstance.mesh(),
527  renderContext.globalToModelerMatrix * meshInstance.globalMatrix());
528  }
529  }
530  drawMeshInstances(renderContext, meshInstances);
531  glPushMatrix();
532  _renderScene(renderContext);
533  glCallList(_displayListOverlay);
534  glPopMatrix();
535  }
536 
537  // render the TYAtcor2D list
538  glDisable(GL_LIGHTING);
539  std::vector<OGLElement*>::iterator iter;
540  for (iter = _tabOGLElement.begin(); iter < _tabOGLElement.end(); iter++)
541  {
542  glPushMatrix();
543  (*iter)->render();
544  glPopMatrix();
545  }
546 
547  glPolygonMode(GL_FRONT_AND_BACK, polygon_mode[0]);
548 }
549 
551 {
552  LPTYElementGraphic pGraphObj = NULL;
553  if (renderContext.modelerElement)
554  {
555  pGraphObj = renderContext.modelerElement->getGraphicObject();
556 
557  if (dynamic_cast<TYAltimetrieGraphic*>(pGraphObj.getRealPointer()) != nullptr)
558  {
559  std::vector<OGLMeshInstance> meshInstances = {};
560  pGraphObj->collectMeshInstances(meshInstances, &renderContext);
561  }
562 
563  if (dynamic_cast<TYSiteNode*>(renderContext.modelerElement) != nullptr)
564  {
565  TYElement* pParent = renderContext.modelerElement->getParent();
566  if (pParent && pParent->isA("TYProjet"))
567  {
568  pGraphObj = pParent->getGraphicObject();
569  }
570  }
571 
572  glRotatef(-90.0, 1.0, 0.0, 0.0);
573  if (pGraphObj)
574  {
575  pGraphObj->display(renderContext);
576  }
577  }
578 }
579 
581 {
582  bool _bFinded = false;
583  std::vector<OGLElement*>::iterator iter;
584  for (iter = _tabOGLElement.begin(); !_bFinded && (iter < _tabOGLElement.end()); iter++)
585  {
586  if ((OGLElement*)(*iter) == pOGLElement)
587  {
588  _bFinded = true;
589  }
590  }
591  if (!_bFinded)
592  {
593  _tabOGLElement.push_back(pOGLElement);
594  }
595 }
596 
598 {
599  _tabLights.push_back(pOGLElement);
600 }
601 
603 {
604  _tabLights.clear();
605 }
606 
607 std::vector<OGLLightElement*> TYOpenGLRenderer::getLights()
608 {
609  return _tabLights;
610 }
611 
613 {
614  std::vector<OGLElement*>::iterator iter;
615  bool _bFinded = false;
616  for (iter = _tabOGLElement.begin(); !_bFinded && (iter < _tabOGLElement.end()); iter++)
617  {
618  if ((OGLElement*)(*iter) == pOGLElement)
619  {
620  _bFinded = true;
621  _tabOGLElement.erase(iter);
622  break;
623  }
624  }
625 }
626 
628 {
629  bool _bFinded = false;
630  std::vector<TYElement*>::iterator iter;
631  for (iter = _tabSelectedElements.begin(); !_bFinded && (iter < _tabSelectedElements.end()); iter++)
632  {
633  if ((TYElement*)(*iter) == pElement)
634  {
635  _bFinded = true;
636  }
637  }
638  if (!_bFinded)
639  {
640  _tabSelectedElements.push_back(pElement);
641  }
642 }
643 
645 {
646  std::vector<TYElement*>::iterator iter;
647  bool _bFinded = false;
648  for (iter = _tabSelectedElements.begin(); !_bFinded && (iter < _tabSelectedElements.end()); iter++)
649  {
650  if ((TYElement*)(*iter) == pElement)
651  {
652  _bFinded = true;
653  _tabSelectedElements.erase(iter);
654  break;
655  }
656  }
657 }
658 
660 {
661  _tabSelectedElements.clear();
662 }
663 
664 void gluPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay, GLint viewport[4])
665 {
666  if (deltax <= 0 || deltay <= 0)
667  {
668  return;
669  }
670 
671  /* Translate and scale the picked region to the entire window */
672  glTranslated((viewport[2] - 2 * (x - viewport[0])) / deltax,
673  (viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
674  glScaled(viewport[2] / deltax, viewport[3] / deltay, 1.0);
675 }
676 
678  const std::vector<OGLMeshInstance>& meshInstances) const
679 {
680  auto camera = renderContext.viewport.camera();
681  QMatrix4x4 viewMatrix = camera->viewMatrix();
682  // TODO: Tympan coordinate system is RHS with Z-up while camera is operated as if
683  // Y was UP. Rotating the view matrix before rendering fixes it (the same
684  // hack is used both in interactions and with legacy render pipeline).
685  viewMatrix.rotate(90, -1, 0, 0);
686 
687  QMatrix4x4 projectionMatrix = camera->projectionMatrix();
688 
689  // >>> Extraction cam en espace monde à partir de viewMatrix <<<
690  bool ok = false;
691  QMatrix4x4 invView = viewMatrix.inverted(&ok);
692  // position caméra = C * (0,0,0,1)
693  const QVector3D camPosWS = invView.map(QVector3D(0.0f, 0.0f, 0.0f));
694  // direction avant caméra = C * (0,0,-1,0) (vecteur)
695  QVector3D camFwdWS = invView.mapVector(QVector3D(0.0f, 0.0f, -1.0f));
696  camFwdWS.normalize();
697 
698  // Dans Tympan, le monde est RHS avec Z-up => "vers le bas" = -Z
699  const QVector3D downDirWS(0.0f, 0.0f, -1.0f);
700 
701  QOpenGLShaderProgram* shaderProgram = OGLShaderManager::instance(QOpenGLContext::currentContext())
703  shaderProgram->bind();
704 
705  // Position et et direction avant caméra
706  shaderProgram->setUniformValue("uCamPosWS", camPosWS);
707  shaderProgram->setUniformValue("uCamFwdWS", camFwdWS);
708 
709  // Ambiant & matériau
710  shaderProgram->setUniformValue("uGlobalAmbient", QVector3D(0.8f, 0.8f, 0.8f));
711  shaderProgram->setUniformValue("uKa", 0.8f);
712  shaderProgram->setUniformValue("uKd", 0.8f);
713  shaderProgram->setUniformValue("uKsDown", 0.0f);
714  shaderProgram->setUniformValue("uKsHeadlight", 0.0f); // coupe le hotspot
715  shaderProgram->setUniformValue("uShininess", 50.0f);
716 
717  // Directions & gains
718  shaderProgram->setUniformValue("uDownDirWS", QVector3D(0.0f, 0.0f, -1.0f)); // rayons vers le bas
719  shaderProgram->setUniformValue("uDownIntensity", 1.0f);
720  shaderProgram->setUniformValue("uHeadlightIntensity", 1.0f);
721 
722  // Headlight adoucie + remplissage
723  shaderProgram->setUniformValue("uCamWrap", 0.0f); // 0 = Lambert ; 0.4–0.7 adoucit la chute
724  shaderProgram->setUniformValue("uCamPointWeight", 0.0f); // 0 = dir ; 1 = point
725  shaderProgram->setUniformValue("uGrazingFill", 0.0f); // 0.08–0.20
726  shaderProgram->setUniformValue("uHeadlightFloor", 0.0f); // 0.05–0.20
727 
728  for (const OGLMeshInstance& meshInstance : meshInstances)
729  {
730  if (meshInstance.mesh()->primitiveType() == OGLPrivimitiveType::Quads &&
732  {
733  std::shared_ptr<OGLArrayMesh> lineMesh = std::make_shared<OGLArrayMesh>();
734  lineMesh->material() = meshInstance.mesh()->material();
735  lineMesh->fromQuadMeshEdges(*meshInstance.mesh());
736  OGLMeshInstance lineMeshInstance(lineMesh, meshInstance.globalMatrix());
737  drawMeshInstance(lineMeshInstance, shaderProgram, viewMatrix, projectionMatrix);
738  }
739  else
740  {
741  drawMeshInstance(meshInstance, shaderProgram, viewMatrix, projectionMatrix);
742  }
743  }
744  shaderProgram->release();
745 }
Gestionnaire de textures.
Representation graphique d'un ensemble de volumes acoustiques (fichier header)
Representation graphique de l'altimetrie (fichier header)
Representation graphique d'une courbe de niveau (fichier header)
Representation graphique d'un element de base (fichier header)
list< TYElementGraphic * > TYListPtrTYElementGraphic
List de pointeur de TYElement.
Representation graphique d'un GeometryNode (fichier header)
void gluPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay, GLint viewport[4])
void drawMeshInstance(const OGLMeshInstance &meshInstance, QOpenGLShaderProgram *shaderProgram, const QMatrix4x4 &view, const QMatrix4x4 &projection)
Realise le rendu VTK et le rendu OpenGL (fichier header)
Contexte de rendu utilisé par les fonctions d'affichage.
@ Display
The current render is intended to be displayed on screen.
@ Picking
The current render is only done for picking purpose.
@ Overlay
The current render pass is for overlay elements.
@ Default
The current render pass is for 3D elements.
Representation graphique d'un reseau electrique (fichier header)
Representation graphique d'un ensemble de sites (fichier header)
The box class.
Definition: 3d.h:1346
OPoint3D _min
Minimal coordinates of the OBox.
Definition: 3d.h:1423
OPoint3D _max
Maximal coordinates of the OBox.
Definition: 3d.h:1424
double _y
y coordinate of OCoord3D
Definition: 3d.h:283
double _z
z coordinate of OCoord3D
Definition: 3d.h:284
double _x
x coordinate of OCoord3D
Definition: 3d.h:282
void getPosition(double &x, double &y, double &z) const
Definition: OGLCamera.cpp:481
const QMatrix4x4 & projectionMatrix() const
Definition: OGLCamera.cpp:567
const QMatrix4x4 & viewMatrix() const
Definition: OGLCamera.cpp:558
const QMatrix4x4 & globalMatrix() const
std::shared_ptr< const OGLMesh > mesh() const
const std::vector< unsigned int > & indices() const
Definition: OGLMesh.cpp:40
const std::vector< QVector3D > & normals() const
Definition: OGLMesh.cpp:30
const std::vector< QVector3D > & vertices() const
Definition: OGLMesh.cpp:20
const std::vector< QVector2D > & textureCoordinates() const
Definition: OGLMesh.cpp:35
OGLSimpleMaterial & material()
Definition: OGLMesh.cpp:50
const std::vector< float > & verticesColors() const
Definition: OGLMesh.cpp:25
static OGLShaderManager * instance(QOpenGLContext *context)
QOpenGLShaderProgram * getShaderProgram(ShaderId shaderId)
TextureBlend textureBlend
LightingMode lightingMode
static OGLSimpleMaterial BOUNDING_BOX
std::shared_ptr< QImage > image
static OGLTextureManager * instance(QOpenGLContext *context)
The 3D point class.
Definition: 3d.h:487
bool isA(const char *className) const
Definition: TYElement.cpp:65
T * getRealPointer()
Definition: smartptr.h:291
classe graphique pour une ligne acoustique
classe graphique pour un ensemble de volumes acoustiques
classe graphique pour une altimetrie
classe graphique pour une courbe de niveau
classe graphique pour un element de base
OBox boundingBox() const
virtual void update(bool force=false)
bool isBoundingBoxVisible() const
virtual void getChilds(TYListPtrTYElementGraphic &childs, bool recursif=true)
virtual void display(TYRenderContext &renderContext)
QMatrix4x4 globalMatrix() const
bool getModified() const
virtual void collectMeshInstances(std::vector< OGLMeshInstance > &meshInstances, TYRenderContext *renderContext) const
void setVisible(bool visible=true)
bool getVisible() const
TYElement * getParent() const
Definition: TYElement.h:697
classe graphique pour un GeometryNode
void displayPushingParentMatrix(TYRenderContext &renderContext, TYGeometryNode *pDansCeRepere)
TYGeometryNode * GetGeoNodeParent() const
static TYGeometryNode * GetGeoNode(TYElement *pElement)
std::vector< TYElement * > _tabSelectedElements
Elements selectionnes.
void _renderScene(TYRenderContext &renderContext) const
0 --> render all, 1 --> render 2D, 2 --> render 3D
void removeSelectedElement(TYElement *pElement)
void addLight(OGLLightElement *pOGLElementLight)
void addOGLElement(OGLElement *pOGLElement)
void invalidateScene(void)
void removeOGLElement(OGLElement *pOGLElement)
std::vector< OGLLightElement * > _tabLights
Liste des lumieres dans la scene 3D.
void collectMeshInstances(TYElementGraphic *elementGraphic, std::vector< OGLMeshInstance > &meshInstances, TYRenderContext *renderContext)
QMatrix4x4 _boundingBoxScaleMatrix
GLuint _displayList
Display liste globale.
void addBoundingBoxMeshInstances(std::vector< OGLMeshInstance > &meshInstances, TYElementGraphic *element)
RenderMode _renderMode
Mode de rendu.
OGLCamera * _pActiveCamera
void updateDisplayListOverlay(TYRenderContext &renderContext, TYGeometryNode *pElement, TYGeometryNode *pDansCeRepere)
std::vector< OGLElement * > _tabOGLElement
void setRenderMode(RenderMode mode)
double * _pBackgroundColor
std::vector< OGLLightElement * > getLights()
void drawMeshInstances(TYRenderContext &renderContext, const std::vector< OGLMeshInstance > &meshInstances) const
GLuint _displayListOverlay
Display liste pour les deplacements.
void drawElement(TYRenderContext &renderContext) const
RenderMode getRenderMode()
void OpenGLRender(TYRenderContext &renderContext, int x=0, int y=0)
void addSelectedElement(TYElement *pElement)
TYRenderViewport viewport
TYElement * modelerElement
TYRenderType type
TYRenderPass pass
QMatrix4x4 globalToModelerMatrix
const OGLCamera * camera() const
clase graphique pour un ensemble de sites