Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYPlanEauGraphic.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 "gui/gl/TYRenderContext.h"
24 #if _WIN32
25  #include <windows.h>
26 #endif //_WIN32
27 #include <GL/gl.h>
28 #include <GL/glu.h>
29 #include <QtOpenGL>
30 #include <qvector3d.h>
31 #include <vector>
32 
33 #include "TYPlanEauGraphic.h"
34 
36 
39 
41 #include "gui/gl/TYRenderContext.h"
42 #include "gui/tools/OGLArrayMesh.h"
45 
47  : TYElementGraphic(pElement), _pPolygonMesh(std::make_shared<OGLPolygonMesh>())
48 {
49  _pPolygon = new TYPolygon();
50 }
51 
52 void TYPlanEauGraphic::update(bool force /*=false*/)
53 {
55 }
56 
57 void TYPlanEauGraphic::getChilds(TYListPtrTYElementGraphic& childs, bool recursif /*=true*/)
58 {
59  TYElementGraphic* pTYElementGraphic = _pPolygon->getGraphicObject();
60  childs.push_back(pTYElementGraphic);
61  if (recursif)
62  {
63  pTYElementGraphic->getChilds(childs, recursif);
64  }
65 }
66 
68 {
69  if (!_visible)
70  {
71  return;
72  }
73 
74  TYElementGraphic::display(renderContext);
75 
76  TYTabPoint tabpoints = getElement()->getListPoints();
77 
78  // Ajout d'un offset pour limiter le flickering avec l'altimetrie
79  for (unsigned int i = 0; i < tabpoints.size(); i++)
80  {
81  tabpoints[i]._z += 0.5; // Anciennement 0.05
82  }
83 
84  _pPolygon->setPoints(tabpoints);
85 
86  if ((_highlight) && (renderContext.pass == TYRenderPass::Overlay))
87  {
88  drawName(renderContext);
89  }
90 
91  if (renderContext.type == TYRenderType::Picking)
92  {
93  TYPickingTable::addElement(getElement());
94  glPushName((GLuint)(TYPickingTable::getIndex()));
95 
96  glColor4fv(getElement()->getColor());
97 
98  _pPolygon->getGraphicObject()->display(renderContext);
99 
100  glPopName();
101  }
102 }
103 
104 // Store the vertices both as a QVector3D and as an array
105 // Both are used for different tesselator functions
107 {
108  QVector3D position;
109  double rawPosition[3];
110 };
111 
112 // Store the vertices of a primitive and their indices
114 {
115  GLenum type;
116  std::vector<QVector3D> vertices;
117  std::vector<unsigned int> indices;
118 };
119 
120 // Store the primitive and the vertices
122 {
123  std::vector<TesselatorPrimitive> primitives;
124  std::vector<TesselatorVertexData*> generatedVerticesData;
125 };
126 
127 void TYPlanEauGraphic::collectMeshInstances(std::vector<OGLMeshInstance>& meshInstances,
128  TYRenderContext* renderContext) const
129 {
130  if (renderContext == nullptr || renderContext->showLevelCurves)
131  {
132  TYTabPoint polygonVertices = getElement()->getListPoints();
133  polygonVertices.push_back(polygonVertices[0]);
134 
135  // Ajout d'un offset pour limiter le flickering avec l'altimetrie
136  for (unsigned int i = 0; i < polygonVertices.size(); i++)
137  {
138  polygonVertices[i]._z += 0.5; // Anciennement 0.05
139  }
140 
141  // Polygon tesselation. The following code relies on GLUTesselator to
142  // transform the polygon into a triangles soup.
143 
144  TesselatorPolygonData polygonData{std::vector<TesselatorPrimitive>(),
145  std::vector<TesselatorVertexData*>()};
146  GLUtesselator* tesselator = gluNewTess();
147 
148  // Add a new primitive to the tesselation state
149  auto beginCallback = +[](GLenum type, TesselatorPolygonData* polygonData)
150  { polygonData->primitives.emplace_back(TesselatorPrimitive{type}); };
151 
152  // Add a a new vertex to the current primitive
153  auto vertexDataCallback = +[](TesselatorVertexData* vertexData, TesselatorPolygonData* polygonData)
154  {
155  TesselatorPrimitive& primitive = polygonData->primitives.back();
156  primitive.vertices.emplace_back(vertexData->position);
157  unsigned int lastVertexIndex = primitive.vertices.size() - 1;
158 
159  if (primitive.type == GL_TRIANGLES)
160  {
161  primitive.indices.push_back(lastVertexIndex);
162  }
163  else if (primitive.type == GL_TRIANGLE_STRIP)
164  {
165  if (lastVertexIndex >= 2)
166  {
167  primitive.indices.push_back(lastVertexIndex - 2);
168  primitive.indices.push_back(lastVertexIndex - 1);
169  primitive.indices.push_back(lastVertexIndex);
170  }
171  }
172  else if (primitive.type == GL_TRIANGLE_FAN)
173  {
174  if (lastVertexIndex >= 2)
175  {
176  primitive.indices.push_back(0);
177  primitive.indices.push_back(lastVertexIndex - 1);
178  primitive.indices.push_back(lastVertexIndex);
179  }
180  }
181  };
182 
183  // Interpolate data on vertices generated by GLUTesselator
184  auto combineCallback = +[](GLdouble coords[3], TesselatorVertexData* vertexData[4], GLfloat weight[4],
185  TesselatorVertexData** outData, TesselatorPolygonData* polygonData)
186  {
187  TesselatorVertexData* outVertexData = new TesselatorVertexData();
188 
189  outVertexData->position = QVector3D(0, 0, 0);
190  for (int i = 0; i < 4; i++)
191  {
192  if (vertexData[i] != nullptr)
193  {
194  outVertexData->position += (weight[i] * vertexData[i]->position);
195  }
196  }
197  *outData = outVertexData;
198  polygonData->generatedVerticesData.push_back(outVertexData);
199  };
200 
201  gluTessCallback(tesselator, GLU_TESS_BEGIN_DATA, (void (*)())beginCallback);
202  gluTessCallback(tesselator, GLU_TESS_VERTEX_DATA, (void (*)())vertexDataCallback);
203  gluTessCallback(tesselator, GLU_TESS_COMBINE_DATA, (void (*)())combineCallback);
204 
205  gluTessBeginPolygon(tesselator, &polygonData);
206  gluTessBeginContour(tesselator);
207  std::vector<TesselatorVertexData> verticesData;
208  for (const auto& point : polygonVertices)
209  {
210  TesselatorVertexData& vertexData =
211  verticesData.emplace_back(TesselatorVertexData{QVector3D(point._x, point._y, point._z)});
212  vertexData.rawPosition[0] = point._x;
213  vertexData.rawPosition[1] = point._y;
214  vertexData.rawPosition[2] = point._z;
215  }
216  for (auto& vertexData : verticesData)
217  {
218  double position[3] = {vertexData.position.x(), vertexData.position.y(), vertexData.position.z()};
219  gluTessVertex(tesselator, position, &vertexData);
220  }
221  gluTessEndContour(tesselator);
222  gluTessEndPolygon(tesselator);
223 
224  gluDeleteTess(tesselator);
225  for (TesselatorVertexData* generatedVertexData : polygonData.generatedVerticesData)
226  {
227  delete generatedVertexData;
228  }
229 
230  std::vector<QVector3D> vertices;
231  std::vector<unsigned int> indices;
232  unsigned int indicesOffset = 0;
233 
234  // Merge all GL_TRIANGLES primitives into a single one
235  for (auto& primitive : polygonData.primitives)
236  {
237  vertices.insert(vertices.end(), primitive.vertices.begin(), primitive.vertices.end());
238  for (auto index : primitive.indices)
239  {
240  indices.push_back(indicesOffset + index);
241  }
242  indicesOffset += primitive.vertices.size();
243  }
244  _pPolygonMesh->setVertices(vertices);
245 
246  _pPolygonMesh->setIndices(indices);
247  _pPolygonMesh->material().color = getElement()->getColor();
248  meshInstances.emplace_back(_pPolygonMesh, globalMatrix());
249  }
250 }
std::vector< TYPoint > TYTabPoint
Collection de TYPoint.
Definition: TYDefines.h:340
list< TYElementGraphic * > TYListPtrTYElementGraphic
List de pointeur de TYElement.
Gestion de la table de correspondance indice/element pour le picking (fichier header)
Representation graphique d'un plan d'eau (fichier header)
void STDCALL beginCallback(GLenum which)
Contexte de rendu utilisé par les fonctions d'affichage.
@ Picking
The current render is only done for picking purpose.
@ Overlay
The current render pass is for overlay elements.
Bridges TY* types with CGAL functionalities exposed by.
classe graphique pour un element de base
void drawName(TYRenderContext &renderContext)
bool _visible
Inique si l'element est visible.
bool _highlight
Indique si le highlight est active pour cet element.
virtual void update(bool force=false)
virtual void getChilds(TYListPtrTYElementGraphic &childs, bool recursif=true)
virtual void display(TYRenderContext &renderContext)
QMatrix4x4 globalMatrix() const
static int getIndex()
static void addElement(TYElement *pElt)
LPTYPolygon _pPolygon
virtual void display(TYRenderContext &renderContext)
std::shared_ptr< OGLPolygonMesh > _pPolygonMesh
void collectMeshInstances(std::vector< OGLMeshInstance > &meshInstances, TYRenderContext *renderContext) const
virtual void update(bool force=false)
TYPlanEauGraphic(TYPlanEau *pElement)
virtual void getChilds(TYListPtrTYElementGraphic &childs, bool recursif=true)
void setPoints(const TYTabPoint &pts)
Definition: TYPolygon.cpp:389
TYRenderType type
TYRenderPass pass
std::vector< TesselatorPrimitive > primitives
std::vector< TesselatorVertexData * > generatedVerticesData
std::vector< QVector3D > vertices
std::vector< unsigned int > indices