sphereMesh.cpp
Engine/source/math/util/sphereMesh.cpp
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