GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_extrudedmesh.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2013 Laurent Ribon (laumaya@users.sourceforge.net)
5  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib 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 Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 *****************************************************************************/
22 
24 
25 #include <QtDebug>
26 
27 #include "glc_extrudedmesh.h"
28 #include "../maths/glc_plane.h"
29 #include "../maths/glc_geomtools.h"
30 
31 // Class chunk id
32 quint32 GLC_ExtrudedMesh::m_ChunkId= 0xA712;
33 
34 GLC_ExtrudedMesh::GLC_ExtrudedMesh(const QList<GLC_Point3d> &points, const GLC_Vector3d &dir, double lenght)
35  :GLC_Mesh()
36  , m_Points(points)
37  , m_ExtrusionVector(GLC_Vector3d(dir).normalize())
38  , m_ExtrusionLenght(lenght)
39  , m_GivenFaceNormal()
40 {
41  Q_ASSERT(m_Points.size() > 2);
42  Q_ASSERT(pointsLieOnAPlane());
43  Q_ASSERT(!glc::compare(m_Points.first(), m_Points.last(), glc::EPSILON));
44 
47 }
48 
50  :GLC_Mesh(other)
51  , m_Points(other.m_Points)
52  , m_ExtrusionVector(other.m_ExtrusionVector)
53  , m_ExtrusionLenght(other.m_ExtrusionLenght)
54  , m_GivenFaceNormal(other.m_GivenFaceNormal)
55 {
56  if (GLC_Mesh::isEmpty())
57  {
59  }
60 }
61 
63 {
64 
65 }
66 
68 {
69  return m_ChunkId;
70 }
71 
73 {
74  return new GLC_ExtrudedMesh(*this);
75 }
76 
78 {
79  if (GLC_Mesh::isEmpty())
80  {
82  }
83  return GLC_Mesh::boundingBox();
84 }
85 
87 {
88  if (this != &other)
89  {
90  GLC_Mesh::operator =(other);
91  m_Points= other.m_Points;
95  }
96 
97  return *this;
98 }
99 
100 void GLC_ExtrudedMesh::setGeometry(const QList<GLC_Point3d> &points, const GLC_Vector3d &extrudedVector, double lenght)
101 {
102  m_Points= points;
103  m_ExtrusionVector= extrudedVector;
104  m_ExtrusionLenght= lenght;
105 
108 }
109 
110 void GLC_ExtrudedMesh::setPoints(const QList<GLC_Point3d> &points)
111 {
112  m_Points= points;
113 
116 }
117 
119 {
120  m_ExtrusionVector= extrudedVector;
121 
124 }
125 
127 {
128  m_ExtrusionLenght= lenght;
129 
132 }
133 
135 {
136  Q_ASSERT(GLC_Mesh::isEmpty());
137  Q_ASSERT(m_WireData.isEmpty());
138 
139  createMesh();
140  createWire();
141 
142  finish();
143 }
144 
146 {
147  // Bulk data
148  GLfloatVector vertices;
149  GLfloatVector normals;
151  GLC_Mesh::addTexels(texels);
152 
153  // Set the material to use
154  GLC_Material* pMaterial;
155  if (hasMaterial()) pMaterial= this->firstMaterial();
156  else pMaterial= new GLC_Material();
157 
158  {
159  // Given face (Face 1)
160  GLfloatVector face1Vertices= baseFaceVertices();
161  GLfloatVector face1Normals= baseFaceNormals();
162  IndexList face1Index;
163  const GLuint count= m_Points.count();
164  for (GLuint i= 0; i < (count + 1); ++i)
165  {
166  face1Index.append(i % count);
167  }
168  vertices+= face1Vertices;
169  normals+= face1Normals;
170  Q_ASSERT(vertices.size() == normals.size());
171  glc::triangulatePolygon(&face1Index, vertices.toList());
172  addTriangles(pMaterial, face1Index);
173  }
174 
175  {
176  // Created face (Face2)
177  GLfloatVector face2Vertices= createdFaceVertices();
178  GLfloatVector face2Normals= createdFaceNormals();
179  IndexList face2Index;
180  const int offset= vertices.size() / 3;
181  const GLuint count= m_Points.count();
182  for (GLuint i= 0; i < (count + 1); ++i)
183  {
184  face2Index.append(offset + (i % count));
185  }
186  vertices+= face2Vertices;
187  normals+= face2Normals;
188  Q_ASSERT(vertices.size() == normals.size());
189  glc::triangulatePolygon(&face2Index, vertices.toList());
190  addTriangles(pMaterial, face2Index);
191  }
192 
193 
194  {
195  // Add outline faces
196  const GLuint count= m_Points.count();
197  GLuint offset1= vertices.size() / 3;
198  GLfloatVector facesNormals= baseOutlineNormals();
199  GLuint indexLenght= (facesNormals.size() / 3);
200  GLuint offset2= offset1 + indexLenght;
201  facesNormals= facesNormals + createdOutlineNormals();
203  vertices+= facesVertices;
204  normals+= facesNormals;
205 
206  for (GLuint face= 0; face < count; ++face)
207  {
208  IndexList faceIndex;
209  GLuint startIndex1= offset1 + (face * 2);
210  GLuint startIndex2= offset2 + (indexLenght -1) - (face * 2);
211  faceIndex << startIndex1 << startIndex2 << (startIndex1 + 1) << (startIndex2 - 1);
212  addTrianglesStrip(pMaterial, faceIndex);
213  }
214  }
215 
216  // Add bulk data in to the mesh
217  GLC_Mesh::addVertice(vertices);
218  GLC_Mesh::addNormals(normals);
219 
220 }
221 
223 {
224  GLfloatVector baseFaceWire= baseFaceVertices();
225  baseFaceWire << baseFaceWire.at(0) << baseFaceWire.at(1) << baseFaceWire.at(2);
226  GLC_Geometry::addVerticeGroup(baseFaceWire);
227 
228  GLfloatVector createdFaceWire= createdFaceVertices();
229  createdFaceWire << createdFaceWire.at(0) << createdFaceWire.at(1) << createdFaceWire.at(2);
230  GLC_Geometry::addVerticeGroup(createdFaceWire);
231 
232  // Outline edges
233  const int count= m_Points.count();
234  for (int i= 0; i < count; ++i)
235  {
236  GLfloatVector edge(6); // the edge is a line
237  edge[0]= baseFaceWire.at(i * 3);
238  edge[1]= baseFaceWire.at(i * 3 + 1);
239  edge[2]= baseFaceWire.at(i * 3 + 2);
240 
241  edge[3]= createdFaceWire.at(((count - i) % count) * 3);
242  edge[4]= createdFaceWire.at(((count - i) % count) * 3 + 1);
243  edge[5]= createdFaceWire.at(((count - i) % count) * 3 + 2);
244 
246  }
247 }
248 
250 {
251  Q_ASSERT(m_Points.count() > 2);
252 
253  const GLC_Vector3d edge1(GLC_Vector3d(m_Points.at(1) - m_Points.at(0)).normalize());
254  const GLC_Vector3d edge2(GLC_Vector3d(m_Points.at(2) - m_Points.at(1)).normalize());
255 
256  m_GivenFaceNormal= edge1 ^ edge2;
257 }
258 
260 {
261  bool subject= true;
262  const int count= m_Points.count();
263  Q_ASSERT(count > 2);
264  if (count > 3)
265  {
266  // Create a plane on the first 3 points
267  GLC_Plane plane(m_Points.at(0), m_Points.at(1), m_Points.at(2));
268 
269  // Check if others points lie on the plane
270  for (int i= 3; i < count; ++i)
271  {
272  subject= plane.lieOnThisPlane(m_Points.at(i));
273  if (!subject) break;
274  }
275  }
276 
277  return subject;
278 }
279 
281 {
282  const int count= m_Points.count();
283  GLfloatVector subject(count * 6); // 2 normals by vertex and 3 components pear normal => 6
284  for (int i= 0; i < count; ++i)
285  {
286  GLC_Vector3d vect(m_Points.at((i + 1) % count) - m_Points.at(i));
288 
289  // First segment point
290  subject[(6 * i)]= static_cast<GLfloat>(normal.x());
291  subject[(6 * i) + 1]= static_cast<GLfloat>(normal.y());
292  subject[(6 * i) + 2]= static_cast<GLfloat>(normal.z());
293 
294  // Second segment point
295  subject[(6 * i) + 3]= static_cast<GLfloat>(normal.x());
296  subject[(6 * i) + 4]= static_cast<GLfloat>(normal.y());
297  subject[(6 * i) + 5]= static_cast<GLfloat>(normal.z());
298  }
299 
300  return subject;
301 }
302 
304 {
305  const int count= m_Points.count();
306  GLfloatVector subject(count * 6); // 2 normals by vertex and 3 components pear normal => 6
307  int index= 0.0;
308  for (int i= count; i > 0; --i)
309  {
310  GLC_Vector3d vect(m_Points.at(i % count) - m_Points.at(i - 1));
312 
313  // First segment point
314  subject[(6 * index)]= static_cast<GLfloat>(normal.x());
315  subject[(6 * index) + 1]= static_cast<GLfloat>(normal.y());
316  subject[(6 * index) + 2]= static_cast<GLfloat>(normal.z());
317 
318  // Second segment point
319  subject[(6 * index) + 3]= static_cast<GLfloat>(normal.x());
320  subject[(6 * index) + 4]= static_cast<GLfloat>(normal.y());
321  subject[(6 * index) + 5]= static_cast<GLfloat>(normal.z());
322  ++index;
323  }
324 
325  return subject;
326 }
327 
329 {
330  const int count= m_Points.count();
331  GLfloatVector subject(count * 3); // 3 components pear vertice
332  for (int i= 0; i < count; ++i)
333  {
334  GLC_Point3d point= m_Points.at(i);
335  subject[(3 * i)]= static_cast<GLfloat>(point.x());
336  subject[(3 * i) + 1]= static_cast<GLfloat>(point.y());
337  subject[(3 * i) + 2]= static_cast<GLfloat>(point.z());
338  }
339 
340  return subject;
341 }
342 
344 {
345  const int count= m_Points.count();
346  GLfloatVector subject(count * 2);
347 
348  QList<GLC_Point2d> baseFace2DPolygon= glc::polygonIn2d(m_Points);
349  QList<GLC_Point2d> normalizePolygon= glc::normalyzePolygon(baseFace2DPolygon);
350 
351  for (int i= 0; i < count; ++i)
352  {
353  GLC_Point2d texel= normalizePolygon.at(i);
354  subject[i * 2]= static_cast<GLfloat>(texel.x());
355  subject[i * 2 + 1]= static_cast<GLfloat>(texel.y());
356  }
357 
358  return subject;
359 }
360 
362 {
363  const int count= m_Points.count();
364  GLfloatVector subject(count * 6); // 3 components pear vertice * 2
365  for (int i= 0; i < count; ++i)
366  {
367  GLC_Point3d point1= m_Points.at(i);
368  subject[(6 * i)]= static_cast<GLfloat>(point1.x());
369  subject[(6 * i) + 1]= static_cast<GLfloat>(point1.y());
370  subject[(6 * i) + 2]= static_cast<GLfloat>(point1.z());
371 
372  GLC_Point3d point2= m_Points.at((i + 1) % count);
373  subject[(6 * i) + 3]= static_cast<GLfloat>(point2.x());
374  subject[(6 * i) + 4]= static_cast<GLfloat>(point2.y());
375  subject[(6 * i) + 5]= static_cast<GLfloat>(point2.z());
376  }
377 
378  return subject;
379 }
380 
382 {
383  const int count= m_Points.count();
384  GLfloatVector subject(count * 4);
385 
386  QList<GLC_Point2d> baseFace2DPolygon= glc::polygonIn2d(m_Points);
387  QList<GLC_Point2d> normalizePolygon= glc::normalyzePolygon(baseFace2DPolygon);
388 
389  for (int i= 0; i < count; ++i)
390  {
391  GLC_Point2d texel1= normalizePolygon.at(i);
392  subject[i * 4]= static_cast<GLfloat>(texel1.x());
393  subject[i * 4 + 1]= static_cast<GLfloat>(texel1.y());
394 
395  GLC_Point2d texel2= normalizePolygon.at((i + 1) % count);
396  subject[i * 4 + 2]= static_cast<GLfloat>(texel2.x());
397  subject[i * 4 + 3]= static_cast<GLfloat>(texel2.y());
398  }
399 
400  return subject;
401 }
402 
404 {
405  const int count= m_Points.count();
406  GLfloatVector subject(count * 3); // 3 components pear normal
407  for (int i= 0; i < count; ++i)
408  {
409  subject[(3 * i)]= static_cast<GLfloat>(m_GivenFaceNormal.x());
410  subject[(3 * i) + 1]= static_cast<GLfloat>(m_GivenFaceNormal.y());
411  subject[(3 * i) + 2]= static_cast<GLfloat>(m_GivenFaceNormal.z());
412  }
413 
414  return subject;
415 }
416 
417 QList<GLC_Point3d> GLC_ExtrudedMesh::createdFacePoints() const
418 {
419  // The order is inverted to preserve face counterclockwise order
421  const int count= m_Points.count();
422  QList<GLC_Point3d> subject;
423  for (int i= 0; i < count; ++i)
424  {
425  subject.append(m_Points.at((count -i) % count) + offset);
426  }
427 
428  return subject;
429 }
430 
432 {
433  const GLC_Vector3d normal= m_GivenFaceNormal.inverted();
434 
435  const int count= m_Points.count();
436  GLfloatVector subject(count * 3); // 3 components pear normal
437  for (int i= 0; i < count; ++i)
438  {
439  subject[(3 * i)]= static_cast<GLfloat>(normal.x());
440  subject[(3 * i) + 1]= static_cast<GLfloat>(normal.y());
441  subject[(3 * i) + 2]= static_cast<GLfloat>(normal.z());
442  }
443 
444  return subject;
445 }
446 
448 {
449  QList<GLC_Point3d> points= createdFacePoints();
450 
451  const int count= points.count();
452  GLfloatVector subject(count * 3); // 3 components pear normal
453  for (int i= 0; i < count; ++i)
454  {
455  GLC_Point3d point= points.at(i);
456  subject[(3 * i)]= static_cast<GLfloat>(point.x());
457  subject[(3 * i) + 1]= static_cast<GLfloat>(point.y());
458  subject[(3 * i) + 2]= static_cast<GLfloat>(point.z());
459  }
460 
461  return subject;
462 }
463 
465 {
466  const int count= m_Points.count();
467  GLfloatVector subject(count * 2);
468 
469  QList<GLC_Point2d> baseFace2DPolygon= glc::polygonIn2d(createdFacePoints());
470  QList<GLC_Point2d> normalizePolygon= glc::normalyzePolygon(baseFace2DPolygon);
471 
472  for (int i= 0; i < count; ++i)
473  {
474  GLC_Point2d texel= normalizePolygon.at(i);
475  subject[i * 2]= static_cast<GLfloat>(texel.x());
476  subject[i * 2 + 1]= static_cast<GLfloat>(texel.y());
477  }
478 
479  return subject;
480 
481 }
482 
484 {
485  QList<GLC_Point3d> points= createdFacePoints();
486  const int count= points.count();
487  GLfloatVector subject(count * 6); // 3 components pear vertice * 2
488  for (int i= 0; i < count; ++i)
489  {
490  GLC_Point3d point1= points.at(i);
491  subject[(6 * i)]= static_cast<GLfloat>(point1.x());
492  subject[(6 * i) + 1]= static_cast<GLfloat>(point1.y());
493  subject[(6 * i) + 2]= static_cast<GLfloat>(point1.z());
494 
495  GLC_Point3d point2= points.at((i + 1) % count);
496  subject[(6 * i) + 3]= static_cast<GLfloat>(point2.x());
497  subject[(6 * i) + 4]= static_cast<GLfloat>(point2.y());
498  subject[(6 * i) + 5]= static_cast<GLfloat>(point2.z());
499  }
500 
501  return subject;
502 
503 }
504 
506 {
507  const int count= m_Points.count();
508  GLfloatVector subject(count * 4);
509 
510  QList<GLC_Point2d> baseFace2DPolygon= glc::polygonIn2d(createdFacePoints());
511  QList<GLC_Point2d> normalizePolygon= glc::normalyzePolygon(baseFace2DPolygon);
512 
513  for (int i= 0; i < count; ++i)
514  {
515  GLC_Point2d texel1= normalizePolygon.at(i);
516  subject[i * 4]= static_cast<GLfloat>(texel1.x());
517  subject[i * 4 + 1]= static_cast<GLfloat>(texel1.y());
518 
519  GLC_Point2d texel2= normalizePolygon.at((i + 1) % count);
520  subject[i * 4 + 2]= static_cast<GLfloat>(texel2.x());
521  subject[i * 4 + 3]= static_cast<GLfloat>(texel2.y());
522  }
523 
524  return subject;
525 }
526 
527 void GLC_ExtrudedMesh::glDraw(const GLC_RenderProperties& renderProperties)
528 {
529  if (GLC_Mesh::isEmpty())
530  {
532  }
533 
534  GLC_Mesh::glDraw(renderProperties);
535 }

©2005-2013 Laurent Ribon