OGLplus (0.52.0) a C++ wrapper for OpenGL

revolve.hpp
Go to the documentation of this file.
1 
12 #pragma once
13 #ifndef OGLPLUS_SHAPES_REVOLVE_1107121519_HPP
14 #define OGLPLUS_SHAPES_REVOLVE_1107121519_HPP
15 
16 #include <oglplus/shapes/draw.hpp>
17 #include <oglplus/face_mode.hpp>
18 
20 
21 #include <oglplus/math/vector.hpp>
22 #include <oglplus/math/matrix.hpp>
23 #include <oglplus/math/sphere.hpp>
24 
25 #include <cmath>
26 
27 namespace oglplus {
28 namespace shapes {
29 
31 template <typename Type>
32 class RevolveY
33  : public DrawingInstructionWriter
34  , public DrawMode
35 {
36 private:
37  const std::vector<Type> _sections, _section_factors;
38  const unsigned _rings;
39 
40  const std::vector<Vector<Type, 3>> _positions_0, _positions_1;
41  const std::vector<Vector<Type, 3>> _normals_0, _normals_1;
42  const std::vector<Vector<Type, 3>> _tex_coords_0, _tex_coords_1;
43 
44  Type _radius;
45 
46  static Vector<Type, 3> _mix(
47  const Vector<Type, 3>& a,
48  const Vector<Type, 3>& b,
49  Type factor
50  )
51  {
52  if(factor < Type(0)) factor = Type(0);
53  if(factor > Type(1)) factor = Type(1);
54  return a * (Type(1) - factor) + b * factor;
55  }
56 
57  Vector<Type, 3> _get_position(unsigned ring, unsigned section) const
58  {
59  return _mix(
60  _positions_0[ring],
61  _positions_1[ring],
62  _section_factors[section]
63  );
64  }
65 
66  Vector<Type, 3> _get_normal(unsigned ring, unsigned section) const
67  {
68  return _mix(
69  _normals_0[ring],
70  _normals_1[ring],
71  _section_factors[section]
72  );
73  }
74 
75  Vector<Type, 3> _get_tex_coord(unsigned ring, unsigned section) const
76  {
77  return _mix(
78  _tex_coords_0[ring],
79  _tex_coords_1[ring],
80  _section_factors[section]
81  );
82  }
83 
84  static std::vector<Type> _make_default_sections(unsigned sections)
85  {
86  std::vector<Type> result(sections + 1);
87  const Type s_step = Type(1) / Type(sections);
88  Type s = Type(0);
89  for(auto i=result.begin(), e=result.end(); i!=e; ++i, s+=s_step)
90  *i = s;
91  return result;
92  }
93 
94  static std::vector<Vector<Type, 3>> _calculate_normals(
95  const std::vector<Vector<Type, 3>>& pos,
96  const std::vector<Vector<Type, 3>>& nml
97  )
98  {
99  if(!nml.empty())
100  {
101  assert(pos.size() == nml.size());
102  return nml;
103  }
104  std::vector<Vector<Type, 3>> result(pos.size());
105 
106  const unsigned n = result.size()-1;
107  const Vec3f tgnt(0.0, 0.0, -1.0);
108 
109  result[0] = Normalized(Cross(tgnt, pos[1] - pos[0]));
110  for(unsigned i=1; i!=n; ++i)
111  result[i] = Normalized(Cross(tgnt, pos[i+1]-pos[i-1]));
112  result[n] = Normalized(Cross(tgnt, pos[n] - pos[n-1]));
113  return result;
114  }
115 
116  void _check(void)
117  {
118  assert(_rings > 1);
119  assert(_sections.size() > 2);
120  assert(_sections.size() == _section_factors.size());
121 
122  assert(_positions_0.size() == _rings);
123  assert(_positions_1.size() == _rings);
124  assert(_normals_0.size() == _rings);
125  assert(_normals_1.size() == _rings);
126  assert(_tex_coords_0.size() == _rings);
127  assert(_tex_coords_1.size() == _rings);
128  }
129 
130  void _calc_radius(void)
131  {
132  _radius = Type(0);
133  Type l;
134  for(unsigned i=0; i!=_rings; ++i)
135  {
136  l = Length(_positions_0[i]);
137  if(_radius < l) _radius = l;
138  l = Length(_positions_1[i]);
139  if(_radius < l) _radius = l;
140  }
141  }
142 public:
143  using DrawMode::Default;
144 
147  unsigned sections,
148  const std::vector<Vector<Type, 3>>& positions,
149  const std::vector<Vector<Type, 3>>& normals,
150  const std::vector<Vector<Type, 3>>& tex_coords
151  ): _sections(_make_default_sections(sections))
152  , _section_factors(_sections.size(), Type(0))
153  , _rings(positions.size())
154  , _positions_0(positions)
155  , _positions_1(_positions_0)
156  , _normals_0(_calculate_normals(_positions_0, normals))
157  , _normals_1(_normals_0)
158  , _tex_coords_0(tex_coords)
159  , _tex_coords_1(_tex_coords_0)
160  {
161  _check();
162  _calc_radius();
163  }
164 
167  const std::vector<Type>& section_factors,
168  const std::vector<Vector<Type, 3>>& positions_0,
169  const std::vector<Vector<Type, 3>>& positions_1,
170  const std::vector<Vector<Type, 3>>& normals_0,
171  const std::vector<Vector<Type, 3>>& normals_1,
172  const std::vector<Vector<Type, 3>>& tex_coords_0,
173  const std::vector<Vector<Type, 3>>& tex_coords_1
174  ): _sections(_make_default_sections(section_factors.size()-1))
175  , _section_factors(section_factors)
176  , _rings(positions_0.size())
177  , _positions_0(positions_0)
178  , _positions_1(positions_1)
179  , _normals_0(_calculate_normals(_positions_0, normals_0))
180  , _normals_1(_calculate_normals(_positions_1, normals_1))
181  , _tex_coords_0(tex_coords_0)
182  , _tex_coords_1(tex_coords_1)
183  {
184  _check();
185  _calc_radius();
186  }
187 
190  {
191  return FaceOrientation::CW;
192  }
193 
195  template <typename T>
196  GLuint Positions(std::vector<T>& dest) const
197  {
198  dest.resize(_rings * _sections.size() * 3);
199  unsigned k = 0;
200  //
201  for(unsigned si=0, sn=_sections.size(); si!=sn; ++si)
202  {
203  const auto angle = FullCircles(_sections[si]);
204  const auto mat = ModelMatrix<Type>::RotationY(angle);
205 
206  for(unsigned r=0; r!=_rings; ++r)
207  {
208  const Vector<Type, 4> in(_get_position(r, si), 1);
209  const Vector<Type, 4> out = mat * in;
210 
211  dest[k++] = T(out.x());
212  dest[k++] = T(out.y());
213  dest[k++] = T(out.z());
214  }
215  }
216  assert(k == dest.size());
217  return 3;
218  }
219 
221  template <typename T>
222  GLuint Normals(std::vector<T>& dest) const
223  {
224  dest.resize(_rings * _sections.size() * 3);
225  unsigned k = 0;
226  //
227  for(unsigned si=0, sn=_sections.size(); si!=sn; ++si)
228  {
229  const auto angle = FullCircles(_sections[si]);
230  const auto mat = ModelMatrix<Type>::RotationY(angle);
231 
232  for(unsigned r=0; r!=_rings; ++r)
233  {
234  const Vector<Type, 4> in(_get_normal(r, si), 0);
235  const Vector<Type, 4> out = mat * in;
236 
237  dest[k++] = T(out.x());
238  dest[k++] = T(out.y());
239  dest[k++] = T(out.z());
240  }
241  }
242  assert(k == dest.size());
243  return 3;
244  }
245 
247  template <typename T>
248  GLuint Tangents(std::vector<T>& dest) const
249  {
250  dest.resize(_rings * _sections.size() * 3);
251  unsigned k = 0;
252 
253  const Vector<Type, 4> in(0.0, 0.0, -1.0, 0.0);
254 
255  for(unsigned si=0, sn=_sections.size(); si!=sn; ++si)
256  {
257  const auto angle = FullCircles(_sections[si]);
258  const auto mat = ModelMatrix<Type>::RotationY(angle);
259  const auto out = mat * in;
260 
261  for(unsigned r=0; r!=_rings; ++r)
262  {
263  dest[k++] = T(out.x());
264  dest[k++] = T(out.y());
265  dest[k++] = T(out.z());
266  }
267  }
268  assert(k == dest.size());
269  return 3;
270  }
271 
273  template <typename T>
274  GLuint Bitangents(std::vector<T>& dest) const
275  {
276  dest.resize(_rings * _sections.size() * 3);
277  unsigned k = 0;
278 
279  const Vector<Type, 3> tgt(0.0, 0.0, -1.0);
280 
281  for(unsigned si=0, sn=_sections.size(); si!=sn; ++si)
282  {
283  const auto angle = FullCircles(_sections[si]);
284  const auto mat = ModelMatrix<Type>::RotationY(angle);
285 
286  for(unsigned r=0; r!=_rings; ++r)
287  {
288  const Vector<Type, 3> nml(_get_normal(r, si));
289  const Vector<Type, 4> in(Cross(nml, tgt), 0);
290  const auto out = mat * in;
291 
292  dest[k++] = T(out.x());
293  dest[k++] = T(out.y());
294  dest[k++] = T(out.z());
295  }
296  }
297  assert(k == dest.size());
298  return 3;
299  }
300 
302  template <typename T>
303  GLuint TexCoordinates(std::vector<T>& dest) const
304  {
305  dest.resize(_rings * _sections.size() * 3);
306  unsigned k = 0;
307  //
308  const Vector<Type, 4> in(0.0, 0.0, -1.0, 0.0);
309 
310  for(unsigned si=0, sn=_sections.size(); si!=sn; ++si)
311  {
312  const T u_mult = _sections[si];
313 
314  for(unsigned r=0; r!=_rings; ++r)
315  {
316  auto tc = _get_tex_coord(r, si);
317  dest[k++] = T(tc.x()*u_mult);
318  dest[k++] = T(tc.y());
319  dest[k++] = T(tc.z());
320  }
321  }
322  assert(k == dest.size());
323  return 3;
324  }
325 
326 #if OGLPLUS_DOCUMENTATION_ONLY
327 
336  typedef VertexAttribsInfo<RevolveY> VertexAttribs;
337 #else
338  typedef VertexAttribsInfo<
339  RevolveY,
340  std::tuple<
341  VertexPositionsTag,
342  VertexNormalsTag,
343  VertexTangentsTag,
344  VertexBitangentsTag,
345  VertexTexCoordinatesTag
346  >
347  > VertexAttribs;
348 #endif
349 
351  template <typename T>
352  void BoundingSphere(oglplus::Sphere<T>& bounding_sphere) const
353  {
354  // TODO
355  bounding_sphere = oglplus::Sphere<T>(
356  T(0),
357  T(0),
358  T(0),
359  T(_radius)
360  );
361  }
362 
364  typedef std::vector<GLuint> IndexArray;
365 
367  IndexArray Indices(Default = Default()) const
368  {
369  const unsigned sn = _sections.size() - 1;
370  const unsigned n = sn * (2 * _rings + 1);
371  //
372  IndexArray indices(n);
373  unsigned k = 0;
374  unsigned offs = 0;
375  // the triangle strips
376  for(unsigned s=0; s!=sn; ++s)
377  {
378  for(unsigned r=0; r!=_rings; ++r)
379  {
380  indices[k++] = offs + r + _rings;
381  indices[k++] = offs + r;
382  }
383  // primitive restart index
384  indices[k++] = n;
385  offs += _rings;
386  }
387  assert(k == indices.size());
388  //
389  // return the indices
390  return indices;
391  }
392 
395  {
396  auto instructions = this->MakeInstructions();
397  const unsigned sn = _sections.size() - 1;
398  const unsigned n = sn * (2 * _rings + 1);
399 
400  DrawOperation operation;
401  operation.method = DrawOperation::Method::DrawElements;
402  operation.mode = PrimitiveType::TriangleStrip;
403  operation.first = GLuint(0);
404  operation.count = GLuint(n);
405  operation.restart_index = GLuint(n);
406  operation.phase = 0;
407 
408  this->AddInstruction(instructions, operation);
409 
410  return instructions;
411  }
412 };
413 
414 } // shapes
415 } // oglplus
416 
417 #endif // include guard
Implementation of shape draw instructions.
IndexArray Indices(Default=Default()) const
Returns element indices that are used with the drawing instructions.
Definition: revolve.hpp:367
GLuint TexCoordinates(std::vector< T > &dest) const
Makes texture coordinates and returns number of values per vertex.
Definition: revolve.hpp:303
GLuint Bitangents(std::vector< T > &dest) const
Makes vertex bi-tangents and returns number of values per vertex.
Definition: revolve.hpp:274
RevolveY(const std::vector< Type > &section_factors, const std::vector< Vector< Type, 3 >> &positions_0, const std::vector< Vector< Type, 3 >> &positions_1, const std::vector< Vector< Type, 3 >> &normals_0, const std::vector< Vector< Type, 3 >> &normals_1, const std::vector< Vector< Type, 3 >> &tex_coords_0, const std::vector< Vector< Type, 3 >> &tex_coords_1)
Creates a shape by revolving curve approximation around the y-axis.
Definition: revolve.hpp:166
Sphere utility class.
GLuint Normals(std::vector< T > &dest) const
Makes vertex normals and returns number of values per vertex.
Definition: revolve.hpp:222
std::vector< GLuint > IndexArray
The type of index container returned by Indices()
Definition: revolve.hpp:364
FaceOrientation
Face orientation enumeration.
Definition: face_mode.hpp:62
OpenGL face type-related enumeration.
T z(void) const
Returns the 2-nd component.
Definition: vector.hpp:237
VertexAttribsInfo< RevolveY > VertexAttribs
Vertex attribute information for this shape builder.
Definition: revolve.hpp:336
GLuint Positions(std::vector< T > &dest) const
Makes vertex coordinates and returns number of values per vertex.
Definition: revolve.hpp:196
DrawingInstructions Instructions(Default=Default()) const
Returns the instructions for rendering.
Definition: revolve.hpp:394
T y(void) const
Returns the 1-st component.
Definition: vector.hpp:231
FaceOrientation FaceWinding(void) const
Returns the winding direction of faces.
Definition: revolve.hpp:189
void BoundingSphere(oglplus::Sphere< T > &bounding_sphere) const
Queries the bounding sphere coordinates and dimensions.
Definition: revolve.hpp:352
Class providing attributes and instructions for rendering of a revolved shape.
Definition: revolve.hpp:32
GLuint Tangents(std::vector< T > &dest) const
Makes vertex tangents and returns number of values per vertex.
Definition: revolve.hpp:248
Structure containing information about how to draw a part of a shape.
Definition: draw.hpp:100
Method method
The method to be used to draw.
Definition: draw.hpp:106
Classes providing additional information about the shape builders.
Class encapsulating the instructions for drawing of a shape.
Definition: draw.hpp:219
Class implementing sphere-related functionality.
Definition: sphere.hpp:29
static ModelMatrix RotationY(Angle< T > angle)
Constructs a Y-axis rotation matrix.
Definition: matrix.hpp:925
Basic template for vector types.
Definition: fwd.hpp:43
RevolveY(unsigned sections, const std::vector< Vector< Type, 3 >> &positions, const std::vector< Vector< Type, 3 >> &normals, const std::vector< Vector< Type, 3 >> &tex_coords)
Creates a shape by revolving curve approximation around the y-axis.
Definition: revolve.hpp:146
A vector class.
Angle< AngleValueType > FullCircles(AngleValueType value)
Creates a new angle from a value in "full circles" (i.e. 360 degrees)
Definition: angle.hpp:480
A matrix class.

Copyright © 2010-2014 Matúš Chochlík, University of Žilina, Žilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Mon Sep 22 2014 by Doxygen (version 1.8.6).