nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file StandardShapes.cpp nuclear@0: * @brief Implementation of the StandardShapes class nuclear@0: * nuclear@0: * The primitive geometry data comes from nuclear@0: * http://geometrictools.com/Documentation/PlatonicSolids.pdf. nuclear@0: */ nuclear@0: nuclear@0: #include "AssimpPCH.h" nuclear@0: #include "StandardShapes.h" nuclear@0: nuclear@0: namespace Assimp { nuclear@0: nuclear@0: nuclear@0: # define ADD_TRIANGLE(n0,n1,n2) \ nuclear@0: positions.push_back(n0); \ nuclear@0: positions.push_back(n1); \ nuclear@0: positions.push_back(n2); nuclear@0: nuclear@0: # define ADD_PENTAGON(n0,n1,n2,n3,n4) \ nuclear@0: if (polygons) \ nuclear@0: { \ nuclear@0: positions.push_back(n0); \ nuclear@0: positions.push_back(n1); \ nuclear@0: positions.push_back(n2); \ nuclear@0: positions.push_back(n3); \ nuclear@0: positions.push_back(n4); \ nuclear@0: } \ nuclear@0: else \ nuclear@0: { \ nuclear@0: ADD_TRIANGLE(n0, n1, n2) \ nuclear@0: ADD_TRIANGLE(n0, n2, n3) \ nuclear@0: ADD_TRIANGLE(n0, n3, n4) \ nuclear@0: } nuclear@0: nuclear@0: # define ADD_QUAD(n0,n1,n2,n3) \ nuclear@0: if (polygons) \ nuclear@0: { \ nuclear@0: positions.push_back(n0); \ nuclear@0: positions.push_back(n1); \ nuclear@0: positions.push_back(n2); \ nuclear@0: positions.push_back(n3); \ nuclear@0: } \ nuclear@0: else \ nuclear@0: { \ nuclear@0: ADD_TRIANGLE(n0, n1, n2) \ nuclear@0: ADD_TRIANGLE(n0, n2, n3) \ nuclear@0: } nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Fast subdivision for a mesh whose verts have a magnitude of 1 nuclear@0: void Subdivide(std::vector& positions) nuclear@0: { nuclear@0: // assume this to be constant - (fixme: must be 1.0? I think so) nuclear@0: const float fl1 = positions[0].Length(); nuclear@0: nuclear@0: unsigned int origSize = (unsigned int)positions.size(); nuclear@0: for (unsigned int i = 0 ; i < origSize ; i+=3) nuclear@0: { nuclear@0: aiVector3D& tv0 = positions[i]; nuclear@0: aiVector3D& tv1 = positions[i+1]; nuclear@0: aiVector3D& tv2 = positions[i+2]; nuclear@0: nuclear@0: aiVector3D a = tv0, b = tv1, c = tv2; nuclear@0: aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1; nuclear@0: aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1; nuclear@0: aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1; nuclear@0: nuclear@0: tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original nuclear@0: ADD_TRIANGLE(v1, v2, a); nuclear@0: ADD_TRIANGLE(v2, v3, c); nuclear@0: ADD_TRIANGLE(v3, v1, b); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Construct a mesh from given vertex positions nuclear@0: aiMesh* StandardShapes::MakeMesh(const std::vector& positions, nuclear@0: unsigned int numIndices) nuclear@0: { nuclear@0: if (positions.size() & numIndices || positions.empty() || !numIndices) nuclear@0: return NULL; nuclear@0: nuclear@0: // Determine which kinds of primitives the mesh consists of nuclear@0: aiMesh* out = new aiMesh(); nuclear@0: switch (numIndices) nuclear@0: { nuclear@0: case 1: nuclear@0: out->mPrimitiveTypes = aiPrimitiveType_POINT; nuclear@0: break; nuclear@0: case 2: nuclear@0: out->mPrimitiveTypes = aiPrimitiveType_LINE; nuclear@0: break; nuclear@0: case 3: nuclear@0: out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; nuclear@0: break; nuclear@0: default: nuclear@0: out->mPrimitiveTypes = aiPrimitiveType_POLYGON; nuclear@0: break; nuclear@0: }; nuclear@0: nuclear@0: out->mNumFaces = (unsigned int)positions.size() / numIndices; nuclear@0: out->mFaces = new aiFace[out->mNumFaces]; nuclear@0: for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) nuclear@0: { nuclear@0: aiFace& f = out->mFaces[i]; nuclear@0: f.mNumIndices = numIndices; nuclear@0: f.mIndices = new unsigned int[numIndices]; nuclear@0: for (unsigned int i = 0; i < numIndices;++i,++a) nuclear@0: f.mIndices[i] = a; nuclear@0: } nuclear@0: out->mNumVertices = (unsigned int)positions.size(); nuclear@0: out->mVertices = new aiVector3D[out->mNumVertices]; nuclear@0: ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D)); nuclear@0: return out; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Construct a mesh with a specific shape (callback) nuclear@0: aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( nuclear@0: std::vector&)) nuclear@0: { nuclear@0: std::vector temp; nuclear@0: unsigned num = (*GenerateFunc)(temp); nuclear@0: return MakeMesh(temp,num); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Construct a mesh with a specific shape (callback) nuclear@0: aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( nuclear@0: std::vector&, bool)) nuclear@0: { nuclear@0: std::vector temp; nuclear@0: unsigned num = (*GenerateFunc)(temp,true); nuclear@0: return MakeMesh(temp,num); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Construct a mesh with a specific shape (callback) nuclear@0: aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)( nuclear@0: unsigned int,std::vector&)) nuclear@0: { nuclear@0: std::vector temp; nuclear@0: (*GenerateFunc)(num,temp); nuclear@0: return MakeMesh(temp,3); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Build an incosahedron with points.magnitude == 1 nuclear@0: unsigned int StandardShapes::MakeIcosahedron(std::vector& positions) nuclear@0: { nuclear@0: positions.reserve(positions.size()+60); nuclear@0: nuclear@0: const float t = (1.f + 2.236067977f)/2.f; nuclear@0: const float s = sqrt(1.f + t*t); nuclear@0: nuclear@0: const aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s; nuclear@0: const aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s; nuclear@0: const aiVector3D v2 = aiVector3D(t,-1.f, 0.f)/s; nuclear@0: const aiVector3D v3 = aiVector3D(-t,-1.f, 0.f)/s; nuclear@0: const aiVector3D v4 = aiVector3D(1.f, 0.f, t)/s; nuclear@0: const aiVector3D v5 = aiVector3D(1.f, 0.f,-t)/s; nuclear@0: const aiVector3D v6 = aiVector3D(-1.f, 0.f,t)/s; nuclear@0: const aiVector3D v7 = aiVector3D(-1.f, 0.f,-t)/s; nuclear@0: const aiVector3D v8 = aiVector3D(0.f, t, 1.f)/s; nuclear@0: const aiVector3D v9 = aiVector3D(0.f,-t, 1.f)/s; nuclear@0: const aiVector3D v10 = aiVector3D(0.f, t,-1.f)/s; nuclear@0: const aiVector3D v11 = aiVector3D(0.f,-t,-1.f)/s; nuclear@0: nuclear@0: ADD_TRIANGLE(v0,v8,v4); nuclear@0: ADD_TRIANGLE(v0,v5,v10); nuclear@0: ADD_TRIANGLE(v2,v4,v9); nuclear@0: ADD_TRIANGLE(v2,v11,v5); nuclear@0: nuclear@0: ADD_TRIANGLE(v1,v6,v8); nuclear@0: ADD_TRIANGLE(v1,v10,v7); nuclear@0: ADD_TRIANGLE(v3,v9,v6); nuclear@0: ADD_TRIANGLE(v3,v7,v11); nuclear@0: nuclear@0: ADD_TRIANGLE(v0,v10,v8); nuclear@0: ADD_TRIANGLE(v1,v8,v10); nuclear@0: ADD_TRIANGLE(v2,v9,v11); nuclear@0: ADD_TRIANGLE(v3,v11,v9); nuclear@0: nuclear@0: ADD_TRIANGLE(v4,v2,v0); nuclear@0: ADD_TRIANGLE(v5,v0,v2); nuclear@0: ADD_TRIANGLE(v6,v1,v3); nuclear@0: ADD_TRIANGLE(v7,v3,v1); nuclear@0: nuclear@0: ADD_TRIANGLE(v8,v6,v4); nuclear@0: ADD_TRIANGLE(v9,v4,v6); nuclear@0: ADD_TRIANGLE(v10,v5,v7); nuclear@0: ADD_TRIANGLE(v11,v7,v5); nuclear@0: return 3; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Build a dodecahedron with points.magnitude == 1 nuclear@0: unsigned int StandardShapes::MakeDodecahedron(std::vector& positions, nuclear@0: bool polygons /*= false*/) nuclear@0: { nuclear@0: positions.reserve(positions.size()+108); nuclear@0: nuclear@0: const float a = 1.f / 1.7320508f; nuclear@0: const float b = sqrt((3.f-2.23606797f)/6.f); nuclear@0: const float c = sqrt((3.f+2.23606797f)/6.f); nuclear@0: nuclear@0: const aiVector3D v0 = aiVector3D(a,a,a); nuclear@0: const aiVector3D v1 = aiVector3D(a,a,-a); nuclear@0: const aiVector3D v2 = aiVector3D(a,-a,a); nuclear@0: const aiVector3D v3 = aiVector3D(a,-a,-a); nuclear@0: const aiVector3D v4 = aiVector3D(-a,a,a); nuclear@0: const aiVector3D v5 = aiVector3D(-a,a,-a); nuclear@0: const aiVector3D v6 = aiVector3D(-a,-a,a); nuclear@0: const aiVector3D v7 = aiVector3D(-a,-a,-a); nuclear@0: const aiVector3D v8 = aiVector3D(b,c,0.f); nuclear@0: const aiVector3D v9 = aiVector3D(-b,c,0.f); nuclear@0: const aiVector3D v10 = aiVector3D(b,-c,0.f); nuclear@0: const aiVector3D v11 = aiVector3D(-b,-c,0.f); nuclear@0: const aiVector3D v12 = aiVector3D(c, 0.f, b); nuclear@0: const aiVector3D v13 = aiVector3D(c, 0.f, -b); nuclear@0: const aiVector3D v14 = aiVector3D(-c, 0.f, b); nuclear@0: const aiVector3D v15 = aiVector3D(-c, 0.f, -b); nuclear@0: const aiVector3D v16 = aiVector3D(0.f, b, c); nuclear@0: const aiVector3D v17 = aiVector3D(0.f, -b, c); nuclear@0: const aiVector3D v18 = aiVector3D(0.f, b, -c); nuclear@0: const aiVector3D v19 = aiVector3D(0.f, -b, -c); nuclear@0: nuclear@0: ADD_PENTAGON(v0, v8, v9, v4, v16); nuclear@0: ADD_PENTAGON(v0, v12, v13, v1, v8); nuclear@0: ADD_PENTAGON(v0, v16, v17, v2, v12); nuclear@0: ADD_PENTAGON(v8, v1, v18, v5, v9); nuclear@0: ADD_PENTAGON(v12, v2, v10, v3, v13); nuclear@0: ADD_PENTAGON(v16, v4, v14, v6, v17); nuclear@0: ADD_PENTAGON(v9, v5, v15, v14, v4); nuclear@0: nuclear@0: ADD_PENTAGON(v6, v11, v10, v2, v17); nuclear@0: ADD_PENTAGON(v3, v19, v18, v1, v13); nuclear@0: ADD_PENTAGON(v7, v15, v5, v18, v19); nuclear@0: ADD_PENTAGON(v7, v11, v6, v14, v15); nuclear@0: ADD_PENTAGON(v7, v19, v3, v10, v11); nuclear@0: return (polygons ? 5 : 3); nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Build an octahedron with points.magnitude == 1 nuclear@0: unsigned int StandardShapes::MakeOctahedron(std::vector& positions) nuclear@0: { nuclear@0: positions.reserve(positions.size()+24); nuclear@0: nuclear@0: const aiVector3D v0 = aiVector3D(1.0f, 0.f, 0.f) ; nuclear@0: const aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f); nuclear@0: const aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f); nuclear@0: const aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f); nuclear@0: const aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f); nuclear@0: const aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f); nuclear@0: nuclear@0: ADD_TRIANGLE(v4,v0,v2); nuclear@0: ADD_TRIANGLE(v4,v2,v1); nuclear@0: ADD_TRIANGLE(v4,v1,v3); nuclear@0: ADD_TRIANGLE(v4,v3,v0); nuclear@0: nuclear@0: ADD_TRIANGLE(v5,v2,v0); nuclear@0: ADD_TRIANGLE(v5,v1,v2); nuclear@0: ADD_TRIANGLE(v5,v3,v1); nuclear@0: ADD_TRIANGLE(v5,v0,v3); nuclear@0: return 3; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Build a tetrahedron with points.magnitude == 1 nuclear@0: unsigned int StandardShapes::MakeTetrahedron(std::vector& positions) nuclear@0: { nuclear@0: positions.reserve(positions.size()+9); nuclear@0: nuclear@0: const float a = 1.41421f/3.f; nuclear@0: const float b = 2.4494f/3.f; nuclear@0: nuclear@0: const aiVector3D v0 = aiVector3D(0.f,0.f,1.f); nuclear@0: const aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f); nuclear@0: const aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f); nuclear@0: const aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f); nuclear@0: nuclear@0: ADD_TRIANGLE(v0,v1,v2); nuclear@0: ADD_TRIANGLE(v0,v2,v3); nuclear@0: ADD_TRIANGLE(v0,v3,v1); nuclear@0: ADD_TRIANGLE(v1,v3,v2); nuclear@0: return 3; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Build a hexahedron with points.magnitude == 1 nuclear@0: unsigned int StandardShapes::MakeHexahedron(std::vector& positions, nuclear@0: bool polygons /*= false*/) nuclear@0: { nuclear@0: positions.reserve(positions.size()+36); nuclear@0: const float length = 1.f/1.73205080f; nuclear@0: nuclear@0: const aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length; nuclear@0: const aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length; nuclear@0: const aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length; nuclear@0: const aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length; nuclear@0: const aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length; nuclear@0: const aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length; nuclear@0: const aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length; nuclear@0: const aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*length; nuclear@0: nuclear@0: ADD_QUAD(v0,v3,v2,v1); nuclear@0: ADD_QUAD(v0,v1,v5,v4); nuclear@0: ADD_QUAD(v0,v4,v7,v3); nuclear@0: ADD_QUAD(v6,v5,v1,v2); nuclear@0: ADD_QUAD(v6,v2,v3,v7); nuclear@0: ADD_QUAD(v6,v7,v4,v5); nuclear@0: return (polygons ? 4 : 3); nuclear@0: } nuclear@0: nuclear@0: // Cleanup ... nuclear@0: #undef ADD_TRIANGLE nuclear@0: #undef ADD_QUAD nuclear@0: #undef ADD_PENTAGON nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Create a subdivision sphere nuclear@0: void StandardShapes::MakeSphere(unsigned int tess, nuclear@0: std::vector& positions) nuclear@0: { nuclear@0: // Reserve enough storage. Every subdivision nuclear@0: // splits each triangle in 4, the icosahedron consists of 60 verts nuclear@0: positions.reserve(positions.size()+60 * integer_pow(4, tess)); nuclear@0: nuclear@0: // Construct an icosahedron to start with nuclear@0: MakeIcosahedron(positions); nuclear@0: nuclear@0: // ... and subdivide it until the requested output nuclear@0: // tesselation is reached nuclear@0: for (unsigned int i = 0; i& positions,bool bOpen /*= false */) nuclear@0: { nuclear@0: // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE nuclear@0: if (tess < 3 || !height) nuclear@0: return; nuclear@0: nuclear@0: size_t old = positions.size(); nuclear@0: nuclear@0: // No negative radii nuclear@0: radius1 = ::fabs(radius1); nuclear@0: radius2 = ::fabs(radius2); nuclear@0: nuclear@0: float halfHeight = height / 2; nuclear@0: nuclear@0: // radius1 is always the smaller one nuclear@0: if (radius2 > radius1) nuclear@0: { nuclear@0: std::swap(radius2,radius1); nuclear@0: halfHeight = -halfHeight; nuclear@0: } nuclear@0: else old = SIZE_MAX; nuclear@0: nuclear@0: // Use a large epsilon to check whether the cone is pointy nuclear@0: if (radius1 < (radius2-radius1)*10e-3f)radius1 = 0.f; nuclear@0: nuclear@0: // We will need 3*2 verts per segment + 3*2 verts per segment nuclear@0: // if the cone is closed nuclear@0: const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0); nuclear@0: positions.reserve(positions.size () + mem); nuclear@0: nuclear@0: // Now construct all segments nuclear@0: const float angle_delta = (float)AI_MATH_TWO_PI / tess; nuclear@0: const float angle_max = (float)AI_MATH_TWO_PI; nuclear@0: nuclear@0: float s = 1.f; // cos(angle == 0); nuclear@0: float t = 0.f; // sin(angle == 0); nuclear@0: nuclear@0: for (float angle = 0.f; angle < angle_max; ) nuclear@0: { nuclear@0: const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 ); nuclear@0: const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 ); nuclear@0: nuclear@0: const float next = angle + angle_delta; nuclear@0: float s2 = ::cos(next); nuclear@0: float t2 = ::sin(next); nuclear@0: nuclear@0: const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 ); nuclear@0: const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 ); nuclear@0: nuclear@0: positions.push_back(v1); nuclear@0: positions.push_back(v2); nuclear@0: positions.push_back(v3); nuclear@0: positions.push_back(v4); nuclear@0: positions.push_back(v1); nuclear@0: positions.push_back(v3); nuclear@0: nuclear@0: if (!bOpen) nuclear@0: { nuclear@0: // generate the end 'cap' nuclear@0: positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 )); nuclear@0: positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 )); nuclear@0: positions.push_back(aiVector3D(0.f, halfHeight, 0.f)); nuclear@0: nuclear@0: nuclear@0: if (radius1) nuclear@0: { nuclear@0: // generate the other end 'cap' nuclear@0: positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 )); nuclear@0: positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 )); nuclear@0: positions.push_back(aiVector3D(0.f, -halfHeight, 0.f)); nuclear@0: nuclear@0: } nuclear@0: } nuclear@0: s = s2; nuclear@0: t = t2; nuclear@0: angle = next; nuclear@0: } nuclear@0: nuclear@0: // Need to flip face order? nuclear@0: if ( SIZE_MAX != old ) { nuclear@0: for (size_t s = old; s < positions.size();s += 3) { nuclear@0: std::swap(positions[s],positions[s+1]); nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------------------------------------ nuclear@0: // Build a circle nuclear@0: void StandardShapes::MakeCircle(float radius, unsigned int tess, nuclear@0: std::vector& positions) nuclear@0: { nuclear@0: // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE nuclear@0: if (tess < 3 || !radius) nuclear@0: return; nuclear@0: nuclear@0: radius = ::fabs(radius); nuclear@0: nuclear@0: // We will need 3 vertices per segment nuclear@0: positions.reserve(positions.size()+tess*3); nuclear@0: nuclear@0: const float angle_delta = (float)AI_MATH_TWO_PI / tess; nuclear@0: const float angle_max = (float)AI_MATH_TWO_PI; nuclear@0: nuclear@0: float s = 1.f; // cos(angle == 0); nuclear@0: float t = 0.f; // sin(angle == 0); nuclear@0: nuclear@0: for (float angle = 0.f; angle < angle_max; ) nuclear@0: { nuclear@0: positions.push_back(aiVector3D(s * radius,0.f,t * radius)); nuclear@0: angle += angle_delta; nuclear@0: s = ::cos(angle); nuclear@0: t = ::sin(angle); nuclear@0: positions.push_back(aiVector3D(s * radius,0.f,t * radius)); nuclear@0: nuclear@0: positions.push_back(aiVector3D(0.f,0.f,0.f)); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: } // ! Assimp