vrshoot

annotate libs/assimp/StandardShapes.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
rev   line source
nuclear@0 1 /*
nuclear@0 2 Open Asset Import Library (assimp)
nuclear@0 3 ----------------------------------------------------------------------
nuclear@0 4
nuclear@0 5 Copyright (c) 2006-2012, assimp team
nuclear@0 6 All rights reserved.
nuclear@0 7
nuclear@0 8 Redistribution and use of this software in source and binary forms,
nuclear@0 9 with or without modification, are permitted provided that the
nuclear@0 10 following conditions are met:
nuclear@0 11
nuclear@0 12 * Redistributions of source code must retain the above
nuclear@0 13 copyright notice, this list of conditions and the
nuclear@0 14 following disclaimer.
nuclear@0 15
nuclear@0 16 * Redistributions in binary form must reproduce the above
nuclear@0 17 copyright notice, this list of conditions and the
nuclear@0 18 following disclaimer in the documentation and/or other
nuclear@0 19 materials provided with the distribution.
nuclear@0 20
nuclear@0 21 * Neither the name of the assimp team, nor the names of its
nuclear@0 22 contributors may be used to endorse or promote products
nuclear@0 23 derived from this software without specific prior
nuclear@0 24 written permission of the assimp team.
nuclear@0 25
nuclear@0 26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 37
nuclear@0 38 ----------------------------------------------------------------------
nuclear@0 39 */
nuclear@0 40
nuclear@0 41 /** @file StandardShapes.cpp
nuclear@0 42 * @brief Implementation of the StandardShapes class
nuclear@0 43 *
nuclear@0 44 * The primitive geometry data comes from
nuclear@0 45 * http://geometrictools.com/Documentation/PlatonicSolids.pdf.
nuclear@0 46 */
nuclear@0 47
nuclear@0 48 #include "AssimpPCH.h"
nuclear@0 49 #include "StandardShapes.h"
nuclear@0 50
nuclear@0 51 namespace Assimp {
nuclear@0 52
nuclear@0 53
nuclear@0 54 # define ADD_TRIANGLE(n0,n1,n2) \
nuclear@0 55 positions.push_back(n0); \
nuclear@0 56 positions.push_back(n1); \
nuclear@0 57 positions.push_back(n2);
nuclear@0 58
nuclear@0 59 # define ADD_PENTAGON(n0,n1,n2,n3,n4) \
nuclear@0 60 if (polygons) \
nuclear@0 61 { \
nuclear@0 62 positions.push_back(n0); \
nuclear@0 63 positions.push_back(n1); \
nuclear@0 64 positions.push_back(n2); \
nuclear@0 65 positions.push_back(n3); \
nuclear@0 66 positions.push_back(n4); \
nuclear@0 67 } \
nuclear@0 68 else \
nuclear@0 69 { \
nuclear@0 70 ADD_TRIANGLE(n0, n1, n2) \
nuclear@0 71 ADD_TRIANGLE(n0, n2, n3) \
nuclear@0 72 ADD_TRIANGLE(n0, n3, n4) \
nuclear@0 73 }
nuclear@0 74
nuclear@0 75 # define ADD_QUAD(n0,n1,n2,n3) \
nuclear@0 76 if (polygons) \
nuclear@0 77 { \
nuclear@0 78 positions.push_back(n0); \
nuclear@0 79 positions.push_back(n1); \
nuclear@0 80 positions.push_back(n2); \
nuclear@0 81 positions.push_back(n3); \
nuclear@0 82 } \
nuclear@0 83 else \
nuclear@0 84 { \
nuclear@0 85 ADD_TRIANGLE(n0, n1, n2) \
nuclear@0 86 ADD_TRIANGLE(n0, n2, n3) \
nuclear@0 87 }
nuclear@0 88
nuclear@0 89
nuclear@0 90 // ------------------------------------------------------------------------------------------------
nuclear@0 91 // Fast subdivision for a mesh whose verts have a magnitude of 1
nuclear@0 92 void Subdivide(std::vector<aiVector3D>& positions)
nuclear@0 93 {
nuclear@0 94 // assume this to be constant - (fixme: must be 1.0? I think so)
nuclear@0 95 const float fl1 = positions[0].Length();
nuclear@0 96
nuclear@0 97 unsigned int origSize = (unsigned int)positions.size();
nuclear@0 98 for (unsigned int i = 0 ; i < origSize ; i+=3)
nuclear@0 99 {
nuclear@0 100 aiVector3D& tv0 = positions[i];
nuclear@0 101 aiVector3D& tv1 = positions[i+1];
nuclear@0 102 aiVector3D& tv2 = positions[i+2];
nuclear@0 103
nuclear@0 104 aiVector3D a = tv0, b = tv1, c = tv2;
nuclear@0 105 aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1;
nuclear@0 106 aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1;
nuclear@0 107 aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1;
nuclear@0 108
nuclear@0 109 tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original
nuclear@0 110 ADD_TRIANGLE(v1, v2, a);
nuclear@0 111 ADD_TRIANGLE(v2, v3, c);
nuclear@0 112 ADD_TRIANGLE(v3, v1, b);
nuclear@0 113 }
nuclear@0 114 }
nuclear@0 115
nuclear@0 116 // ------------------------------------------------------------------------------------------------
nuclear@0 117 // Construct a mesh from given vertex positions
nuclear@0 118 aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
nuclear@0 119 unsigned int numIndices)
nuclear@0 120 {
nuclear@0 121 if (positions.size() & numIndices || positions.empty() || !numIndices)
nuclear@0 122 return NULL;
nuclear@0 123
nuclear@0 124 // Determine which kinds of primitives the mesh consists of
nuclear@0 125 aiMesh* out = new aiMesh();
nuclear@0 126 switch (numIndices)
nuclear@0 127 {
nuclear@0 128 case 1:
nuclear@0 129 out->mPrimitiveTypes = aiPrimitiveType_POINT;
nuclear@0 130 break;
nuclear@0 131 case 2:
nuclear@0 132 out->mPrimitiveTypes = aiPrimitiveType_LINE;
nuclear@0 133 break;
nuclear@0 134 case 3:
nuclear@0 135 out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
nuclear@0 136 break;
nuclear@0 137 default:
nuclear@0 138 out->mPrimitiveTypes = aiPrimitiveType_POLYGON;
nuclear@0 139 break;
nuclear@0 140 };
nuclear@0 141
nuclear@0 142 out->mNumFaces = (unsigned int)positions.size() / numIndices;
nuclear@0 143 out->mFaces = new aiFace[out->mNumFaces];
nuclear@0 144 for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i)
nuclear@0 145 {
nuclear@0 146 aiFace& f = out->mFaces[i];
nuclear@0 147 f.mNumIndices = numIndices;
nuclear@0 148 f.mIndices = new unsigned int[numIndices];
nuclear@0 149 for (unsigned int i = 0; i < numIndices;++i,++a)
nuclear@0 150 f.mIndices[i] = a;
nuclear@0 151 }
nuclear@0 152 out->mNumVertices = (unsigned int)positions.size();
nuclear@0 153 out->mVertices = new aiVector3D[out->mNumVertices];
nuclear@0 154 ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D));
nuclear@0 155 return out;
nuclear@0 156 }
nuclear@0 157
nuclear@0 158 // ------------------------------------------------------------------------------------------------
nuclear@0 159 // Construct a mesh with a specific shape (callback)
nuclear@0 160 aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
nuclear@0 161 std::vector<aiVector3D>&))
nuclear@0 162 {
nuclear@0 163 std::vector<aiVector3D> temp;
nuclear@0 164 unsigned num = (*GenerateFunc)(temp);
nuclear@0 165 return MakeMesh(temp,num);
nuclear@0 166 }
nuclear@0 167
nuclear@0 168 // ------------------------------------------------------------------------------------------------
nuclear@0 169 // Construct a mesh with a specific shape (callback)
nuclear@0 170 aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
nuclear@0 171 std::vector<aiVector3D>&, bool))
nuclear@0 172 {
nuclear@0 173 std::vector<aiVector3D> temp;
nuclear@0 174 unsigned num = (*GenerateFunc)(temp,true);
nuclear@0 175 return MakeMesh(temp,num);
nuclear@0 176 }
nuclear@0 177
nuclear@0 178 // ------------------------------------------------------------------------------------------------
nuclear@0 179 // Construct a mesh with a specific shape (callback)
nuclear@0 180 aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)(
nuclear@0 181 unsigned int,std::vector<aiVector3D>&))
nuclear@0 182 {
nuclear@0 183 std::vector<aiVector3D> temp;
nuclear@0 184 (*GenerateFunc)(num,temp);
nuclear@0 185 return MakeMesh(temp,3);
nuclear@0 186 }
nuclear@0 187
nuclear@0 188 // ------------------------------------------------------------------------------------------------
nuclear@0 189 // Build an incosahedron with points.magnitude == 1
nuclear@0 190 unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
nuclear@0 191 {
nuclear@0 192 positions.reserve(positions.size()+60);
nuclear@0 193
nuclear@0 194 const float t = (1.f + 2.236067977f)/2.f;
nuclear@0 195 const float s = sqrt(1.f + t*t);
nuclear@0 196
nuclear@0 197 const aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s;
nuclear@0 198 const aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s;
nuclear@0 199 const aiVector3D v2 = aiVector3D(t,-1.f, 0.f)/s;
nuclear@0 200 const aiVector3D v3 = aiVector3D(-t,-1.f, 0.f)/s;
nuclear@0 201 const aiVector3D v4 = aiVector3D(1.f, 0.f, t)/s;
nuclear@0 202 const aiVector3D v5 = aiVector3D(1.f, 0.f,-t)/s;
nuclear@0 203 const aiVector3D v6 = aiVector3D(-1.f, 0.f,t)/s;
nuclear@0 204 const aiVector3D v7 = aiVector3D(-1.f, 0.f,-t)/s;
nuclear@0 205 const aiVector3D v8 = aiVector3D(0.f, t, 1.f)/s;
nuclear@0 206 const aiVector3D v9 = aiVector3D(0.f,-t, 1.f)/s;
nuclear@0 207 const aiVector3D v10 = aiVector3D(0.f, t,-1.f)/s;
nuclear@0 208 const aiVector3D v11 = aiVector3D(0.f,-t,-1.f)/s;
nuclear@0 209
nuclear@0 210 ADD_TRIANGLE(v0,v8,v4);
nuclear@0 211 ADD_TRIANGLE(v0,v5,v10);
nuclear@0 212 ADD_TRIANGLE(v2,v4,v9);
nuclear@0 213 ADD_TRIANGLE(v2,v11,v5);
nuclear@0 214
nuclear@0 215 ADD_TRIANGLE(v1,v6,v8);
nuclear@0 216 ADD_TRIANGLE(v1,v10,v7);
nuclear@0 217 ADD_TRIANGLE(v3,v9,v6);
nuclear@0 218 ADD_TRIANGLE(v3,v7,v11);
nuclear@0 219
nuclear@0 220 ADD_TRIANGLE(v0,v10,v8);
nuclear@0 221 ADD_TRIANGLE(v1,v8,v10);
nuclear@0 222 ADD_TRIANGLE(v2,v9,v11);
nuclear@0 223 ADD_TRIANGLE(v3,v11,v9);
nuclear@0 224
nuclear@0 225 ADD_TRIANGLE(v4,v2,v0);
nuclear@0 226 ADD_TRIANGLE(v5,v0,v2);
nuclear@0 227 ADD_TRIANGLE(v6,v1,v3);
nuclear@0 228 ADD_TRIANGLE(v7,v3,v1);
nuclear@0 229
nuclear@0 230 ADD_TRIANGLE(v8,v6,v4);
nuclear@0 231 ADD_TRIANGLE(v9,v4,v6);
nuclear@0 232 ADD_TRIANGLE(v10,v5,v7);
nuclear@0 233 ADD_TRIANGLE(v11,v7,v5);
nuclear@0 234 return 3;
nuclear@0 235 }
nuclear@0 236
nuclear@0 237 // ------------------------------------------------------------------------------------------------
nuclear@0 238 // Build a dodecahedron with points.magnitude == 1
nuclear@0 239 unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions,
nuclear@0 240 bool polygons /*= false*/)
nuclear@0 241 {
nuclear@0 242 positions.reserve(positions.size()+108);
nuclear@0 243
nuclear@0 244 const float a = 1.f / 1.7320508f;
nuclear@0 245 const float b = sqrt((3.f-2.23606797f)/6.f);
nuclear@0 246 const float c = sqrt((3.f+2.23606797f)/6.f);
nuclear@0 247
nuclear@0 248 const aiVector3D v0 = aiVector3D(a,a,a);
nuclear@0 249 const aiVector3D v1 = aiVector3D(a,a,-a);
nuclear@0 250 const aiVector3D v2 = aiVector3D(a,-a,a);
nuclear@0 251 const aiVector3D v3 = aiVector3D(a,-a,-a);
nuclear@0 252 const aiVector3D v4 = aiVector3D(-a,a,a);
nuclear@0 253 const aiVector3D v5 = aiVector3D(-a,a,-a);
nuclear@0 254 const aiVector3D v6 = aiVector3D(-a,-a,a);
nuclear@0 255 const aiVector3D v7 = aiVector3D(-a,-a,-a);
nuclear@0 256 const aiVector3D v8 = aiVector3D(b,c,0.f);
nuclear@0 257 const aiVector3D v9 = aiVector3D(-b,c,0.f);
nuclear@0 258 const aiVector3D v10 = aiVector3D(b,-c,0.f);
nuclear@0 259 const aiVector3D v11 = aiVector3D(-b,-c,0.f);
nuclear@0 260 const aiVector3D v12 = aiVector3D(c, 0.f, b);
nuclear@0 261 const aiVector3D v13 = aiVector3D(c, 0.f, -b);
nuclear@0 262 const aiVector3D v14 = aiVector3D(-c, 0.f, b);
nuclear@0 263 const aiVector3D v15 = aiVector3D(-c, 0.f, -b);
nuclear@0 264 const aiVector3D v16 = aiVector3D(0.f, b, c);
nuclear@0 265 const aiVector3D v17 = aiVector3D(0.f, -b, c);
nuclear@0 266 const aiVector3D v18 = aiVector3D(0.f, b, -c);
nuclear@0 267 const aiVector3D v19 = aiVector3D(0.f, -b, -c);
nuclear@0 268
nuclear@0 269 ADD_PENTAGON(v0, v8, v9, v4, v16);
nuclear@0 270 ADD_PENTAGON(v0, v12, v13, v1, v8);
nuclear@0 271 ADD_PENTAGON(v0, v16, v17, v2, v12);
nuclear@0 272 ADD_PENTAGON(v8, v1, v18, v5, v9);
nuclear@0 273 ADD_PENTAGON(v12, v2, v10, v3, v13);
nuclear@0 274 ADD_PENTAGON(v16, v4, v14, v6, v17);
nuclear@0 275 ADD_PENTAGON(v9, v5, v15, v14, v4);
nuclear@0 276
nuclear@0 277 ADD_PENTAGON(v6, v11, v10, v2, v17);
nuclear@0 278 ADD_PENTAGON(v3, v19, v18, v1, v13);
nuclear@0 279 ADD_PENTAGON(v7, v15, v5, v18, v19);
nuclear@0 280 ADD_PENTAGON(v7, v11, v6, v14, v15);
nuclear@0 281 ADD_PENTAGON(v7, v19, v3, v10, v11);
nuclear@0 282 return (polygons ? 5 : 3);
nuclear@0 283 }
nuclear@0 284
nuclear@0 285 // ------------------------------------------------------------------------------------------------
nuclear@0 286 // Build an octahedron with points.magnitude == 1
nuclear@0 287 unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
nuclear@0 288 {
nuclear@0 289 positions.reserve(positions.size()+24);
nuclear@0 290
nuclear@0 291 const aiVector3D v0 = aiVector3D(1.0f, 0.f, 0.f) ;
nuclear@0 292 const aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f);
nuclear@0 293 const aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f);
nuclear@0 294 const aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f);
nuclear@0 295 const aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f);
nuclear@0 296 const aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f);
nuclear@0 297
nuclear@0 298 ADD_TRIANGLE(v4,v0,v2);
nuclear@0 299 ADD_TRIANGLE(v4,v2,v1);
nuclear@0 300 ADD_TRIANGLE(v4,v1,v3);
nuclear@0 301 ADD_TRIANGLE(v4,v3,v0);
nuclear@0 302
nuclear@0 303 ADD_TRIANGLE(v5,v2,v0);
nuclear@0 304 ADD_TRIANGLE(v5,v1,v2);
nuclear@0 305 ADD_TRIANGLE(v5,v3,v1);
nuclear@0 306 ADD_TRIANGLE(v5,v0,v3);
nuclear@0 307 return 3;
nuclear@0 308 }
nuclear@0 309
nuclear@0 310 // ------------------------------------------------------------------------------------------------
nuclear@0 311 // Build a tetrahedron with points.magnitude == 1
nuclear@0 312 unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
nuclear@0 313 {
nuclear@0 314 positions.reserve(positions.size()+9);
nuclear@0 315
nuclear@0 316 const float a = 1.41421f/3.f;
nuclear@0 317 const float b = 2.4494f/3.f;
nuclear@0 318
nuclear@0 319 const aiVector3D v0 = aiVector3D(0.f,0.f,1.f);
nuclear@0 320 const aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f);
nuclear@0 321 const aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f);
nuclear@0 322 const aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f);
nuclear@0 323
nuclear@0 324 ADD_TRIANGLE(v0,v1,v2);
nuclear@0 325 ADD_TRIANGLE(v0,v2,v3);
nuclear@0 326 ADD_TRIANGLE(v0,v3,v1);
nuclear@0 327 ADD_TRIANGLE(v1,v3,v2);
nuclear@0 328 return 3;
nuclear@0 329 }
nuclear@0 330
nuclear@0 331 // ------------------------------------------------------------------------------------------------
nuclear@0 332 // Build a hexahedron with points.magnitude == 1
nuclear@0 333 unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
nuclear@0 334 bool polygons /*= false*/)
nuclear@0 335 {
nuclear@0 336 positions.reserve(positions.size()+36);
nuclear@0 337 const float length = 1.f/1.73205080f;
nuclear@0 338
nuclear@0 339 const aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length;
nuclear@0 340 const aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length;
nuclear@0 341 const aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length;
nuclear@0 342 const aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length;
nuclear@0 343 const aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length;
nuclear@0 344 const aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length;
nuclear@0 345 const aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length;
nuclear@0 346 const aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*length;
nuclear@0 347
nuclear@0 348 ADD_QUAD(v0,v3,v2,v1);
nuclear@0 349 ADD_QUAD(v0,v1,v5,v4);
nuclear@0 350 ADD_QUAD(v0,v4,v7,v3);
nuclear@0 351 ADD_QUAD(v6,v5,v1,v2);
nuclear@0 352 ADD_QUAD(v6,v2,v3,v7);
nuclear@0 353 ADD_QUAD(v6,v7,v4,v5);
nuclear@0 354 return (polygons ? 4 : 3);
nuclear@0 355 }
nuclear@0 356
nuclear@0 357 // Cleanup ...
nuclear@0 358 #undef ADD_TRIANGLE
nuclear@0 359 #undef ADD_QUAD
nuclear@0 360 #undef ADD_PENTAGON
nuclear@0 361
nuclear@0 362 // ------------------------------------------------------------------------------------------------
nuclear@0 363 // Create a subdivision sphere
nuclear@0 364 void StandardShapes::MakeSphere(unsigned int tess,
nuclear@0 365 std::vector<aiVector3D>& positions)
nuclear@0 366 {
nuclear@0 367 // Reserve enough storage. Every subdivision
nuclear@0 368 // splits each triangle in 4, the icosahedron consists of 60 verts
nuclear@0 369 positions.reserve(positions.size()+60 * integer_pow(4, tess));
nuclear@0 370
nuclear@0 371 // Construct an icosahedron to start with
nuclear@0 372 MakeIcosahedron(positions);
nuclear@0 373
nuclear@0 374 // ... and subdivide it until the requested output
nuclear@0 375 // tesselation is reached
nuclear@0 376 for (unsigned int i = 0; i<tess;++i)
nuclear@0 377 Subdivide(positions);
nuclear@0 378 }
nuclear@0 379
nuclear@0 380 // ------------------------------------------------------------------------------------------------
nuclear@0 381 // Build a cone
nuclear@0 382 void StandardShapes::MakeCone(float height,float radius1,
nuclear@0 383 float radius2,unsigned int tess,
nuclear@0 384 std::vector<aiVector3D>& positions,bool bOpen /*= false */)
nuclear@0 385 {
nuclear@0 386 // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE
nuclear@0 387 if (tess < 3 || !height)
nuclear@0 388 return;
nuclear@0 389
nuclear@0 390 size_t old = positions.size();
nuclear@0 391
nuclear@0 392 // No negative radii
nuclear@0 393 radius1 = ::fabs(radius1);
nuclear@0 394 radius2 = ::fabs(radius2);
nuclear@0 395
nuclear@0 396 float halfHeight = height / 2;
nuclear@0 397
nuclear@0 398 // radius1 is always the smaller one
nuclear@0 399 if (radius2 > radius1)
nuclear@0 400 {
nuclear@0 401 std::swap(radius2,radius1);
nuclear@0 402 halfHeight = -halfHeight;
nuclear@0 403 }
nuclear@0 404 else old = SIZE_MAX;
nuclear@0 405
nuclear@0 406 // Use a large epsilon to check whether the cone is pointy
nuclear@0 407 if (radius1 < (radius2-radius1)*10e-3f)radius1 = 0.f;
nuclear@0 408
nuclear@0 409 // We will need 3*2 verts per segment + 3*2 verts per segment
nuclear@0 410 // if the cone is closed
nuclear@0 411 const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0);
nuclear@0 412 positions.reserve(positions.size () + mem);
nuclear@0 413
nuclear@0 414 // Now construct all segments
nuclear@0 415 const float angle_delta = (float)AI_MATH_TWO_PI / tess;
nuclear@0 416 const float angle_max = (float)AI_MATH_TWO_PI;
nuclear@0 417
nuclear@0 418 float s = 1.f; // cos(angle == 0);
nuclear@0 419 float t = 0.f; // sin(angle == 0);
nuclear@0 420
nuclear@0 421 for (float angle = 0.f; angle < angle_max; )
nuclear@0 422 {
nuclear@0 423 const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
nuclear@0 424 const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
nuclear@0 425
nuclear@0 426 const float next = angle + angle_delta;
nuclear@0 427 float s2 = ::cos(next);
nuclear@0 428 float t2 = ::sin(next);
nuclear@0 429
nuclear@0 430 const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 );
nuclear@0 431 const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 );
nuclear@0 432
nuclear@0 433 positions.push_back(v1);
nuclear@0 434 positions.push_back(v2);
nuclear@0 435 positions.push_back(v3);
nuclear@0 436 positions.push_back(v4);
nuclear@0 437 positions.push_back(v1);
nuclear@0 438 positions.push_back(v3);
nuclear@0 439
nuclear@0 440 if (!bOpen)
nuclear@0 441 {
nuclear@0 442 // generate the end 'cap'
nuclear@0 443 positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 ));
nuclear@0 444 positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 ));
nuclear@0 445 positions.push_back(aiVector3D(0.f, halfHeight, 0.f));
nuclear@0 446
nuclear@0 447
nuclear@0 448 if (radius1)
nuclear@0 449 {
nuclear@0 450 // generate the other end 'cap'
nuclear@0 451 positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 ));
nuclear@0 452 positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 ));
nuclear@0 453 positions.push_back(aiVector3D(0.f, -halfHeight, 0.f));
nuclear@0 454
nuclear@0 455 }
nuclear@0 456 }
nuclear@0 457 s = s2;
nuclear@0 458 t = t2;
nuclear@0 459 angle = next;
nuclear@0 460 }
nuclear@0 461
nuclear@0 462 // Need to flip face order?
nuclear@0 463 if ( SIZE_MAX != old ) {
nuclear@0 464 for (size_t s = old; s < positions.size();s += 3) {
nuclear@0 465 std::swap(positions[s],positions[s+1]);
nuclear@0 466 }
nuclear@0 467 }
nuclear@0 468 }
nuclear@0 469
nuclear@0 470 // ------------------------------------------------------------------------------------------------
nuclear@0 471 // Build a circle
nuclear@0 472 void StandardShapes::MakeCircle(float radius, unsigned int tess,
nuclear@0 473 std::vector<aiVector3D>& positions)
nuclear@0 474 {
nuclear@0 475 // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE
nuclear@0 476 if (tess < 3 || !radius)
nuclear@0 477 return;
nuclear@0 478
nuclear@0 479 radius = ::fabs(radius);
nuclear@0 480
nuclear@0 481 // We will need 3 vertices per segment
nuclear@0 482 positions.reserve(positions.size()+tess*3);
nuclear@0 483
nuclear@0 484 const float angle_delta = (float)AI_MATH_TWO_PI / tess;
nuclear@0 485 const float angle_max = (float)AI_MATH_TWO_PI;
nuclear@0 486
nuclear@0 487 float s = 1.f; // cos(angle == 0);
nuclear@0 488 float t = 0.f; // sin(angle == 0);
nuclear@0 489
nuclear@0 490 for (float angle = 0.f; angle < angle_max; )
nuclear@0 491 {
nuclear@0 492 positions.push_back(aiVector3D(s * radius,0.f,t * radius));
nuclear@0 493 angle += angle_delta;
nuclear@0 494 s = ::cos(angle);
nuclear@0 495 t = ::sin(angle);
nuclear@0 496 positions.push_back(aiVector3D(s * radius,0.f,t * radius));
nuclear@0 497
nuclear@0 498 positions.push_back(aiVector3D(0.f,0.f,0.f));
nuclear@0 499 }
nuclear@0 500 }
nuclear@0 501
nuclear@0 502 } // ! Assimp