GteRevolutionMesh.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.3 (2016/07/12)
7 
8 #pragma once
9 
10 #include <Mathematics/GteMesh.h>
13 #include <memory>
14 
15 namespace gte
16 {
17 
18 template <typename Real>
19 class RevolutionMesh : public Mesh<Real>
20 {
21 public:
22  // The axis of revolution is the z-axis. The curve of revolution is
23  // p(t) = (x(t),z(t)), where t in [tmin,tmax], x(t) > 0 for t in
24  // (tmin,tmax), x(tmin) >= 0, and x(tmax) >= 0. The values tmin and tmax
25  // are those for the curve object passed to the constructor. The curve
26  // must be non-self-intersecting, except possibly at its endpoints. The
27  // curve is closed when p(tmin) = p(tmax), in which case the surface of
28  // revolution has torus topology. The curve is open when p(tmin) !=
29  // p(tmax). For an open curve, define x0 = x(tmin) and x1 = x(tmax). The
30  // surface has cylinder topology when x0 > 0 and x1 > 0, disk topology
31  // when exactly one of x0 or x1 is zero, or sphere topology when x0 and
32  // x1 are both zero. However, to simplify the design, the mesh is always
33  // built using cylinder topology. The row samples correspond to curve
34  // points and the column samples correspond to the points on the circles
35  // of revolution.
36  RevolutionMesh(MeshDescription const& description,
37  std::shared_ptr<ParametricCurve<2, Real>> const& curve,
38  bool sampleByArcLength = false);
39 
40  // Member access.
41  inline std::shared_ptr<ParametricCurve<2, Real>> const& GetCurve() const;
42  inline bool IsSampleByArcLength() const;
43 
44 private:
45  void CreateSampler();
46  void InitializeTCoords();
47  virtual void UpdatePositions() override;
49  void UpdateTorusPositions();
50  void UpdateDiskPositions();
51  void UpdateSpherePositions();
52 
53  std::shared_ptr<ParametricCurve<2, Real>> mCurve;
55  std::vector<Real> mCosAngle, mSinAngle;
56  std::function<Real(unsigned int)> mTSampler;
57  std::vector<Vector3<Real>> mSamples;
58 
59  // If the client does not request texture coordinates, they will be
60  // computed internally for use in evaluation of the surface geometry.
61  std::vector<Vector2<Real>> mDefaultTCoords;
62 };
63 
64 
65 template <typename Real>
67  std::shared_ptr<ParametricCurve<2, Real>> const& curve, bool sampleByArcLength)
68  :
69  Mesh<Real>(description,
71  mCurve(curve),
72  mSampleByArcLength(sampleByArcLength)
73 {
74  if (!this->mDescription.constructed)
75  {
76  // The logger system will report these errors in the Mesh constructor.
77  mCurve = nullptr;
78  return;
79  }
80 
81  if (!mCurve)
82  {
83  LogWarning("A nonnull revolution curve is required.");
84  this->mDescription.constructed = false;
85  return;
86  }
87 
88  // The four supported topologies all wrap around in the column direction.
89  mCosAngle.resize(this->mDescription.numCols + 1);
90  mSinAngle.resize(this->mDescription.numCols + 1);
91  Real invRadialSamples = (Real)1 / (Real)this->mDescription.numCols;
92  for (unsigned int c = 0; c < this->mDescription.numCols; ++c)
93  {
94  Real angle = c * invRadialSamples * (Real)GTE_C_TWO_PI;
95  mCosAngle[c] = cos(angle);
96  mSinAngle[c] = sin(angle);
97  }
100 
101  CreateSampler();
102 
103  if (!this->mTCoords)
104  {
106  this->mTCoords = mDefaultTCoords.data();
107  this->mTCoordStride = sizeof(Vector2<Real>);
108 
110  if (this->mDescription.allowUpdateFrame)
111  {
113  {
114  this->mDescription.allowUpdateFrame = false;
115  }
116 
117  if (!this->mNormals)
118  {
119  this->mDescription.allowUpdateFrame = false;
120  }
121  }
122  }
123 
124  this->ComputeIndices();
126  UpdatePositions();
127  if (this->mDescription.allowUpdateFrame)
128  {
129  this->UpdateFrame();
130  }
131  else if (this->mNormals)
132  {
133  this->UpdateNormals();
134  }
135 }
136 
137 template <typename Real>
138 inline std::shared_ptr<ParametricCurve<2, Real>> const& RevolutionMesh<Real>::GetCurve() const
139 {
140  return mCurve;
141 }
142 
143 template <typename Real>
145 {
146  return mSampleByArcLength;
147 }
148 
149 template <typename Real>
151 {
153  || this->mDescription.topology == MeshTopology::TORUS)
154  {
155  mSamples.resize(this->mDescription.rMax + 1);
156  }
157  else if (this->mDescription.topology == MeshTopology::DISK)
158  {
159  mSamples.resize(this->mDescription.rMax + 2);
160  }
161  else if (this->mDescription.topology == MeshTopology::SPHERE)
162  {
163  mSamples.resize(this->mDescription.rMax + 3);
164  }
165 
166  Real invDenom = ((Real)1) / (Real)(mSamples.size() - 1);
167  if (mSampleByArcLength)
168  {
169  Real factor = mCurve->GetTotalLength() * invDenom;
170  mTSampler = [this, factor](unsigned int i)
171  {
172  return mCurve->GetTime(i * factor);
173  };
174  }
175  else
176  {
177  Real factor = (mCurve->GetTMax() - mCurve->GetTMin()) * invDenom;
178  mTSampler = [this, factor](unsigned int i)
179  {
180  return mCurve->GetTMin() + i * factor;
181  };
182  }
183 }
184 
185 template <typename Real>
187 {
188  Vector2<Real>tcoord;
189 
190  switch (this->mDescription.topology)
191  {
193  {
194  for (unsigned int r = 0, i = 0; r < this->mDescription.numRows; ++r)
195  {
196  tcoord[1] = (Real)r / (Real)(this->mDescription.numRows - 1);
197  for (unsigned int c = 0; c <= this->mDescription.numCols; ++c, ++i)
198  {
199  tcoord[0] = (Real)c / (Real)this->mDescription.numCols;
200  this->TCoord(i) = tcoord;
201  }
202  }
203  break;
204  }
205  case MeshTopology::TORUS:
206  {
207  for (unsigned int r = 0, i = 0; r <= this->mDescription.numRows; ++r)
208  {
209  tcoord[1] = (Real)r / (Real)this->mDescription.numRows;
210  for (unsigned int c = 0; c <= this->mDescription.numCols; ++c, ++i)
211  {
212  tcoord[0] = (Real)c / (Real)this->mDescription.numCols;
213  this->TCoord(i) = tcoord;
214  }
215  }
216  break;
217  }
218  case MeshTopology::DISK:
219  {
220  Vector2<Real> origin{ (Real)0.5, (Real)0.5 };
221  unsigned int i = 0;
222  for (unsigned int r = 0; r < this->mDescription.numRows; ++r)
223  {
224  Real radius = (Real)(r + 1) / (Real)(2 * this->mDescription.numRows);
225  radius = std::min(radius, (Real)0.5);
226  for (unsigned int c = 0; c <= this->mDescription.numCols; ++c, ++i)
227  {
228  Real angle = (Real)GTE_C_TWO_PI * (Real)c / (Real)this->mDescription.numCols;
229  this->TCoord(i) = { radius * (float)cos(angle), radius * (float)sin(angle) };
230  }
231  }
232  this->TCoord(i) = origin;
233  break;
234  }
236  {
237  unsigned int i = 0;
238  for (unsigned int r = 0; r < this->mDescription.numRows; ++r)
239  {
240  tcoord[1] = (Real)r / (Real)(this->mDescription.numRows - 1);
241  for (unsigned int c = 0; c <= this->mDescription.numCols; ++c, ++i)
242  {
243  tcoord[0] = (Real)c / (Real)this->mDescription.numCols;
244  this->TCoord(i) = tcoord;
245  }
246  }
247  this->TCoord(i++) = { (Real)0.5, (Real)0 };
248  this->TCoord(i) = { (Real)0.5, (Real)1 };
249  break;
250  }
251  default:
252  // Invalid topology is reported by the Mesh constructor, so there is
253  // no need to log a message here.
254  break;
255  }
256 }
257 
258 template <typename Real>
260 {
261  unsigned int const numSamples = static_cast<unsigned int>(mSamples.size());
262  for (unsigned int i = 0; i < numSamples; ++i)
263  {
264  Real t = mTSampler(i);
265  Vector2<Real> position = mCurve->GetPosition(t);
266  mSamples[i][0] = position[0];
267  mSamples[i][1] = (Real)0;
268  mSamples[i][2] = position[1];
269  }
270 
271  switch (this->mDescription.topology)
272  {
275  break;
276  case MeshTopology::TORUS:
278  break;
279  case MeshTopology::DISK:
281  break;
284  break;
285  default:
286  break;
287  }
288 }
289 
290 template <typename Real>
292 {
293  for (unsigned int r = 0, i = 0; r <= this->mDescription.rMax; ++r)
294  {
295  Real radius = mSamples[r][0];
296  for (unsigned int c = 0; c <= this->mDescription.cMax; ++c, ++i)
297  {
298  this->Position(i) = { radius * mCosAngle[c], radius * mSinAngle[c], mSamples[r][2] };
299  }
300  }
301 }
302 
303 template <typename Real>
305 {
306  for (unsigned int r = 0, i = 0; r <= this->mDescription.rMax; ++r)
307  {
308  Real radius = mSamples[r][0];
309  for (unsigned int c = 0; c <= this->mDescription.cMax; ++c, ++i)
310  {
311  this->Position(i) = { radius * mCosAngle[c], radius * mSinAngle[c], mSamples[r][2] };
312  }
313  }
314 }
315 
316 template <typename Real>
318 {
319  for (unsigned int r = 0, rp1 = 1, i = 0; r <= this->mDescription.rMax; ++r, ++rp1)
320  {
321  Real radius = mSamples[rp1][0];
322  for (unsigned int c = 0; c <= this->mDescription.cMax; ++c, ++i)
323  {
324  this->Position(i) = { radius * mCosAngle[c], radius * mSinAngle[c], mSamples[rp1][2] };
325  }
326  }
327 
328  this->Position(this->mDescription.numVertices - 1) = { (Real)0, (Real)0, mSamples.front()[2] };
329 }
330 
331 template <typename Real>
333 {
334  for (unsigned int r = 0, rp1 = 1, i = 0; r <= this->mDescription.rMax; ++r, ++rp1)
335  {
336  Real radius = mSamples[rp1][0];
337  for (unsigned int c = 0; c <= this->mDescription.cMax; ++c, ++i)
338  {
339  this->Position(i) = { radius * mCosAngle[c], radius * mSinAngle[c], mSamples[rp1][2] };
340  }
341  }
342 
343  this->Position(this->mDescription.numVertices - 2) = { (Real)0, (Real)0, mSamples.front()[2] };
344  this->Position(this->mDescription.numVertices - 1) = { (Real)0, (Real)0, mSamples.back()[2] };
345 }
346 
347 
348 }
MeshDescription mDescription
Definition: GteMesh.h:163
RevolutionMesh(MeshDescription const &description, std::shared_ptr< ParametricCurve< 2, Real >> const &curve, bool sampleByArcLength=false)
uint32_t numRows
Definition: GteMesh.h:97
std::vector< Vector2< Real > > mDefaultTCoords
GLfloat angle
Definition: glext.h:6466
virtual void UpdateNormals()
Definition: GteMesh.h:586
std::vector< Real > mCosAngle
std::shared_ptr< ParametricCurve< 2, Real > > const & GetCurve() const
std::shared_ptr< ParametricCurve< 2, Real > > mCurve
const GLubyte * c
Definition: glext.h:11671
bool wantDynamicTangentSpaceUpdate
Definition: GteMesh.h:91
Vector3< Real > * mNormals
Definition: GteMesh.h:167
virtual void UpdatePositions() override
std::function< Real(unsigned int)> mTSampler
#define LogWarning(message)
Definition: GteLogger.h:95
GLdouble GLdouble t
Definition: glext.h:239
uint32_t numVertices
Definition: GteMesh.h:87
virtual void UpdateFrame()
Definition: GteMesh.h:630
Vector2< Real > & TCoord(uint32_t i)
Definition: GteMesh.h:508
GLboolean r
Definition: glcorearb.h:1217
size_t mTCoordStride
Definition: GteMesh.h:179
Vector2< Real > * mTCoords
Definition: GteMesh.h:172
void ComputeIndices()
Definition: GteMesh.h:515
std::vector< Real > mSinAngle
uint32_t numCols
Definition: GteMesh.h:97
std::vector< Vector3< Real > > mSamples
bool hasTangentSpaceVectors
Definition: GteMesh.h:95
Vector3< Real > & Position(uint32_t i)
Definition: GteMesh.h:466
MeshTopology topology
Definition: GteMesh.h:86
bool IsSampleByArcLength() const
#define GTE_C_TWO_PI
Definition: GteConstants.h:20


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01