GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_cylinder.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 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 "glc_cylinder.h"
26 #include "../glc_openglexception.h"
27 #include "../shading/glc_selectionmaterial.h"
28 #include "../glc_state.h"
29 
30 #include <QVector>
31 
32 // Class chunk id
33 quint32 GLC_Cylinder::m_ChunkId= 0xA705;
34 
36 // Constructor destructor
38 
39 GLC_Cylinder::GLC_Cylinder(double dRadius, double dLength, int discretization)
40 :GLC_Mesh()
41 , m_Radius(dRadius)
42 , m_Length(dLength)
43 , m_Discret(discretization) // Default discretion
44 , m_EndedIsCaped(true) // Cylinder ended are closed
45 {
46  Q_ASSERT((m_Radius > 0.0) && (m_Length > 0.0));
48 }
49 
51 :GLC_Mesh(sourceCylinder)
52 , m_Radius(sourceCylinder.m_Radius)
53 , m_Length(sourceCylinder.m_Length)
54 , m_Discret(sourceCylinder.m_Discret)
55 , m_EndedIsCaped(sourceCylinder.m_EndedIsCaped)
56 {
57  Q_ASSERT((m_Radius > 0.0) && (m_Length > 0.0) && (m_Discret > 0));
58  if (isEmpty()) createMeshAndWire();
59 }
60 
62 {
63 
64 }
65 
67 // Get Functions
69 
71 {
72  return m_ChunkId;
73 }
74 
75 
77 {
78  return new GLC_Cylinder(*this);
79 }
80 
81 
83 {
84  if (GLC_Mesh::isEmpty())
85  {
87  }
88  return GLC_Mesh::boundingBox();
89 }
90 
92 // Set Functions
94 
95 void GLC_Cylinder::setLength(double Length)
96 {
97  Q_ASSERT(Length > 0.0);
98  m_Length= Length;
99 
101 }
102 
103 
104 void GLC_Cylinder::setRadius(double Radius)
105 {
106  Q_ASSERT(Radius > 0.0);
107  m_Radius= Radius;
108 
110 }
111 
112 
113 void GLC_Cylinder::setDiscretion(int TargetDiscret)
114 {
115  Q_ASSERT(TargetDiscret > 0);
116  if (TargetDiscret != m_Discret)
117  {
118  m_Discret= TargetDiscret;
119  if (m_Discret < 6) m_Discret= 6;
120 
122  }
123 }
124 
125 
126 void GLC_Cylinder::setEndedCaps(bool CapsEnded)
127 {
128  if (m_EndedIsCaped != CapsEnded)
129  {
130  m_EndedIsCaped= CapsEnded;
131 
133  }
134 }
135 
137 // Private Opengl functions
139 
140 
141 void GLC_Cylinder::glDraw(const GLC_RenderProperties& renderProperties)
142 {
143 
144  if (GLC_Mesh::isEmpty())
145  {
147  }
148 
149  GLC_Mesh::glDraw(renderProperties);
150 }
151 
152 
154 {
155  Q_ASSERT(GLC_Mesh::isEmpty());
156  Q_ASSERT(m_WireData.isEmpty());
157 
158  // Create cosinus and sinus array according to the discretion and radius
159  const int vertexNumber= m_Discret + 1;
160  // Normals values
161  QVector<float> cosNormalArray(vertexNumber);
162  QVector<float> sinNormalArray(vertexNumber);
163 
164  QVector<float> cosArray(vertexNumber);
165  QVector<float> sinArray(vertexNumber);
166 
167  const double angle= (2.0 * glc::PI) / static_cast<double>(m_Discret);
168 
169  for (int i= 0; i < vertexNumber; ++i)
170  {
171  const double cosValue= cos(static_cast<double>(i) * angle);
172  const double sinValue= sin(static_cast<double>(i) * angle);
173 
174  cosNormalArray[i]= static_cast<GLfloat>(cosValue);
175  sinNormalArray[i]= static_cast<GLfloat>(sinValue);
176 
177  cosArray[i]= static_cast<GLfloat>(m_Radius * cosValue);
178  sinArray[i]= static_cast<GLfloat>(m_Radius * sinValue);
179  }
180 
181  // Mesh Data
182  GLfloatVector verticeVector;
183  GLfloatVector normalsVector;
185 
186  // Wire Data
187  GLfloatVector bottomWireData(vertexNumber * 3);
188  GLfloatVector topWireData(vertexNumber * 3);
189 
190  if (m_EndedIsCaped)
191  {
192  const int size= vertexNumber * 4;
193  verticeVector.resize(3 * size);
194  normalsVector.resize(3 * size);
195  texelVector.resize(2 * size);
196  }
197  else
198  {
199  const int size= vertexNumber * 2;
200  verticeVector.resize(3 * size);
201  normalsVector.resize(3 * size);
202  texelVector.resize(2 * size);
203  }
204  for (int i= 0; i < vertexNumber; ++i)
205  {
206  // Bottom Mesh
207  verticeVector[3 * i]= cosArray[i];
208  verticeVector[3 * i + 1]= sinArray[i];
209  verticeVector[3 * i + 2]= 0.0f;
210 
211  normalsVector[3 * i]= cosNormalArray[i];
212  normalsVector[3 * i + 1]= sinNormalArray[i];
213  normalsVector[3 * i + 2]= 0.0f;
214 
215  texelVector[2 * i]= static_cast<float>(i) / static_cast<float>(m_Discret);
216  texelVector[2 * i + 1]= 0.0f;
217 
218  // Bottom Wire
219  bottomWireData[3 * i]= cosArray[i];
220  bottomWireData[3 * i + 1]= sinArray[i];
221  bottomWireData[3 * i + 2]= 0.0f;
222 
223  // Top
224  verticeVector[3 * i + 3 * vertexNumber]= cosArray[i];
225  verticeVector[3 * i + 1 + 3 * vertexNumber]= sinArray[i];
226  verticeVector[3 * i + 2 + 3 * vertexNumber]= static_cast<float>(m_Length);
227 
228  normalsVector[3 * i + 3 * vertexNumber]= cosNormalArray[i];
229  normalsVector[3 * i + 1 + 3 * vertexNumber]= sinNormalArray[i];
230  normalsVector[3 * i + 2 + 3 * vertexNumber]= 0.0f;
231 
232  texelVector[2 * i + 2 * vertexNumber]= texelVector[2 * i];
233  texelVector[2 * i + 1 + 2 * vertexNumber]= 1.0f;
234 
235  // Top Wire
236  topWireData[3 * i]= cosArray[i];
237  topWireData[3 * i + 1]= sinArray[i];
238  topWireData[3 * i + 2]= static_cast<float>(m_Length);
239 
240  if (m_EndedIsCaped)
241  {
242  // Bottom Cap ends
243  verticeVector[3 * i + 2 * 3 * vertexNumber]= cosArray[i];
244  verticeVector[3 * i + 1 + 2 * 3 * vertexNumber]= sinArray[i];
245  verticeVector[3 * i + 2 + 2 * 3 * vertexNumber]= 0.0f;
246 
247  normalsVector[3 * i + 2 * 3 * vertexNumber]= 0.0f;
248  normalsVector[3 * i + 1 + 2 * 3 * vertexNumber]= 0.0f;
249  normalsVector[3 * i + 2 + 2 * 3 * vertexNumber]= -1.0f;
250 
251  texelVector[2 * i + 2 * 2 * vertexNumber]= texelVector[2 * i];
252  texelVector[2 * i + 1 + 2 * 2 * vertexNumber]= 0.0f;
253 
254  // Top Cap ends
255  verticeVector[3 * i + 3 * 3 * vertexNumber]= cosArray[i];
256  verticeVector[3 * i + 1 + 3 * 3 * vertexNumber]= sinArray[i];
257  verticeVector[3 * i + 2 + 3 * 3 * vertexNumber]= static_cast<float>(m_Length);
258 
259  normalsVector[3 * i + 3 * 3 * vertexNumber]= 0.0f;
260  normalsVector[3 * i + 1 + 3 * 3 * vertexNumber]= 0.0f;
261  normalsVector[3 * i + 2 + 3 * 3 * vertexNumber]= 1.0f;
262 
263  texelVector[2 * i + 3 * 2 * vertexNumber]= texelVector[2 * i];
264  texelVector[2 * i + 1 + 3 * 2 * vertexNumber]= 1.0f;
265  }
266  }
267 
268  // Add bulk data in to the mesh
269  GLC_Mesh::addVertice(verticeVector);
270  GLC_Mesh::addNormals(normalsVector);
271  GLC_Mesh::addTexels(texelVector);
272 
273  // Add polyline to wire data
274  GLC_Geometry::addVerticeGroup(bottomWireData);
275  GLC_Geometry::addVerticeGroup(topWireData);
276 
277  // Set the material to use
278  GLC_Material* pCylinderMaterial;
279  if (hasMaterial())
280  {
281  pCylinderMaterial= this->firstMaterial();
282  }
283  else
284  {
285  pCylinderMaterial= new GLC_Material();
286  }
287 
288  IndexList circumferenceStrips;
289  // Create the index
290  for (int i= 0; i < vertexNumber; ++i)
291  {
292  circumferenceStrips.append(i + vertexNumber);
293  circumferenceStrips.append(i);
294  }
295  addTrianglesStrip(pCylinderMaterial, circumferenceStrips);
296 
297  if (m_EndedIsCaped)
298  {
299  IndexList bottomCap;
300  IndexList topCap;
301  int id1= 0;
302  int id2= m_Discret - 1;
303  const int size= m_Discret / 2 + (m_Discret % 2);
304  for (int i= 0; i < size; ++i)
305  {
306  bottomCap.append(id1 + 2 * vertexNumber);
307  topCap.append(id2 + 3 * vertexNumber);
308 
309  bottomCap.append(id2 + 2 * vertexNumber);
310  topCap.append(id1 + 3 * vertexNumber);
311 
312  id1+= 1;
313  id2-= 1;
314  }
315  addTrianglesStrip(pCylinderMaterial, bottomCap);
316  addTrianglesStrip(pCylinderMaterial, topCap);
317  }
318 
319  finish();
320 }

©2005-2013 Laurent Ribon