GteMeshFactory.cpp
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/08/29)
7 
8 #include <GTEnginePCH.h>
12 using namespace gte;
13 
15 {
16 }
17 
19  :
20  mIndexSize(sizeof(unsigned int)),
23  mOutside(true),
24  mPositions(nullptr),
25  mNormals(nullptr),
26  mTangents(nullptr),
27  mBitangents(nullptr)
28 {
29  for (int i = 0; i < VA_MAX_TCOORD_UNITS; ++i)
30  {
31  mAssignTCoords[i] = false;
32  mTCoords[i] = nullptr;
33  }
34 }
35 
36 std::shared_ptr<Visual> MeshFactory::CreateRectangle(unsigned int numXSamples,
37  unsigned int numYSamples, float xExtent, float yExtent)
38 {
39  // Determine the number of vertices and triangles.
40  MeshDescription desc(MeshTopology::RECTANGLE, numXSamples, numYSamples);
41 
42  auto vbuffer = CreateVBuffer(desc.numVertices);
43  if (!vbuffer)
44  {
45  return nullptr;
46  }
47 
48  auto ibuffer = CreateIBuffer(desc.numTriangles);
49  if (!vbuffer)
50  {
51  return nullptr;
52  }
53 
54  size_t stride = static_cast<size_t>(mVFormat.GetVertexSize());
55  desc.vertexAttributes =
56  {
57  VertexAttribute("position", mPositions, stride),
58  VertexAttribute("normal", mNormals, stride),
59  VertexAttribute("tangent", mTangents, stride),
60  VertexAttribute("bitangent", mBitangents, stride),
61  VertexAttribute("tcoord", mTCoords[0], stride)
62  };
63 
64  desc.indexAttribute = IndexAttribute(ibuffer->GetData(), mIndexSize);
65 
66  Rectangle<3, float> rectangle;
67  rectangle.center = { 0.0f, 0.0f, 0.0f };
68  rectangle.axis[0] = { 1.0f, 0.0f, 0.0f };
69  rectangle.axis[1] = { 0.0f, 1.0f, 0.0f };
70  rectangle.extent = { xExtent, yExtent };
71  RectangleMesh<float> mesh(desc, rectangle);
72 
73  auto visual = std::make_shared<Visual>(vbuffer, ibuffer);
74  if (visual)
75  {
76  visual->UpdateModelBound();
77  }
78  return visual;
79 }
80 
81 std::shared_ptr<Visual> MeshFactory::CreateTriangle(unsigned int numSamples,
82  float xExtent, float yExtent)
83 {
84  // Quantities derived from inputs.
85  float inv = 1.0f / (static_cast<float>(numSamples)-1.0f);
86  unsigned int numVertices = numSamples*(numSamples + 1)/2;
87  unsigned int numTriangles = (numSamples - 1)*(numSamples - 1);
88 
89  // Generate geometry.
90  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
91  if (!vbuffer)
92  {
93  return nullptr;
94  }
95 
96  Vector3<float> pos;
97  Vector3<float> nor{ 0.0f, 0.0f, 1.0f };
98  Vector3<float> tan{ 1.0f, 0.0f, 0.0f };
99  Vector3<float> bin{ 0.0f, 1.0f, 0.0f }; // = Cross(nor,tan)
100  Vector2<float> tcd;
101  pos[2] = 0.0f;
102  for (unsigned int i1 = 0, i = 0; i1 < numSamples; ++i1)
103  {
104  tcd[1] = i1*inv;
105  pos[1] = tcd[1] * yExtent;
106  for (unsigned int i0 = 0; i0 + i1 < numSamples; ++i0, ++i)
107  {
108  tcd[0] = i0*inv;
109  pos[0] = tcd[0] * xExtent;
110 
111  SetPosition(i, pos);
112  SetNormal(i, nor);
113  SetTangent(i, tan);
114  SetBinormal(i, bin);
115  SetTCoord(i, tcd);
116  }
117  }
118 
119  // Generate indices.
120  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
121  if (!ibuffer)
122  {
123  return nullptr;
124  }
125 
126  int y0 = 0, y1 = numSamples;
127  unsigned int t = 0;
128  for (unsigned int i1 = 0; i1 < numSamples - 2; ++i1)
129  {
130  int bot0 = y0, bot1 = bot0 + 1, top0 = y1, top1 = y1 + 1;
131  for (unsigned int i0 = 0; i0 + i1 < numSamples - 2; ++i0)
132  {
133  ibuffer->SetTriangle(t++, bot0, bot1, top0);
134  ibuffer->SetTriangle(t++, bot1, top1, top0);
135  bot0 = bot1++;
136  top0 = top1++;
137  }
138  ibuffer->SetTriangle(t++, bot0, bot1, top0);
139  y0 = y1;
140  y1 = top0 + 1;
141  }
142  ibuffer->SetTriangle(t++, y0, y0 + 1, y1);
143 
144  // Create the mesh.
145  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
146  if (visual)
147  {
148  visual->UpdateModelBound();
149  }
150  return visual;
151 }
152 
153 std::shared_ptr<Visual> MeshFactory::CreateDisk(unsigned int numShellSamples,
154  unsigned int numRadialSamples, float radius)
155 {
156  // Quantities derived from inputs.
157  unsigned int ssm1 = numShellSamples - 1;
158  unsigned int rsm1 = numRadialSamples - 1;
159  float invSSm1 = 1.0f/static_cast<float>(ssm1);
160  float invRS = 1.0f/static_cast<float>(numRadialSamples);
161  unsigned int numVertices = 1 + numRadialSamples*ssm1;
162  unsigned int numTriangles = numRadialSamples*(2 * ssm1 - 1);
163 
164  // Generate geometry.
165  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
166  if (!vbuffer)
167  {
168  return nullptr;
169  }
170 
171  Vector3<float> pos;
172  Vector3<float> nor{ 0.0f, 0.0f, 1.0f };
173  Vector3<float> tan{ 1.0f, 0.0f, 0.0f };
174  Vector3<float> bin{ 0.0f, 1.0f, 0.0f }; // = Cross(nor,tan)
175  Vector2<float> tcd;
176 
177  // Center of disk.
178  pos = { 0.0f, 0.0f, 0.0f };
179  tcd = { 0.5f, 0.5f };
180  SetPosition(0, pos);
181  SetNormal(0, nor);
182  SetTangent(0, tan);
183  SetBinormal(0, bin);
184  SetTCoord(0, tcd);
185 
186  for (unsigned int r = 0; r < numRadialSamples; ++r)
187  {
188  float angle = invRS*r*(float)GTE_C_TWO_PI;
189  float cs = cos(angle);
190  float sn = sin(angle);
191  Vector3<float> radial{ cs, sn, 0.0f };
192 
193  for (unsigned int s = 1; s < numShellSamples; ++s)
194  {
195  float fraction = invSSm1*s; // in (0,R]
196  Vector3<float> fracRadial = fraction*radial;
197  unsigned int i = s + ssm1*r;
198  pos = radius*fracRadial;
199  tcd[0] = 0.5f + 0.5f*fracRadial[0];
200  tcd[1] = 0.5f + 0.5f*fracRadial[1];
201 
202  SetPosition(i, pos);
203  SetNormal(i, nor);
204  SetTangent(i, tan);
205  SetBinormal(i, bin);
206  SetTCoord(i, tcd);
207  }
208  }
209 
210  // Generate indices.
211  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
212  if (!ibuffer)
213  {
214  return nullptr;
215  }
216  for (unsigned int r0 = rsm1, r1 = 0, t = 0; r1 < numRadialSamples;
217  r0 = r1++)
218  {
219  ibuffer->SetTriangle(t++, 0, 1 + ssm1*r0, 1 + ssm1*r1);
220 
221  for (unsigned int s = 1; s < ssm1; ++s)
222  {
223  unsigned int i00 = s + ssm1*r0;
224  unsigned int i01 = s + ssm1*r1;
225  unsigned int i10 = i00 + 1;
226  unsigned int i11 = i01 + 1;
227 
228  ibuffer->SetTriangle(t++, i00, i10, i11);
229  ibuffer->SetTriangle(t++, i00, i11, i01);
230  }
231  }
232 
233  // Create the mesh.
234  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
235  if (visual)
236  {
237  visual->UpdateModelBound();
238  }
239  return visual;
240 }
241 
242 std::shared_ptr<Visual> MeshFactory::CreateBox(float xExtent, float yExtent,
243  float zExtent)
244 {
245  // Quantities derived from inputs.
246  int numVertices = 8;
247  int numTriangles = 12;
248 
249  // Generate geometry.
250  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
251  if (!vbuffer)
252  {
253  return nullptr;
254  }
255 
256  Vector3<float> pos, nor, basis[3];
257  Vector2<float> tcd;
258 
259  // Choose vertex normals in the diagonal directions.
260  Vector3<float> diag{ xExtent, yExtent, zExtent };
261  Normalize(diag);
262  if (!mOutside)
263  {
264  diag = -diag;
265  }
266 
267  for (unsigned int z = 0, v = 0; z < 2; ++z)
268  {
269  float fz = static_cast<float>(z), omfz = 1.0f - fz;
270  float zSign = 2.0f*fz - 1.0f;
271  pos[2] = zSign*zExtent;
272  nor[2] = zSign*diag[2];
273  for (unsigned int y = 0; y < 2; ++y)
274  {
275  float fy = static_cast<float>(y);
276  float ySign = 2.0f*fy - 1.0f;
277  pos[1] = ySign*yExtent;
278  nor[1] = ySign*diag[1];
279  tcd[1] = (1.0f - fy)*omfz + (0.75f - 0.5f*fy)*fz;
280  for (unsigned int x = 0; x < 2; ++x, ++v)
281  {
282  float fx = static_cast<float>(x);
283  float xSign = 2.0f*fx - 1.0f;
284  pos[0] = xSign*xExtent;
285  nor[0] = xSign*diag[0];
286  tcd[0] = fx*omfz + (0.25f + 0.5f*fx)*fz;
287 
288  basis[0] = nor;
289  ComputeOrthogonalComplement(1, basis);
290 
291  SetPosition(v, pos);
292  SetNormal(v, nor);
293  SetTangent(v, basis[1]);
294  SetBinormal(v, basis[2]);
295  SetTCoord(v, tcd);
296  }
297  }
298  }
299 
300  // Generate indices (outside view).
301  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
302  if (!ibuffer)
303  {
304  return nullptr;
305  }
306  ibuffer->SetTriangle(0, 0, 2, 3);
307  ibuffer->SetTriangle( 1, 0, 3, 1);
308  ibuffer->SetTriangle( 2, 0, 1, 5);
309  ibuffer->SetTriangle( 3, 0, 5, 4);
310  ibuffer->SetTriangle( 4, 0, 4, 6);
311  ibuffer->SetTriangle( 5, 0, 6, 2);
312  ibuffer->SetTriangle( 6, 7, 6, 4);
313  ibuffer->SetTriangle( 7, 7, 4, 5);
314  ibuffer->SetTriangle( 8, 7, 5, 1);
315  ibuffer->SetTriangle( 9, 7, 1, 3);
316  ibuffer->SetTriangle(10, 7, 3, 2);
317  ibuffer->SetTriangle(11, 7, 2, 6);
318  if (!mOutside)
319  {
320  ReverseTriangleOrder(ibuffer.get());
321  }
322 
323  // Create the mesh.
324  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
325  if (visual)
326  {
327  visual->UpdateModelBound();
328  }
329  return visual;
330 }
331 
332 std::shared_ptr<Visual> MeshFactory::CreateCylinderOpen(
333  unsigned int numAxisSamples, unsigned int numRadialSamples, float radius,
334  float height)
335 {
336  // Quantities derived from inputs.
337  unsigned int numVertices = numAxisSamples*(numRadialSamples + 1);
338  unsigned int numTriangles = 2 * (numAxisSamples - 1)*numRadialSamples;
339  float invRS = 1.0f/static_cast<float>(numRadialSamples);
340  float invASm1 = 1.0f/static_cast<float>(numAxisSamples - 1);
341  float halfHeight = 0.5f*height;
342 
343  // Generate geometry.
344  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
345  if (!vbuffer)
346  {
347  return nullptr;
348  }
349 
350  Vector3<float> pos, nor, basis[3];
351  Vector2<float> tcd;
352 
353  // Generate points on the unit circle to be used in computing the mesh
354  // points on a cylinder slice.
355  std::vector<float> cs(numRadialSamples + 1);
356  std::vector<float> sn(numRadialSamples + 1);
357  for (unsigned int r = 0; r < numRadialSamples; ++r)
358  {
359  float angle = invRS*r*(float)GTE_C_TWO_PI;
360  cs[r] = cos(angle);
361  sn[r] = sin(angle);
362  }
363  cs[numRadialSamples] = cs[0];
364  sn[numRadialSamples] = sn[0];
365 
366  // Generate the cylinder itself.
367  for (unsigned int a = 0, i = 0; a < numAxisSamples; ++a)
368  {
369  float axisFraction = a*invASm1; // in [0,1]
370  float z = -halfHeight + height*axisFraction;
371 
372  // Compute center of slice.
373  Vector3<float> sliceCenter{ 0.0f, 0.0f, z };
374 
375  // Compute slice vertices with duplication at endpoint.
376  for (unsigned int r = 0; r <= numRadialSamples; ++r, ++i)
377  {
378  float radialFraction = r*invRS; // in [0,1)
379  nor = { cs[r], sn[r], 0.0f };
380  pos = sliceCenter + radius*nor;
381  if (!mOutside)
382  {
383  nor = -nor;
384  }
385 
386  basis[0] = nor;
387  ComputeOrthogonalComplement(1, basis);
388  tcd = { radialFraction, axisFraction };
389 
390  SetPosition(i, pos);
391  SetNormal(i, nor);
392  SetTangent(i, basis[1]);
393  SetBinormal(i, basis[2]);
394  SetTCoord(i, tcd);
395  }
396  }
397 
398  // Generate indices (outside view).
399  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
400  if (!ibuffer)
401  {
402  return nullptr;
403  }
404  for (unsigned int a = 0, aStart = 0, t = 0; a < numAxisSamples - 1; ++a)
405  {
406  unsigned int i0 = aStart;
407  unsigned int i1 = i0 + 1;
408  aStart += numRadialSamples + 1;
409  unsigned int i2 = aStart;
410  unsigned int i3 = i2 + 1;
411  for (unsigned int i = 0; i < numRadialSamples;
412  ++i, ++i0, ++i1, ++i2, ++i3)
413  {
414  ibuffer->SetTriangle(t++, i0, i1, i2);
415  ibuffer->SetTriangle(t++, i1, i3, i2);
416  }
417  }
418  if (!mOutside)
419  {
420  ReverseTriangleOrder(ibuffer.get());
421  }
422 
423  // Create the mesh.
424  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
425  if (visual)
426  {
427  visual->UpdateModelBound();
428 
429  // The duplication of vertices at the seam causes the automatically
430  // generated bounding volume to be slightly off center. Reset the
431  // bound to use the true information.
432  float maxDist = sqrt(radius*radius + height*height);
433  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
434  visual->modelBound.SetRadius(maxDist);
435  }
436 
437  return visual;
438 }
439 
440 std::shared_ptr<Visual> MeshFactory::CreateCylinderClosed(
441  unsigned int numAxisSamples, unsigned int numRadialSamples, float radius,
442  float height)
443 {
444  // Create a sphere and then deform it into a closed cylinder.
445  std::shared_ptr<Visual> visual = CreateSphere(numAxisSamples,
446  numRadialSamples, radius);
447  if (!visual)
448  {
449  return nullptr;
450  }
451 
452  VertexBuffer* vbuffer = visual->GetVertexBuffer().get();
453  unsigned int numVertices = vbuffer->GetNumElements();
454  Vector3<float> pos, basis[3];
455  unsigned int i;
456 
457  // Flatten sphere at poles.
458  float hDiv2 = 0.5f*height;
459  i = numVertices - 2;
460  pos = Position(i);
461  pos[2] = -hDiv2;
462  SetPosition(i, pos); // south pole
463  i = numVertices - 1;
464  pos = Position(i);
465  pos[2] = +hDiv2;
466  SetPosition(i, pos); // north pole
467 
468  // Remap z-values to [-h/2,h/2].
469  float zFactor = 2.0f/static_cast<float>(numAxisSamples - 1);
470  float tmp0 = radius*(-1.0f + zFactor);
471  float tmp1 = 1.0f/(radius*(+1.0f - zFactor));
472  for (i = 0; i < numVertices-2; ++i)
473  {
474  pos = Position(i);
475  pos[2] = hDiv2*(-1.0f + tmp1*(pos[2] - tmp0));
476  float adjust = radius/sqrt(pos[0]*pos[0] + pos[1]*pos[1]);
477  pos[0] *= adjust;
478  pos[1] *= adjust;
479  SetPosition(i, pos);
480  }
481 
482  // Let the Visual update normals using its algorithm.
483  if (visual->UpdateModelNormals())
484  {
485  // Update tangent space, if relevant.
486  for (i = 0; i < numVertices; ++i)
487  {
488  basis[0] = Normal(i);
489  ComputeOrthogonalComplement(1, basis);
490  SetTangent(i, basis[1]);
491  SetBinormal(i, basis[2]);
492  }
493  }
494 
495  // The duplication of vertices at the seam causes the automatically
496  // generated bounding volume to be slightly off center. Reset the bound
497  // to use the true information.
498  float maxDist = sqrt(radius*radius + height*height);
499  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
500  visual->modelBound.SetRadius(maxDist);
501  return visual;
502 }
503 
504 std::shared_ptr<Visual> MeshFactory::CreateSphere(unsigned int numZSamples,
505  unsigned int numRadialSamples, float radius)
506 {
507  // Quantities derived from inputs.
508  unsigned int zsm1 = numZSamples - 1;
509  unsigned int zsm2 = numZSamples - 2;
510  unsigned int zsm3 = numZSamples - 3;
511  unsigned int rsp1 = numRadialSamples + 1;
512  float invRS = 1.0f/static_cast<float>(numRadialSamples);
513  float zFactor = 2.0f/static_cast<float>(zsm1);
514  unsigned int numVertices = zsm2*rsp1 + 2;
515  unsigned int numTriangles = 2 * zsm2*numRadialSamples;
516 
517  // Generate geometry.
518  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
519  if (!vbuffer)
520  {
521  return nullptr;
522  }
523 
524  Vector3<float> pos, nor, basis[3];
525  Vector2<float> tcd;
526 
527  // Generate points on the unit circle to be used in computing the mesh
528  // points on a sphere slice.
529  std::vector<float> cs(rsp1), sn(rsp1);
530  for (unsigned int r = 0; r < numRadialSamples; ++r)
531  {
532  float angle = invRS*r*(float)GTE_C_TWO_PI;
533  cs[r] = cos(angle);
534  sn[r] = sin(angle);
535  }
536  cs[numRadialSamples] = cs[0];
537  sn[numRadialSamples] = sn[0];
538 
539  // Generate the sphere itself.
540  unsigned int i = 0;
541  for (unsigned int z = 1; z < zsm1; ++z)
542  {
543  float zFraction = -1.0f + zFactor*static_cast<float>(z); // in (-1,1)
544  float zValue = radius*zFraction;
545 
546  // Compute center of slice.
547  Vector3<float> sliceCenter{ 0.0f, 0.0f, zValue };
548 
549  // Compute radius of slice.
550  float sliceRadius = sqrt(std::abs(radius*radius - zValue*zValue));
551 
552  // Compute slice vertices with duplication at endpoint.
553  for (unsigned int r = 0; r <= numRadialSamples; ++r, ++i)
554  {
555  float radialFraction = r*invRS; // in [0,1)
556  Vector3<float> radial{ cs[r], sn[r], 0.0f };
557  pos = sliceCenter + sliceRadius*radial;
558  nor = pos;
559  Normalize(nor);
560  if (!mOutside)
561  {
562  nor = -nor;
563  }
564 
565  basis[0] = nor;
566  ComputeOrthogonalComplement(1, basis);
567  tcd = { radialFraction, 0.5f*(zFraction + 1.0f) };
568 
569  SetPosition(i, pos);
570  SetNormal(i, nor);
571  SetTangent(i, basis[1]);
572  SetBinormal(i, basis[2]);
573  SetTCoord(i, tcd);
574  }
575  }
576 
577  // The point at the south pole.
578  pos = { 0.0f, 0.0f, -radius };
579  if (mOutside)
580  {
581  nor = { 0.0f, 0.0f, -1.0f };
582  }
583  else
584  {
585  nor = { 0.0f, 0.0f, 1.0f };
586  }
587  basis[0] = nor;
588  ComputeOrthogonalComplement(1, basis);
589  tcd = { 0.5f, 0.5f };
590  SetPosition(i, pos);
591  SetNormal(i, nor);
592  SetTangent(i, basis[1]);
593  SetBinormal(i, basis[2]);
594  SetTCoord(i, tcd);
595  ++i;
596 
597  // The point at the north pole.
598  pos = { 0.0f, 0.0f, radius };
599  if (mOutside)
600  {
601  nor = { 0.0f, 0.0f, 1.0f };
602  }
603  else
604  {
605  nor = { 0.0f, 0.0f, -1.0f };
606  }
607  basis[0] = nor;
608  ComputeOrthogonalComplement(1, basis);
609  tcd = { 0.5f, 1.0f };
610  SetPosition(i, pos);
611  SetNormal(i, nor);
612  SetTangent(i, basis[1]);
613  SetBinormal(i, basis[2]);
614  SetTCoord(i, tcd);
615 
616  // Generate indices (outside view).
617  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
618  if (!ibuffer)
619  {
620  return nullptr;
621  }
622  unsigned int t = 0;
623  for (unsigned int z = 0, zStart = 0; z < zsm3; ++z)
624  {
625  unsigned int i0 = zStart;
626  unsigned int i1 = i0 + 1;
627  zStart += rsp1;
628  unsigned int i2 = zStart;
629  unsigned int i3 = i2 + 1;
630  for (i = 0; i < numRadialSamples; ++i, ++i0, ++i1, ++i2, ++i3)
631  {
632  ibuffer->SetTriangle(t++, i0, i1, i2);
633  ibuffer->SetTriangle(t++, i1, i3, i2);
634  }
635  }
636 
637  // The south pole triangles (outside view).
638  unsigned int numVerticesM2 = numVertices - 2;
639  for (i = 0; i < numRadialSamples; ++i, ++t)
640  {
641  ibuffer->SetTriangle(t, i, numVerticesM2, i+1);
642  }
643 
644  // The north pole triangles (outside view).
645  unsigned int numVerticesM1 = numVertices - 1, offset = zsm3*rsp1;
646  for (i = 0; i < numRadialSamples; ++i, ++t)
647  {
648  ibuffer->SetTriangle(t, i+offset, i+1+offset, numVerticesM1);
649  }
650 
651  if (!mOutside)
652  {
653  ReverseTriangleOrder(ibuffer.get());
654  }
655 
656  // Create the mesh.
657  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
658  if (visual)
659  {
660  visual->UpdateModelBound();
661 
662  // The duplication of vertices at the seam cause the automatically
663  // generated bounding volume to be slightly off center. Reset the
664  // bound to use the true information.
665  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
666  visual->modelBound.SetRadius(radius);
667  }
668  return visual;
669 }
670 
671 std::shared_ptr<Visual> MeshFactory::CreateTorus(
672  unsigned int numCircleSamples, unsigned int numRadialSamples,
673  float outerRadius, float innerRadius)
674 {
675  // Quantities derived from inputs.
676  float invCS = 1.0f/static_cast<float>(numCircleSamples);
677  float invRS = 1.0f/static_cast<float>(numRadialSamples);
678  unsigned int numVertices = (numCircleSamples + 1)*(numRadialSamples + 1);
679  unsigned int numTriangles = 2 * numCircleSamples*numRadialSamples;
680 
681  // Generate geometry.
682  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
683  if (!vbuffer)
684  {
685  return nullptr;
686  }
687 
688  Vector3<float> pos, nor, basis[3];
689  Vector2<float> tcd;
690 
691  // Generate an open cylinder that is warped into a torus.
692  unsigned int i = 0;
693  for (unsigned int c = 0; c < numCircleSamples; ++c)
694  {
695  // Compute center point on torus circle at specified angle.
696  float circleFraction = static_cast<float>(c)*invCS; // in [0,1)
697  float theta = circleFraction*(float)GTE_C_TWO_PI;
698  float cosTheta = cos(theta);
699  float sinTheta = sin(theta);
700  Vector3<float> radial{ cosTheta, sinTheta, 0.0f };
701  Vector3<float> torusMiddle = outerRadius*radial;
702 
703  // Compute slice vertices with duplication at endpoint.
704  for (unsigned int r = 0; r <= numRadialSamples; ++r, ++i)
705  {
706  float radialFraction = static_cast<float>(r)*invRS; // in [0,1)
707  float phi = radialFraction*(float)GTE_C_TWO_PI;
708  float cosPhi = cos(phi);
709  float sinPhi = sin(phi);
710  nor = cosPhi*radial + sinPhi*Vector3<float>::Unit(2);
711  pos = torusMiddle + innerRadius*nor;
712  if (!mOutside)
713  {
714  nor = -nor;
715  }
716 
717  basis[0] = nor;
718  ComputeOrthogonalComplement(1, basis);
719  tcd = { radialFraction, circleFraction };
720 
721  SetPosition(i, pos);
722  SetNormal(i, nor);
723  SetTangent(i, basis[1]);
724  SetBinormal(i, basis[2]);
725  SetTCoord(i, tcd);
726  }
727  }
728 
729  // Duplicate the cylinder ends to form a torus.
730  for (unsigned int r = 0; r <= numRadialSamples; ++r, ++i)
731  {
732  Position(i) = Position(r);
733  if (mNormals)
734  {
735  Normal(i) = Normal(r);
736  }
737  if (mTangents)
738  {
739  Tangent(i) = Tangent(r);
740  }
741  if (mBitangents)
742  {
743  Bitangent(i) = Bitangent(r);
744  }
745  for (unsigned int unit = 0; unit < VA_MAX_TCOORD_UNITS; ++unit)
746  {
747  if (mAssignTCoords[unit])
748  {
749  TCoord(unit, i) = Vector2<float>{ TCoord(unit, r)[0], 1.0f };
750  }
751  }
752  }
753 
754  // Generate indices (outside view).
755  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
756  if (!ibuffer)
757  {
758  return nullptr;
759  }
760  unsigned int t = 0;
761  for (unsigned int c = 0, cStart = 0; c < numCircleSamples; ++c)
762  {
763  unsigned int i0 = cStart;
764  unsigned int i1 = i0 + 1;
765  cStart += numRadialSamples + 1;
766  unsigned int i2 = cStart;
767  unsigned int i3 = i2 + 1;
768  for (i = 0; i < numRadialSamples; ++i, ++i0, ++i1, ++i2, ++i3)
769  {
770  ibuffer->SetTriangle(t++, i0, i2, i1);
771  ibuffer->SetTriangle(t++, i1, i2, i3);
772  }
773  }
774 
775  if (!mOutside)
776  {
777  ReverseTriangleOrder(ibuffer.get());
778  }
779 
780  // Create the mesh.
781  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
782  if (visual)
783  {
784  visual->UpdateModelBound();
785 
786  // The duplication of vertices at the seam cause the automatically
787  // generated bounding volume to be slightly off center. Reset the
788  // bound to use the true information.
789  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
790  visual->modelBound.SetRadius(outerRadius);
791  }
792  return visual;
793 }
794 
795 std::shared_ptr<Visual> MeshFactory::CreateTetrahedron()
796 {
797  float const sqrt2Div3 = sqrt(2.0f)/3.0f;
798  float const sqrt6Div3 = sqrt(6.0f)/3.0f;
799  float const oneThird = 1.0f/3.0f;
800  unsigned int const numVertices = 4;
801  unsigned int const numTriangles = 4;
802 
803  // Generate geometry.
804  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
805  if (!vbuffer)
806  {
807  return nullptr;
808  }
809 
810  Vector3<float> pos, nor, basis[3];
811 
812  Position(0) = { 0.0f, 0.0f, 1.0f };
813  Position(1) = { 2.0f*sqrt2Div3, 0.0f, -oneThird };
814  Position(2) = { -sqrt2Div3, sqrt6Div3, -oneThird };
815  Position(3) = { -sqrt2Div3, -sqrt6Div3, -oneThird };
816  for (unsigned int i = 0; i < numVertices; ++i)
817  {
818  pos = Position(i);
819  nor = (mOutside ? pos : -pos);
820  SetNormal(i, nor);
821  basis[0] = nor;
822  ComputeOrthogonalComplement(1, basis);
823  SetTangent(i, basis[1]);
824  SetBinormal(i, basis[2]);
825  SetPlatonicTCoord(i, pos);
826  }
827 
828  // Generate indices (outside view).
829  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
830  if (!ibuffer)
831  {
832  return nullptr;
833  }
834  ibuffer->SetTriangle(0, 0, 1, 2);
835  ibuffer->SetTriangle(1, 0, 2, 3);
836  ibuffer->SetTriangle(2, 0, 3, 1);
837  ibuffer->SetTriangle(3, 1, 3, 2);
838 
839  if (!mOutside)
840  {
841  ReverseTriangleOrder(ibuffer.get());
842  }
843 
844  // Create the mesh.
845  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
846  if (visual)
847  {
848  // The bound is the unit sphere.
849  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
850  visual->modelBound.SetRadius(1.0f);
851  }
852  return visual;
853 }
854 
855 std::shared_ptr<Visual> MeshFactory::CreateHexahedron()
856 {
857  float const sqrtThird = sqrt(1.0f/3.0f);
858  unsigned int const numVertices = 8;
859  unsigned int const numTriangles = 12;
860 
861  // Generate geometry.
862  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
863  if (!vbuffer)
864  {
865  return nullptr;
866  }
867 
868  Vector3<float> pos, nor, basis[3];
869 
870  Position(0) = { -sqrtThird, -sqrtThird, -sqrtThird };
871  Position(1) = { sqrtThird, -sqrtThird, -sqrtThird };
872  Position(2) = { sqrtThird, sqrtThird, -sqrtThird };
873  Position(3) = { -sqrtThird, sqrtThird, -sqrtThird };
874  Position(4) = { -sqrtThird, -sqrtThird, sqrtThird };
875  Position(5) = { sqrtThird, -sqrtThird, sqrtThird };
876  Position(6) = { sqrtThird, sqrtThird, sqrtThird };
877  Position(7) = { -sqrtThird, sqrtThird, sqrtThird };
878  for (unsigned int i = 0; i < numVertices; ++i)
879  {
880  pos = Position(i);
881  nor = (mOutside ? pos : -pos);
882  SetNormal(i, nor);
883  basis[0] = nor;
884  ComputeOrthogonalComplement(1, basis);
885  SetTangent(i, basis[1]);
886  SetBinormal(i, basis[2]);
887  SetPlatonicTCoord(i, pos);
888  }
889 
890  // Generate indices (outside view).
891  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
892  if (!ibuffer)
893  {
894  return nullptr;
895  }
896  ibuffer->SetTriangle(0, 0, 3, 2);
897  ibuffer->SetTriangle( 1, 0, 2, 1);
898  ibuffer->SetTriangle( 2, 0, 1, 5);
899  ibuffer->SetTriangle( 3, 0, 5, 4);
900  ibuffer->SetTriangle( 4, 0, 4, 7);
901  ibuffer->SetTriangle( 5, 0, 7, 3);
902  ibuffer->SetTriangle( 6, 6, 5, 1);
903  ibuffer->SetTriangle( 7, 6, 1, 2);
904  ibuffer->SetTriangle( 8, 6, 2, 3);
905  ibuffer->SetTriangle( 9, 6, 3, 7);
906  ibuffer->SetTriangle(10, 6, 7, 4);
907  ibuffer->SetTriangle(11, 6, 4, 5);
908 
909  if (!mOutside)
910  {
911  ReverseTriangleOrder(ibuffer.get());
912  }
913 
914  // Create the mesh.
915  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
916  if (visual)
917  {
918  // The bound is the unit sphere.
919  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
920  visual->modelBound.SetRadius(1.0f);
921  }
922  return visual;
923 }
924 
925 std::shared_ptr<Visual> MeshFactory::CreateOctahedron()
926 {
927  unsigned int const numVertices = 6;
928  unsigned int const numTriangles = 8;
929 
930  // Generate geometry.
931  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
932  if (!vbuffer)
933  {
934  return nullptr;
935  }
936 
937  Vector3<float> pos, nor, basis[3];
938 
939  Position(0) = { 1.0f, 0.0f, 0.0f };
940  Position(1) = { -1.0f, 0.0f, 0.0f };
941  Position(2) = { 0.0f, 1.0f, 0.0f };
942  Position(3) = { 0.0f, -1.0f, 0.0f };
943  Position(4) = { 0.0f, 0.0f, 1.0f };
944  Position(5) = { 0.0f, 0.0f, -1.0f };
945  for (unsigned int i = 0; i < numVertices; ++i)
946  {
947  pos = Position(i);
948  nor = (mOutside ? pos : -pos);
949  SetNormal(i, nor);
950  basis[0] = nor;
951  ComputeOrthogonalComplement(1, basis);
952  SetTangent(i, basis[1]);
953  SetBinormal(i, basis[2]);
954  SetPlatonicTCoord(i, pos);
955  }
956 
957  // Generate indices (outside view).
958  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
959  if (!ibuffer)
960  {
961  return nullptr;
962  }
963  ibuffer->SetTriangle(0, 4, 0, 2);
964  ibuffer->SetTriangle(1, 4, 2, 1);
965  ibuffer->SetTriangle(2, 4, 1, 3);
966  ibuffer->SetTriangle(3, 4, 3, 0);
967  ibuffer->SetTriangle(4, 5, 2, 0);
968  ibuffer->SetTriangle(5, 5, 1, 2);
969  ibuffer->SetTriangle(6, 5, 3, 1);
970  ibuffer->SetTriangle(7, 5, 0, 3);
971 
972  if (!mOutside)
973  {
974  ReverseTriangleOrder(ibuffer.get());
975  }
976 
977  // Create the mesh.
978  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
979  if (visual)
980  {
981  // The bound is the unit sphere.
982  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
983  visual->modelBound.SetRadius(1.0f);
984  }
985  return visual;
986 }
987 
988 std::shared_ptr<Visual> MeshFactory::CreateDodecahedron()
989 {
990  float const a = 1.0f/sqrt(3.0f);
991  float const b = sqrt((3.0f - sqrt(5.0f))/6.0f);
992  float const c = sqrt((3.0f + sqrt(5.0f))/6.0f);
993  unsigned int const numVertices = 20;
994  unsigned int const numTriangles = 36;
995 
996  // Generate geometry.
997  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
998  if (!vbuffer)
999  {
1000  return nullptr;
1001  }
1002 
1003  Vector3<float> pos, nor, basis[3];
1004 
1005  Position(0) = { a, a, a };
1006  Position(1) = { a, a, -a };
1007  Position(2) = { a, -a, a };
1008  Position(3) = { a, -a, -a };
1009  Position(4) = { -a, a, a };
1010  Position(5) = { -a, a, -a };
1011  Position(6) = { -a, -a, a };
1012  Position(7) = { -a, -a, -a };
1013  Position(8) = { b, c, 0.0f };
1014  Position(9) = { -b, c, 0.0f };
1015  Position(10) = { b, -c, 0.0f };
1016  Position(11) = { -b, -c, 0.0f };
1017  Position(12) = { c, 0.0f, b };
1018  Position(13) = { c, 0.0f, -b };
1019  Position(14) = { -c, 0.0f, b };
1020  Position(15) = { -c, 0.0f, -b };
1021  Position(16) = { 0.0f, b, c };
1022  Position(17) = { 0.0f, -b, c };
1023  Position(18) = { 0.0f, b, -c };
1024  Position(19) = { 0.0f, -b, -c };
1025  for (unsigned int i = 0; i < numVertices; ++i)
1026  {
1027  pos = Position(i);
1028  nor = (mOutside ? pos : -pos);
1029  SetNormal(i, nor);
1030  basis[0] = nor;
1031  ComputeOrthogonalComplement(1, basis);
1032  SetTangent(i, basis[1]);
1033  SetBinormal(i, basis[2]);
1034  SetPlatonicTCoord(i, pos);
1035  }
1036 
1037  // Generate indices.
1038  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
1039  if (!ibuffer)
1040  {
1041  return nullptr;
1042  }
1043  ibuffer->SetTriangle(0, 0, 8, 9);
1044  ibuffer->SetTriangle( 1, 0, 9, 4);
1045  ibuffer->SetTriangle( 2, 0, 4, 16);
1046  ibuffer->SetTriangle( 3, 0, 12, 13);
1047  ibuffer->SetTriangle( 4, 0, 13, 1);
1048  ibuffer->SetTriangle( 5, 0, 1, 8);
1049  ibuffer->SetTriangle( 6, 0, 16, 17);
1050  ibuffer->SetTriangle( 7, 0, 17, 2);
1051  ibuffer->SetTriangle( 8, 0, 2, 12);
1052  ibuffer->SetTriangle( 9, 8, 1, 18);
1053  ibuffer->SetTriangle(10, 8, 18, 5);
1054  ibuffer->SetTriangle(11, 8, 5, 9);
1055  ibuffer->SetTriangle(12, 12, 2, 10);
1056  ibuffer->SetTriangle(13, 12, 10, 3);
1057  ibuffer->SetTriangle(14, 12, 3, 13);
1058  ibuffer->SetTriangle(15, 16, 4, 14);
1059  ibuffer->SetTriangle(16, 16, 14, 6);
1060  ibuffer->SetTriangle(17, 16, 6, 17);
1061  ibuffer->SetTriangle(18, 9, 5, 15);
1062  ibuffer->SetTriangle(19, 9, 15, 14);
1063  ibuffer->SetTriangle(20, 9, 14, 4);
1064  ibuffer->SetTriangle(21, 6, 11, 10);
1065  ibuffer->SetTriangle(22, 6, 10, 2);
1066  ibuffer->SetTriangle(23, 6, 2, 17);
1067  ibuffer->SetTriangle(24, 3, 19, 18);
1068  ibuffer->SetTriangle(25, 3, 18, 1);
1069  ibuffer->SetTriangle(26, 3, 1, 13);
1070  ibuffer->SetTriangle(27, 7, 15, 5);
1071  ibuffer->SetTriangle(28, 7, 5, 18);
1072  ibuffer->SetTriangle(29, 7, 18, 19);
1073  ibuffer->SetTriangle(30, 7, 11, 6);
1074  ibuffer->SetTriangle(31, 7, 6, 14);
1075  ibuffer->SetTriangle(32, 7, 14, 15);
1076  ibuffer->SetTriangle(33, 7, 19, 3);
1077  ibuffer->SetTriangle(34, 7, 3, 10);
1078  ibuffer->SetTriangle(35, 7, 10, 11);
1079 
1080  if (!mOutside)
1081  {
1082  ReverseTriangleOrder(ibuffer.get());
1083  }
1084 
1085  // Create the mesh.
1086  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
1087  if (visual)
1088  {
1089  // The bound is the unit sphere.
1090  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
1091  visual->modelBound.SetRadius(1.0f);
1092  }
1093  return visual;
1094 }
1095 
1096 std::shared_ptr<Visual> MeshFactory::CreateIcosahedron()
1097 {
1098  float const goldenRatio = 0.5f*(1.0f + sqrt(5.0f));
1099  float const invRoot = 1.0f/sqrt(1.0f + goldenRatio*goldenRatio);
1100  float const u = goldenRatio*invRoot;
1101  float const v = invRoot;
1102  unsigned int const numVertices = 12;
1103  unsigned int const numTriangles = 20;
1104 
1105  // Generate geometry.
1106  std::shared_ptr<VertexBuffer> vbuffer = CreateVBuffer(numVertices);
1107  if (!vbuffer)
1108  {
1109  return nullptr;
1110  }
1111 
1112  Vector3<float> pos, nor, basis[3];
1113 
1114  Position(0) = { u, v, 0.0f };
1115  Position(1) = { -u, v, 0.0f };
1116  Position(2) = { u, -v, 0.0f };
1117  Position(3) = { -u, -v, 0.0f };
1118  Position(4) = { v, 0.0f, u };
1119  Position(5) = { v, 0.0f, -u };
1120  Position(6) = { -v, 0.0f, u };
1121  Position(7) = { -v, 0.0f, -u };
1122  Position(8) = { 0.0f, u, v };
1123  Position(9) = { 0.0f, -u, v };
1124  Position(10) = { 0.0f, u, -v };
1125  Position(11) = { 0.0f, -u, -v };
1126  for (unsigned int i = 0; i < numVertices; ++i)
1127  {
1128  pos = Position(i);
1129  nor = (mOutside ? pos : -pos);
1130  SetNormal(i, nor);
1131  basis[0] = nor;
1132  ComputeOrthogonalComplement(1, basis);
1133  SetTangent(i, basis[1]);
1134  SetBinormal(i, basis[2]);
1135  SetPlatonicTCoord(i, pos);
1136  }
1137 
1138  // Generate indices.
1139  std::shared_ptr<IndexBuffer> ibuffer = CreateIBuffer(numTriangles);
1140  if (!ibuffer)
1141  {
1142  return nullptr;
1143  }
1144  ibuffer->SetTriangle(0, 0, 8, 4);
1145  ibuffer->SetTriangle( 1, 0, 5, 10);
1146  ibuffer->SetTriangle( 2, 2, 4, 9);
1147  ibuffer->SetTriangle( 3, 2, 11, 5);
1148  ibuffer->SetTriangle( 4, 1, 6, 8);
1149  ibuffer->SetTriangle( 5, 1, 10, 7);
1150  ibuffer->SetTriangle( 6, 3, 9, 6);
1151  ibuffer->SetTriangle( 7, 3, 7, 11);
1152  ibuffer->SetTriangle( 8, 0, 10, 8);
1153  ibuffer->SetTriangle( 9, 1, 8, 10);
1154  ibuffer->SetTriangle(10, 2, 9, 11);
1155  ibuffer->SetTriangle(11, 3, 11, 9);
1156  ibuffer->SetTriangle(12, 4, 2, 0);
1157  ibuffer->SetTriangle(13, 5, 0, 2);
1158  ibuffer->SetTriangle(14, 6, 1, 3);
1159  ibuffer->SetTriangle(15, 7, 3, 1);
1160  ibuffer->SetTriangle(16, 8, 6, 4);
1161  ibuffer->SetTriangle(17, 9, 4, 6);
1162  ibuffer->SetTriangle(18, 10, 5, 7);
1163  ibuffer->SetTriangle(19, 11, 7, 5);
1164 
1165  if (!mOutside)
1166  {
1167  ReverseTriangleOrder(ibuffer.get());
1168  }
1169 
1170  // Create the mesh.
1171  std::shared_ptr<Visual> visual = std::make_shared<Visual>(vbuffer, ibuffer);
1172  if (visual)
1173  {
1174  // The bound is the unit sphere.
1175  visual->modelBound.SetCenter({ 0.0f, 0.0f, 0.0f, 1.0f });
1176  visual->modelBound.SetRadius(1.0f);
1177  }
1178  return visual;
1179 }
1180 
1181 std::shared_ptr<VertexBuffer> MeshFactory::CreateVBuffer(unsigned int numVertices)
1182 {
1183  auto vbuffer = std::make_shared<VertexBuffer>(mVFormat, numVertices);
1184  if (vbuffer)
1185  {
1186  // Get the position channel.
1187  mPositions = GetGeometricChannel(vbuffer, VA_POSITION, 1.0f);
1188  if (!mPositions)
1189  {
1190  LogError("Positions are required.");
1191  return nullptr;
1192  }
1193 
1194  // Get the optional geometric channels.
1195  mNormals = GetGeometricChannel(vbuffer, VA_NORMAL, 0.0f);
1196  mTangents = GetGeometricChannel(vbuffer, VA_TANGENT, 0.0f);
1197  mBitangents = GetGeometricChannel(vbuffer, VA_BINORMAL, 0.0f);
1198 
1199  // Get texture coordinate channels that are to be assigned values.
1200  // Clear the mAssignTCoords element in case any elements were set by a
1201  // previous mesh factory creation call.
1202  std::set<DFType> required;
1203  required.insert(DF_R32G32_FLOAT);
1204  for (unsigned int unit = 0; unit < VA_MAX_TCOORD_UNITS; ++unit)
1205  {
1206  mTCoords[unit] = vbuffer->GetChannel(VA_TEXCOORD, unit, required);
1207  if (mTCoords[unit])
1208  {
1209  mAssignTCoords[unit] = true;
1210  }
1211  else
1212  {
1213  mAssignTCoords[unit] = false;
1214  }
1215  }
1216 
1217  vbuffer->SetUsage(mVBUsage);
1218  }
1219  return vbuffer;
1220 }
1221 
1222 std::shared_ptr<IndexBuffer> MeshFactory::CreateIBuffer(unsigned int numTriangles)
1223 {
1224  auto ibuffer = std::make_shared<IndexBuffer>(IP_TRIMESH, numTriangles, mIndexSize);
1225  if (ibuffer)
1226  {
1227  ibuffer->SetUsage(mIBUsage);
1228  }
1229  return ibuffer;
1230 }
1231 
1233  std::shared_ptr<VertexBuffer> const& vbuffer, VASemantic semantic,
1234  float w)
1235 {
1236  char* channel = nullptr;
1237  int index = mVFormat.GetIndex(semantic, 0);
1238  if (index >= 0)
1239  {
1240  channel = vbuffer->GetChannel(semantic, 0, std::set<DFType>());
1241  LogAssert(channel != 0, "Unexpected condition.");
1242  if (mVFormat.GetType(index) == DF_R32G32B32A32_FLOAT)
1243  {
1244  // Fill in the w-components.
1245  int const numVertices = vbuffer->GetNumElements();
1246  for (int i = 0; i < numVertices; ++i)
1247  {
1248  float* tuple4 = reinterpret_cast<float*>(
1249  channel + i*mVFormat.GetVertexSize());
1250  tuple4[3] = w;
1251  }
1252  }
1253  }
1254  return channel;
1255 }
1256 
1257 void MeshFactory::SetPosition(unsigned int i, Vector3<float> const& pos)
1258 {
1259  Position(i) = pos;
1260 }
1261 
1262 void MeshFactory::SetNormal(unsigned int i, Vector3<float> const& nor)
1263 {
1264  if (mNormals)
1265  {
1266  Normal(i) = nor;
1267  }
1268 }
1269 
1270 void MeshFactory::SetTangent(unsigned int i, Vector3<float> const& tan)
1271 {
1272  if (mTangents)
1273  {
1274  Tangent(i) = tan;
1275  }
1276 }
1277 
1278 void MeshFactory::SetBinormal(unsigned int i, Vector3<float> const& bin)
1279 {
1280  if (mBitangents)
1281  {
1282  Bitangent(i) = bin;
1283  }
1284 }
1285 
1286 void MeshFactory::SetTCoord(unsigned int i, Vector2<float> const& tcd)
1287 {
1288  for (unsigned int unit = 0; unit < VA_MAX_TCOORD_UNITS; ++unit)
1289  {
1290  if (mAssignTCoords[unit])
1291  {
1292  TCoord(unit, i) = tcd;
1293  }
1294  }
1295 }
1296 
1297 void MeshFactory::SetPlatonicTCoord(unsigned int i, Vector3<float> const& pos)
1298 {
1299  Vector2<float> tcd;
1300  if (std::abs(pos[2]) < 1.0f)
1301  {
1302  tcd[0] = 0.5f*(1.0f +
1303  Function<float>::ATan2(pos[1], pos[0])* (float)GTE_C_INV_PI );
1304  }
1305  else
1306  {
1307  tcd[0] = 0.5f;
1308  }
1309 
1310  tcd[1] = Function<float>::ACos(pos[2]) * (float)GTE_C_INV_PI;
1311 
1312  for (int unit = 0; unit < VA_MAX_TCOORD_UNITS; ++unit)
1313  {
1314  if (mAssignTCoords[unit])
1315  {
1316  TCoord(unit, i) = tcd;
1317  }
1318  }
1319 }
1320 
1322 {
1323  unsigned int const numTriangles = ibuffer->GetNumPrimitives();
1324  for (unsigned int t = 0; t < numTriangles; ++t)
1325  {
1326  unsigned int v0, v1, v2;
1327  ibuffer->GetTriangle(t, v0, v1, v2);
1328  ibuffer->SetTriangle(t, v0, v2, v1);
1329  }
1330 }
void ReverseTriangleOrder(IndexBuffer *ibuffer)
std::shared_ptr< Visual > CreateHexahedron()
Vector3< float > & Normal(unsigned int i)
Vector< N, Real > center
Definition: GteRectangle.h:38
void SetPosition(unsigned int i, Vector3< float > const &pos)
VA_TEXCOORD
unsigned int GetNumElements() const
Definition: GteResource.h:106
std::shared_ptr< Visual > CreateCylinderClosed(unsigned int numAxisSamples, unsigned int numRadialSamples, float radius, float height)
Vector3< float > & Bitangent(unsigned int i)
std::shared_ptr< IndexBuffer > CreateIBuffer(unsigned int numTriangles)
VA_MAX_TCOORD_UNITS
void SetTangent(unsigned int i, Vector3< float > const &tan)
VA_NORMAL
std::shared_ptr< Visual > CreateRectangle(unsigned int numXSamples, unsigned int numYSamples, float xExtent, float yExtent)
bool SetTriangle(uint32_t i, uint32_t v0, uint32_t v1, uint32_t v2)
unsigned int GetVertexSize() const
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
#define LogAssert(condition, message)
Definition: GteLogger.h:86
IP_TRIMESH
std::shared_ptr< Visual > CreateTorus(unsigned int numCircleSamples, unsigned int numRadialSamples, float outerRadius, float innerRadius)
std::shared_ptr< VertexBuffer > CreateVBuffer(unsigned int numVertices)
IMMUTABLE
Definition: GteResource.h:42
uint32_t GetNumPrimitives() const
void SetBinormal(unsigned int i, Vector3< float > const &bin)
std::shared_ptr< Visual > CreateSphere(unsigned int numZSamples, unsigned int numRadialSamples, float radius)
Vector3< float > & Position(unsigned int i)
std::shared_ptr< Visual > CreateCylinderOpen(unsigned int numAxisSamples, unsigned int numRadialSamples, float radius, float height)
GLfloat GLfloat v1
Definition: glcorearb.h:812
GLfloat angle
Definition: glext.h:6466
void SetPlatonicTCoord(unsigned int i, Vector3< float > const &pos)
int GetIndex(VASemantic semantic, unsigned int unit) const
std::shared_ptr< Visual > CreateTetrahedron()
Vector2< float > & TCoord(unsigned int unit, unsigned int i)
IndexAttribute indexAttribute
Definition: GteMesh.h:90
bool mAssignTCoords[VA_MAX_TCOORD_UNITS]
GLint GLenum GLint x
Definition: glcorearb.h:404
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:852
void SetTCoord(unsigned int i, Vector2< float > const &tcd)
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1217
std::shared_ptr< Visual > CreateOctahedron()
std::shared_ptr< Visual > CreateTriangle(unsigned int numSamples, float xExtent, float yExtent)
std::vector< VertexAttribute > vertexAttributes
Definition: GteMesh.h:89
const GLubyte * c
Definition: glext.h:11671
VA_POSITION
GLfixed y1
Definition: glext.h:4952
static Real ACos(Real const &x)
Definition: GteFunctions.h:221
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
#define LogError(message)
Definition: GteLogger.h:92
std::shared_ptr< Visual > CreateBox(float xExtent, float yExtent, float zExtent)
Vector3< float > & Tangent(unsigned int i)
DF_R32G32B32A32_FLOAT
Definition: GteDataFormat.h:20
VertexFormat mVFormat
VA_BINORMAL
std::shared_ptr< Visual > CreateDodecahedron()
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
GLfloat v0
Definition: glcorearb.h:811
GLdouble GLdouble t
Definition: glext.h:239
uint32_t numVertices
Definition: GteMesh.h:87
GLint GLsizei GLsizei height
Definition: glcorearb.h:98
Resource::Usage mIBUsage
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1217
VA_TANGENT
std::shared_ptr< Visual > CreateIcosahedron()
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:843
static Real ATan2(Real const &y, Real const &x)
Definition: GteFunctions.h:383
std::shared_ptr< Visual > CreateDisk(unsigned int numShellSamples, unsigned int numRadialSamples, float radius)
DF_R32G32_FLOAT
Definition: GteDataFormat.h:20
const GLdouble * v
Definition: glcorearb.h:832
GLboolean r
Definition: glcorearb.h:1217
GLdouble s
Definition: glext.h:231
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:813
GLuint index
Definition: glcorearb.h:781
GLuint GLfloat GLfloat y0
Definition: glext.h:9013
GLfloat f
Definition: glcorearb.h:1921
Real ComputeOrthogonalComplement(int numInputs, Vector2< Real > *v, bool robust=false)
Definition: GteVector2.h:123
DFType GetType(int i) const
GLintptr offset
Definition: glcorearb.h:660
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:867
char * GetGeometricChannel(std::shared_ptr< VertexBuffer > const &vbuffer, VASemantic semantic, float w)
bool GetTriangle(uint32_t i, uint32_t &v0, uint32_t &v1, uint32_t &v2) const
void SetNormal(unsigned int i, Vector3< float > const &nor)
#define GTE_C_INV_PI
Definition: GteConstants.h:21
uint32_t numTriangles
Definition: GteMesh.h:88
#define GTE_C_TWO_PI
Definition: GteConstants.h:20
GLint y
Definition: glcorearb.h:98
char * mTCoords[VA_MAX_TCOORD_UNITS]
static Vector Unit(int d)
Definition: GteVector.h:303
Resource::Usage mVBUsage


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