sphereMesh.cpp

Engine/source/math/util/sphereMesh.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "math/util/sphereMesh.h"
 25
 26SphereMesh::SphereMesh(U32 baseType)
 27{
 28   VECTOR_SET_ASSOCIATION(mDetails);
 29
 30   switch(baseType)
 31   {
 32      case Tetrahedron:
 33         mDetails.push_back(createTetrahedron());
 34         break;
 35
 36      case Octahedron:
 37         mDetails.push_back(createOctahedron());
 38         break;
 39
 40      case Icosahedron:
 41         mDetails.push_back(createIcosahedron());
 42         break;
 43   }
 44   calcNormals(mDetails[0]);
 45}
 46
 47//------------------------------------------------------------------------------
 48
 49SphereMesh::TriangleMesh * SphereMesh::createTetrahedron()
 50{
 51   const F32 sqrt3 = 0.5773502692f;
 52
 53   static Point3F spherePnts[] = {
 54      Point3F( sqrt3, sqrt3, sqrt3 ),
 55      Point3F(-sqrt3,-sqrt3, sqrt3 ),
 56      Point3F(-sqrt3, sqrt3,-sqrt3 ),
 57      Point3F( sqrt3,-sqrt3,-sqrt3 )
 58   };
 59
 60   static Triangle tetrahedron[] = {
 61      Triangle(spherePnts[0], spherePnts[1], spherePnts[2]),
 62      Triangle(spherePnts[0], spherePnts[3], spherePnts[1]),
 63      Triangle(spherePnts[2], spherePnts[1], spherePnts[3]),
 64      Triangle(spherePnts[3], spherePnts[0], spherePnts[2]),
 65   };
 66
 67   static TriangleMesh tetrahedronMesh = {
 68      Tetrahedron,
 69      &tetrahedron[0]
 70   };
 71
 72   return(&tetrahedronMesh);
 73}
 74
 75//------------------------------------------------------------------------------
 76
 77SphereMesh::TriangleMesh * SphereMesh::createOctahedron()
 78{
 79   //
 80   static Point3F spherePnts[] = {
 81      Point3F( 1, 0, 0),
 82      Point3F(-1, 0, 0),
 83      Point3F( 0, 1, 0),
 84      Point3F( 0,-1, 0),
 85      Point3F( 0, 0, 1),
 86      Point3F( 0, 0,-1)
 87   };
 88
 89   //
 90   static Triangle octahedron[] = {
 91      Triangle(spherePnts[0], spherePnts[4], spherePnts[2]),
 92      Triangle(spherePnts[2], spherePnts[4], spherePnts[1]),
 93      Triangle(spherePnts[1], spherePnts[4], spherePnts[3]),
 94      Triangle(spherePnts[3], spherePnts[4], spherePnts[0]),
 95      Triangle(spherePnts[0], spherePnts[2], spherePnts[5]),
 96      Triangle(spherePnts[2], spherePnts[1], spherePnts[5]),
 97      Triangle(spherePnts[1], spherePnts[3], spherePnts[5]),
 98      Triangle(spherePnts[3], spherePnts[0], spherePnts[5])
 99   };
100
101   //
102   static TriangleMesh octahedronMesh = {
103      Octahedron,
104      &octahedron[0]
105   };
106
107   return(&octahedronMesh);
108}
109
110SphereMesh::TriangleMesh * SphereMesh::createIcosahedron()
111{
112   const F32 tau = 0.8506508084f;
113   const F32 one = 0.5257311121f;
114
115   static Point3F spherePnts[] = {
116      Point3F( tau, one,   0),
117      Point3F(-tau, one,   0),
118      Point3F(-tau,-one,   0),
119      Point3F( tau,-one,   0),
120      Point3F( one,   0, tau),
121      Point3F( one,   0,-tau),
122      Point3F(-one,   0,-tau),
123      Point3F(-one,   0, tau),
124      Point3F(   0, tau, one),
125      Point3F(   0,-tau, one),
126      Point3F(   0,-tau,-one),
127      Point3F(   0, tau,-one),
128   };
129
130   static Triangle icosahedron[] = {
131      Triangle(spherePnts[4],  spherePnts[8],  spherePnts[7]),
132      Triangle(spherePnts[4],  spherePnts[7],  spherePnts[9]),
133      Triangle(spherePnts[5],  spherePnts[6],  spherePnts[11]),
134      Triangle(spherePnts[5],  spherePnts[10], spherePnts[6]),
135      Triangle(spherePnts[0],  spherePnts[4],  spherePnts[3]),
136      Triangle(spherePnts[0],  spherePnts[3],  spherePnts[5]),
137      Triangle(spherePnts[2],  spherePnts[7],  spherePnts[1]),
138      Triangle(spherePnts[2],  spherePnts[1],  spherePnts[6]),
139      Triangle(spherePnts[8],  spherePnts[0],  spherePnts[11]),
140      Triangle(spherePnts[8],  spherePnts[11], spherePnts[1]),
141      Triangle(spherePnts[9],  spherePnts[10], spherePnts[3]),
142      Triangle(spherePnts[9],  spherePnts[2],  spherePnts[10]),
143      Triangle(spherePnts[8],  spherePnts[4],  spherePnts[0]),
144      Triangle(spherePnts[11], spherePnts[0],  spherePnts[5]),
145      Triangle(spherePnts[4],  spherePnts[9],  spherePnts[3]),
146      Triangle(spherePnts[5],  spherePnts[3],  spherePnts[10]),
147      Triangle(spherePnts[7],  spherePnts[8],  spherePnts[1]),
148      Triangle(spherePnts[6],  spherePnts[1],  spherePnts[11]),
149      Triangle(spherePnts[7],  spherePnts[2],  spherePnts[9]),
150      Triangle(spherePnts[6],  spherePnts[10], spherePnts[2]),
151   };
152
153   static TriangleMesh icosahedronMesh = {
154      Icosahedron,
155      &icosahedron[0]
156   };
157
158   return(&icosahedronMesh);
159}
160
161//------------------------------------------------------------------------------
162
163void SphereMesh::calcNormals(TriangleMesh * mesh)
164{
165   for(U32 i = 0; i < mesh->numPoly; i++)
166   {
167      Triangle & tri = mesh->poly[i];
168      mCross(tri.pnt[1] - tri.pnt[0], tri.pnt[2] - tri.pnt[0], &tri.normal);
169   }
170}
171
172//------------------------------------------------------------------------------
173
174SphereMesh::~SphereMesh()
175{
176   // level 0 is static data
177   for(U32 i = 1; i < mDetails.size(); i++)
178   {
179      delete [] mDetails[i]->poly;
180      delete mDetails[i];
181   }
182}
183
184//------------------------------------------------------------------------------
185
186const SphereMesh::TriangleMesh * SphereMesh::getMesh(U32 level)
187{
188   AssertFatal(mDetails.size(), "SphereMesh::getMesh: no details!");
189
190   if(level > MaxLevel)
191      level = MaxLevel;
192
193   //
194   while(mDetails.size() <= level)
195      mDetails.push_back(subdivideMesh(mDetails.last()));
196
197   return(mDetails[level]);
198}
199
200SphereMesh::TriangleMesh * SphereMesh::subdivideMesh(TriangleMesh * prevMesh)
201{
202   AssertFatal(prevMesh, "SphereMesh::subdivideMesh: invalid previous mesh level!");
203
204   //
205   TriangleMesh * mesh = new TriangleMesh;
206
207   mesh->numPoly = prevMesh->numPoly * 4;
208   mesh->poly = new Triangle [mesh->numPoly];
209
210   //
211   for(U32 i = 0; i < prevMesh->numPoly; i++)
212   {
213      Triangle * pt = &prevMesh->poly[i];
214      Triangle * nt = &mesh->poly[i*4];
215
216      Point3F a = (pt->pnt[0] + pt->pnt[2]) / 2;
217      Point3F b = (pt->pnt[0] + pt->pnt[1]) / 2;
218      Point3F c = (pt->pnt[1] + pt->pnt[2]) / 2;
219
220      // force the point onto the unit sphere surface
221      a.normalize();
222      b.normalize();
223      c.normalize();
224
225      //
226      nt->pnt[0] = pt->pnt[0];
227      nt->pnt[1] = b;
228      nt->pnt[2] = a;
229      nt++;
230
231      //
232      nt->pnt[0] = b;
233      nt->pnt[1] = pt->pnt[1];
234      nt->pnt[2] = c;
235      nt++;
236
237      //
238      nt->pnt[0] = a;
239      nt->pnt[1] = b;
240      nt->pnt[2] = c;
241      nt++;
242
243      //
244      nt->pnt[0] = a;
245      nt->pnt[1] = c;
246      nt->pnt[2] = pt->pnt[2];
247   }
248
249   calcNormals(mesh);
250   return(mesh);
251}
252