gVirtualXRay  2.0.10
VirtualX-RayImagingLibraryonGPU
CylinderMesh.inl
Go to the documentation of this file.
1 /*
2 
3 Copyright (c) 2017-2023, Dr Franck P. Vidal, Bangor University, All rights reserved.
4 Copyright (c) 2023-present, Prof Franck P. Vidal (franck.vidal@stfc.ac.uk),
5 UK Research and Innovation, All rights reserved.
6 
7 
8 Redistribution and use in source and binary forms, with or without modification,
9 are permitted provided that the following conditions are met:
10 
11 1. Redistributions of source code must retain the above copyright notice,
12 this list of conditions and the following disclaimer.
13 
14 2. Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation and/or
16 other materials provided with the distribution.
17 
18 3. Neither the name of Bangor University, UK Research and Innovation nor the
19 names of its contributors may be used to endorse or promote products derived
20 from this software without specific prior written permission.
21 
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 */
34 
35 
63 //******************************************************************************
64 // namespace
65 //******************************************************************************
66 namespace gVirtualXRay {
67 
68 
69 //--------------------------------------------------------------
70 template<typename T> CylinderMesh<T>::CylinderMesh(unsigned int aNumberOfSectors,
71  double aHeight,
72  double aRadius,
73  int anIndexDataType):
74 //--------------------------------------------------------------
75  PolygonMesh()
76 //--------------------------------------------------------------
77 {
78  create(aNumberOfSectors, aHeight, aRadius, anIndexDataType);
79 }
80 
81 
82 //------------------------------------------------------
83 template<typename T> void CylinderMesh<T>::create(unsigned int aNumberOfSectors,
84  double aHeight,
85  double aRadius,
86  int anIndexDataType)
87 //------------------------------------------------------
88 {
89  if (aNumberOfSectors < 3)
90  {
91  throw Exception(__FILE__, __FUNCTION__, __LINE__, "Invalid parameter, the number of sectors should be at least 3");
92  }
93 
94  // Reset the mesh
95  reset();
96  m_external_data_flag = false;
97 
98  m_radius = aRadius;
99 
100  m_local_min_corner = VEC3(-aRadius, -aHeight / 2.0, -aRadius);
101  m_local_max_corner = VEC3( aRadius, aHeight / 2.0, aRadius);
102 
103  std::vector<T> p_vertex_set;
104  std::vector<T> p_normal_set;
105  std::vector<unsigned int> p_index_set;
106 
107  double theta(0);
108  double angle(Pi * 2.0 / aNumberOfSectors);
109 
110  p_vertex_set.push_back(0);
111  p_vertex_set.push_back(-aHeight / 2.0);
112  p_vertex_set.push_back(0);
113 
114  p_vertex_set.push_back(0);
115  p_vertex_set.push_back(aHeight / 2.0);
116  p_vertex_set.push_back(0);
117 
118 
119  // The side of the cylinder
120  for(unsigned int s(0); s < aNumberOfSectors; ++s, theta += angle)
121  {
122  double const x = cos(theta);
123  double const z = sin(theta);
124 
125  p_vertex_set.push_back(x * aRadius);
126  p_vertex_set.push_back(-aHeight / 2.0);
127  p_vertex_set.push_back(z * aRadius);
128 
129  p_normal_set.push_back(x);
130  p_normal_set.push_back(0);
131  p_normal_set.push_back(z);
132 
133  p_vertex_set.push_back(x * aRadius);
134  p_vertex_set.push_back(aHeight / 2.0);
135  p_vertex_set.push_back(z * aRadius);
136 
137  p_normal_set.push_back(x);
138  p_normal_set.push_back(0);
139  p_normal_set.push_back(z);
140 
141 
142  if (s < aNumberOfSectors - 1)
143  {
144  p_index_set.push_back(2 + s * 2);
145  p_index_set.push_back(2 + s * 2 + 1);
146  p_index_set.push_back(2 + s * 2 + 2);
147 
148  p_index_set.push_back(2 + s * 2 + 2);
149  p_index_set.push_back(2 + s * 2 + 1);
150  p_index_set.push_back(2 + s * 2 + 3);
151  }
152  else
153  {
154  p_index_set.push_back(2 + s * 2);
155  p_index_set.push_back(2 + s * 2 + 1);
156  p_index_set.push_back(2 + 0);
157 
158  p_index_set.push_back(2 + 0);
159  p_index_set.push_back(2 + s * 2 + 1);
160  p_index_set.push_back(2 + 1);
161  }
162  }
163 
164  // Caps
165  theta = 0;
166  for(unsigned int s(0); s < aNumberOfSectors; ++s, theta += angle)
167  {
168  p_normal_set.push_back(0);
169  p_normal_set.push_back(-1);
170  p_normal_set.push_back(0);
171 
172  p_normal_set.push_back(0);
173  p_normal_set.push_back(1);
174  p_normal_set.push_back(0);
175 
176  if (s < aNumberOfSectors - 1)
177  {
178  p_index_set.push_back(0);
179  p_index_set.push_back(2 + s * 2);
180  p_index_set.push_back(2 + s * 2 + 2);
181 
182  p_index_set.push_back(1);
183  p_index_set.push_back(2 + s * 2 + 3);
184  p_index_set.push_back(2 + s * 2 + 1);
185  }
186  else
187  {
188  p_index_set.push_back(0);
189  p_index_set.push_back(2 + s * 2);
190  p_index_set.push_back(2);
191 
192  p_index_set.push_back(1);
193  p_index_set.push_back(2 + 1);
194  p_index_set.push_back(2 + s * 2 + 1);
195  }
196  }
197 
198  if (anIndexDataType)
199  {
200  // Use vertex normals
201  std::vector<T> p_normal_set2;
202 
203  for (unsigned int vertex_id = 0; vertex_id < p_vertex_set.size() / 3; ++vertex_id)
204  {
205  double x = 0;
206  double y = 0;
207  double z = 0;
208 
209  unsigned int counter = 0;
210 
211  for (unsigned int face_id = 0; face_id < p_index_set.size() / 3; ++face_id)
212  {
213  if (p_index_set[face_id * 3] == vertex_id ||
214  p_index_set[face_id * 3 + 1] == vertex_id ||
215  p_index_set[face_id * 3 + 2] == vertex_id)
216  {
217  counter++;
218  x += p_normal_set[face_id * 3];
219  y += p_normal_set[face_id * 3 + 1];
220  z += p_normal_set[face_id * 3 + 2];
221  }
222  }
223 
224  if (counter > 0)
225  {
226  x /= counter;
227  y /= counter;
228  z /= counter;
229  }
230 
231  p_normal_set2.push_back(x);
232  p_normal_set2.push_back(y);
233  p_normal_set2.push_back(z);
234  }
235 
236  switch (anIndexDataType)
237  {
238  case GL_UNSIGNED_INT:
239  {
240  setInternalData(GL_TRIANGLES,
241  &p_vertex_set,
242  &p_normal_set2,
243  &p_index_set,
244  false,
245  GL_STATIC_DRAW);
246  }
247  break;
248 
249  case GL_UNSIGNED_SHORT:
250  {
251  std::vector<GLushort> p_ushort_index_set;
252 
253  for (std::vector<GLuint>::const_iterator ite(p_index_set.begin());
254  ite != p_index_set.end();
255  ++ite)
256  {
257  p_ushort_index_set.push_back(*ite);
258  }
259 
260  setInternalData(GL_TRIANGLES,
261  &p_vertex_set,
262  &p_normal_set2,
263  &p_ushort_index_set,
264  false,
265  GL_STATIC_DRAW);
266  }
267  break;
268 
269  case GL_UNSIGNED_BYTE:
270  {
271  std::vector<GLubyte> p_ubyte_index_set;
272 
273  for (std::vector<GLuint>::const_iterator ite(p_index_set.begin());
274  ite != p_index_set.end();
275  ++ite)
276  {
277  p_ubyte_index_set.push_back(*ite);
278  }
279 
280  setInternalData(GL_TRIANGLES,
281  &p_vertex_set,
282  &p_normal_set2,
283  &p_ubyte_index_set,
284  false,
285  GL_STATIC_DRAW);
286  }
287  break;
288 
289  default:
290  throw Exception(__FILE__, __FUNCTION__, __LINE__,
291  "Invalid data type.");
292  }
293  }
294  else
295  {
296  std::vector<T> p_vertex_set2;
297  std::vector<T> p_normal_set2;
298 
299  int normal_id = 0;
300  for (std::vector<unsigned int>::const_iterator ite = p_index_set.begin();
301  ite != p_index_set.end();
302  ++ite, ++normal_id)
303  {
304  p_vertex_set2.push_back(p_vertex_set[*ite * 3 + 0]);
305  p_vertex_set2.push_back(p_vertex_set[*ite * 3 + 1]);
306  p_vertex_set2.push_back(p_vertex_set[*ite * 3 + 2]);
307 
308  p_normal_set2.push_back(p_normal_set[3 * (normal_id / 3) + 0]);
309  p_normal_set2.push_back(p_normal_set[3 * (normal_id / 3) + 1]);
310  p_normal_set2.push_back(p_normal_set[3 * (normal_id / 3) + 2]);
311  }
312 
313  setInternalData(GL_TRIANGLES,
314  &p_vertex_set2,
315  &p_normal_set2,
316  false,
317  GL_STATIC_DRAW);
318  }
319 }
320 
321 
322 } // namespace gVirtualXRay
CylinderMesh(unsigned int aNumberOfSectors=10, double aHeight=1.0 *cm, double aRadius=0.5 *cm, int anIndexDataType=0)
Default constructor.
void create(unsigned int aNumberOfSectors=10, double aHeight=1.0 *cm, double aRadius=0.5 *cm, int anIndexDataType=0)
Create a new sphere.
Exception is a class to handle exceptions.
Definition: Exception.h:109
PolygonMesh is a class to handle polygon (triangles) meshes.
Definition: PolygonMesh.h:114
Vec3< RATIONAL_NUMBER > VEC3
Type of data used to store 3D vectors.
Definition: Types.h:115
const double Pi
Pi.