gVirtualXRay  2.0.10
VirtualX-RayImagingLibraryonGPU
StepWedgeMesh.inl
Go to the documentation of this file.
1 /*
2 
3 Copyright (c) 2024-present, Prof Franck P. Vidal (franck.vidal@stfc.ac.uk),
4 UK Research and Innovation, All rights reserved.
5 Copyright (c) 2024-present, Mr Nalin Gupta, UK Research and Innovation,
6 All rights reserved.
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 the Bangor University nor the names of its contributors
19 may be used to endorse or promote products derived from this software without
20 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 
64 //******************************************************************************
65 // Include
66 //******************************************************************************
67 #ifndef __Logger_h
68 #include "gVirtualXRay/Logger.h"
69 #endif
70 
71 
72 //******************************************************************************
73 // namespace
74 //******************************************************************************
75 namespace gVirtualXRay {
76 
77 
78 //-------------------------------------------------------------------------------
79 template<typename T> StepWedgeMesh<T>::StepWedgeMesh(unsigned int aNumberOfSteps,
80  T aTotalLength,
81  T aWidth,
82  T aFirstStepHeight,
83  T anOtherStepHeight,
84  int anIndexDataType):
85 //-------------------------------------------------------------------------------
86  PolygonMesh()
87 //-------------------------------------------------------------------------------
88 {
89  create(aNumberOfSteps,
90  aTotalLength,
91  aWidth,
92  aFirstStepHeight,
93  anOtherStepHeight,
94  anIndexDataType);
95 }
96 
97 
98 //-----------------------------------------------------------------------------
99 template<typename T> void StepWedgeMesh<T>::create(unsigned int aNumberOfSteps,
100  T aTotalLength,
101  T aWidth,
102  T aFirstStepHeight,
103  T anOtherStepHeight,
104  int anIndexDataType)
105 //-----------------------------------------------------------------------------
106 {
107  unsigned int double_step = 2 * aNumberOfSteps;
108  T single_step_length = aTotalLength / aNumberOfSteps;
109  T half_length = aTotalLength * 0.5;
110  unsigned int number_of_vertices = aNumberOfSteps * (aNumberOfSteps + 5) + 2;
111  unsigned int number_of_triangles = 2 * aNumberOfSteps * (aNumberOfSteps + 5);
112 
113  // INITIALISE 1D VECTORS OF SIZE
114  std::vector<T> p_vertex_set;
115  p_vertex_set.reserve(3 * number_of_vertices); // 3 points per vertex in 3D
116 
117  // 2^8 is too small to hold indices as bit as number_of_vertices
118  // Make use of 2^16
119  if (anIndexDataType == GL_UNSIGNED_BYTE && number_of_vertices > 255)
120  {
121  LOGGER.logWarning("The data type of the index set is UCHAR. The number of vertices (") <<
122  number_of_vertices << ") is bigger than 255. We'll try using USHORT." << std::endl;
123 
124  anIndexDataType = GL_UNSIGNED_SHORT;
125  }
126 
127  // 2^16 is too small to hold indices as bit as number_of_vertices
128  // Make use of 2^32
129  if (anIndexDataType == GL_UNSIGNED_SHORT && number_of_vertices > 65536)
130  {
131  LOGGER.logWarning("The data type of the index set is USHORT. The number of vertices (") <<
132  number_of_vertices << ") is bigger than 255. We'll try using UINT." << std::endl;
133 
134  anIndexDataType = GL_UNSIGNED_INT;
135  }
136 
137  std::vector<unsigned int> p_uint_index_set;
138  p_uint_index_set.reserve(3 * number_of_triangles); // 3 indices per triangle
139 
140  // CREATE VERTICES FOR THE FLOOR
141  for (int f = 0; f < aNumberOfSteps + 1; ++f) {
142  T floorX = f * single_step_length - half_length;
143  T floorY = aWidth * 0.5;
144  T floorZ = 0;
145 
146  p_vertex_set.insert(p_vertex_set.end(), {floorX, +floorY, floorZ,
147  floorX, -floorY, floorZ});
148  }
149 
150 
151  // THE REST OF IT
152  for (int i = 0; i < aNumberOfSteps; ++i) {
153  // VERTICES FOR THE STEPS
154  unsigned int stepLayer = aNumberOfSteps - i;
155 
156  for (int j = 0; j < stepLayer + 1; ++j) {
157  T stepX = j * single_step_length - half_length;
158  T stepY = aWidth * 0.5;
159  T stepZ = (i * anOtherStepHeight) + aFirstStepHeight;
160 
161  p_vertex_set.insert(p_vertex_set.end(), {stepX, +stepY, stepZ,
162  stepX, -stepY, stepZ});
163  }
164 
165  // TRIANGLES TO CREATE FACES
166  int iDoubled = i * 2;
167  int iSquared = i * i;
168  unsigned int iSwitch = (i > 0) ? 1 : 0;
169 
170  // FOR ALL PARTS EXCEPT SIDES
171  //
172  // unique indices (a,b,c,d) uses 2 triangles
173  // (a,b,c) and (c,d,a)
174 
175  // bottom indices
176  unsigned int bottom1 = 1 + iDoubled;
177  unsigned int bottom2 = 0 + iDoubled;
178  unsigned int bottom3 = 2 + iDoubled;
179  unsigned int bottom4 = 3 + iDoubled;
180 
181  // backward indices
182  unsigned int back1 = (double_step + 3) * (i + 1) - iSquared;
183  unsigned int back2 = back1 - 1;
184  unsigned int back3 = ((double_step + 5) * i - iSquared - 2) * iSwitch;
185  unsigned int back4 = back3 + 1;
186 
187  // front-top indices
188  unsigned int frontTop1 = (double_step + 1) * (i + 2) - iSquared;
189  unsigned int frontTop2 = frontTop1 - 2;
190  unsigned int frontTop3 = frontTop1 - 1;
191  unsigned int frontTop4 = frontTop1 + 1;
192 
193  // forward indices
194  unsigned int forward1 = back2 - 2 * (iSwitch + 1);
195  unsigned int forward2 = frontTop1;
196  unsigned int forward3 = frontTop4;
197  unsigned int forward4 = forward1 + 1;
198 
199  p_uint_index_set.insert(p_uint_index_set.end(), {bottom1, bottom2, bottom3,
200  bottom3, bottom4, bottom1, // Bottom face
201 
202  back1, back2, back3,
203  back3, back4, back1, // Backward face
204 
205  frontTop1, frontTop2, frontTop3,
206  frontTop3, frontTop4, frontTop1, // Front-top face
207 
208  forward1, forward2, forward3,
209  forward3, forward4, forward1}); // Forward face
210  int size = p_uint_index_set.size();
211 
212  // THE FACES FOR THE SIDES
213  for (int k = 0; k < stepLayer; ++k) {
214  int kSwitch = (k > 0) ? 1 : -1;
215  int kSquared = k * k;
216 
217  unsigned int shiftValue = (double_step + 5) * k - kSquared - 1;
218  unsigned int lowerShift = iDoubled + (shiftValue * kSwitch);
219  unsigned int upperShift = iDoubled + shiftValue + double_step - 2 * (k - 2);
220 
221  // Faces in the -y direction
222  unsigned int negativeYSide4 = lowerShift;
223  unsigned int negativeYSide3 = upperShift;
224  unsigned int negativeYSide2 = negativeYSide3 + 2;
225  unsigned int negativeYSide1 = negativeYSide4 + 2;
226 
227  // Faces in the +y direction
228  unsigned int positiveYSide4 = negativeYSide1 - 1;
229  unsigned int positiveYSide3 = negativeYSide2 - 1;
230  unsigned int positiveYSide2 = negativeYSide3 - 1;
231  unsigned int positiveYSide1 = negativeYSide4 - 1;
232 
233  p_uint_index_set.insert(p_uint_index_set.end(), {negativeYSide1, negativeYSide2, negativeYSide3,
234  negativeYSide3, negativeYSide4, negativeYSide1, // -y direction faces
235 
236  positiveYSide1, positiveYSide2, positiveYSide3,
237  positiveYSide3, positiveYSide4, positiveYSide1}); // +y direction faces
238  }
239  }
240 
241 
242 
243 
244  if (anIndexDataType)
245  {
246  switch (anIndexDataType)
247  {
248  case GL_UNSIGNED_INT:
249  {
250  setInternalData(GL_TRIANGLES,
251  &p_vertex_set,
252  &p_uint_index_set,
253  false,
254  GL_STATIC_DRAW);
255  }
256  break;
257 
258  case GL_UNSIGNED_SHORT:
259  {
260  std::vector<GLushort> p_ushort_index_set;
261 
262  for (std::vector<GLuint>::const_iterator ite(p_uint_index_set.begin());
263  ite != p_uint_index_set.end();
264  ++ite)
265  {
266  p_ushort_index_set.push_back(*ite);
267  }
268 
269  setInternalData(GL_TRIANGLES,
270  &p_vertex_set,
271  &p_ushort_index_set,
272  false,
273  GL_STATIC_DRAW);
274  }
275  break;
276 
277  case GL_UNSIGNED_BYTE:
278  {
279  std::vector<GLubyte> p_ubyte_index_set;
280 
281  for (std::vector<GLuint>::const_iterator ite(p_uint_index_set.begin());
282  ite != p_uint_index_set.end();
283  ++ite)
284  {
285  p_ubyte_index_set.push_back(*ite);
286  }
287 
288  setInternalData(GL_TRIANGLES,
289  &p_vertex_set,
290  &p_ubyte_index_set,
291  false,
292  GL_STATIC_DRAW);
293  }
294  break;
295 
296  default:
297  throw Exception(__FILE__, __FUNCTION__, __LINE__,
298  "Invalid data type.");
299  }
300  }
301  // Don't use an index
302  else
303  {
304  std::vector<T> p_vertex_set2;
305 
306  int normal_id = 0;
307  for (std::vector<unsigned int>::const_iterator ite = p_uint_index_set.begin();
308  ite != p_uint_index_set.end();
309  ++ite, ++normal_id)
310  {
311  p_vertex_set2.push_back(p_vertex_set[*ite * 3 + 0]);
312  p_vertex_set2.push_back(p_vertex_set[*ite * 3 + 1]);
313  p_vertex_set2.push_back(p_vertex_set[*ite * 3 + 2]);
314  }
315 
316  setInternalData(GL_TRIANGLES,
317  &p_vertex_set2,
318  false,
319  GL_STATIC_DRAW);
320  }
321 }
322 
323 
324 } // namespace gVirtualXRay
void create(unsigned int aNumberOfSteps=2, T aTotalLength=10.0 *cm, T aWidth=1.0 *cm, T aFirstStepHeight=1.0 *cm, T anOtherStepHeight=0.1 *cm, int anIndexDataType=0)
Create a new step wedge.
Exception is a class to handle exceptions.
Definition: Exception.h:109
PolygonMesh is a class to handle polygon (triangles) meshes.
Definition: PolygonMesh.h:114
std::ostream & logWarning(const std::string &aMessage="")
StepWedgeMesh(unsigned int aNumberOfSteps=2, T aTotalLength=10.0 *cm, T aWidth=1.0 *cm, T aFirstStepHeight=1.0 *cm, T anOtherStepHeight=0.1 *cm, int anIndexDataType=0)
Default constructor.