From 49c6bea7224665ea370fc29fac4b01dcf2a40fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 4 Apr 2012 11:49:50 +0200 Subject: [PATCH] Capsule and UVSphere primitive, with normals and texture coordinates. --- src/Primitives/CMakeLists.txt | 7 ++ src/Primitives/Capsule.cpp | 138 ++++++++++++++++++++++++ src/Primitives/Capsule.h | 69 ++++++++++++ src/Primitives/Test/CMakeLists.txt | 2 + src/Primitives/Test/CapsuleTest.cpp | 151 +++++++++++++++++++++++++++ src/Primitives/Test/CapsuleTest.h | 32 ++++++ src/Primitives/Test/UVSphereTest.cpp | 108 +++++++++++++++++++ src/Primitives/Test/UVSphereTest.h | 32 ++++++ src/Primitives/UVSphere.cpp | 49 +++++++++ src/Primitives/UVSphere.h | 43 ++++++++ 10 files changed, 631 insertions(+) create mode 100644 src/Primitives/Capsule.cpp create mode 100644 src/Primitives/Capsule.h create mode 100644 src/Primitives/Test/CMakeLists.txt create mode 100644 src/Primitives/Test/CapsuleTest.cpp create mode 100644 src/Primitives/Test/CapsuleTest.h create mode 100644 src/Primitives/Test/UVSphereTest.cpp create mode 100644 src/Primitives/Test/UVSphereTest.h create mode 100644 src/Primitives/UVSphere.cpp create mode 100644 src/Primitives/UVSphere.h diff --git a/src/Primitives/CMakeLists.txt b/src/Primitives/CMakeLists.txt index e8e613f92..a8e8c5ce0 100644 --- a/src/Primitives/CMakeLists.txt +++ b/src/Primitives/CMakeLists.txt @@ -1,9 +1,16 @@ set(MagnumPrimitives_SRCS + Capsule.cpp Cube.cpp Icosphere.cpp + UVSphere.cpp ) add_library(MagnumPrimitives STATIC ${MagnumPrimitives_SRCS}) target_link_libraries(MagnumPrimitives Magnum) install(TARGETS MagnumPrimitives DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) + +if(BUILD_TESTS) + enable_testing() + add_subdirectory(Test) +endif() diff --git a/src/Primitives/Capsule.cpp b/src/Primitives/Capsule.cpp new file mode 100644 index 000000000..5d0e0da12 --- /dev/null +++ b/src/Primitives/Capsule.cpp @@ -0,0 +1,138 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Capsule.h" + +#include + +using namespace std; +using namespace Corrade::Utility; + +namespace Magnum { namespace Primitives { + +Capsule::Capsule(unsigned int rings, unsigned int segments, GLfloat length, TextureCoords textureCoords): MeshData(Mesh::Primitive::Triangles, new vector, {new vector()}, {new vector()}, textureCoords == TextureCoords::Generate ? vector*>{new vector()} : vector*>()), segments(segments), textureCoords(textureCoords) { + if(rings < 1 || segments < 3) { + Error() << "Capsule must have at least one ring and three segments"; + assert(0); + } + + GLfloat height = 2.0f+length; + GLfloat textureCoordsVIncrement = 1.0f/(rings*height); + GLfloat ringAngleIncrement = PI/(2*rings); + + /* Bottom cap vertex */ + capVertex(-height/2, -1.0f, 0.0f); + + /* Rings of bottom hemisphere */ + vertexRings(rings, -length/2, -PI/2+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement); + + /* Rings of top hemisphere */ + vertexRings(rings, length/2, 0.0f, ringAngleIncrement, (1.0f + length)/height, textureCoordsVIncrement); + + /* Top cap vertex */ + capVertex(height/2, 1.0f, 1.0f); + + /* Faces */ + bottomFaceRing(); + faceRings(rings*2-1); + topFaceRing(); +} + +void Capsule::capVertex(GLfloat y, GLfloat normalY, GLfloat textureCoordsV) { + vertices(0)->push_back({0.0f, y, 0.0f}); + normals(0)->push_back({0.0f, normalY, 0.0f}); + + if(textureCoords == TextureCoords::Generate) + textureCoords2D(0)->push_back({0.5, textureCoordsV}); +} + +void Capsule::vertexRings(unsigned int count, GLfloat centerY, GLfloat startRingAngle, GLfloat ringAngleIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement) { + GLfloat segmentAngleIncrement = 2*PI/segments; + GLfloat x, y, z; + for(unsigned int i = 0; i != count; ++i) { + GLfloat ringAngle = startRingAngle + i*ringAngleIncrement; + x = z = cos(ringAngle); + y = sin(ringAngle); + + for(unsigned int j = 0; j != segments; ++j) { + GLfloat segmentAngle = j*segmentAngleIncrement; + vertices(0)->push_back({x*sin(segmentAngle), centerY+y, z*cos(segmentAngle)}); + normals(0)->push_back({x*sin(segmentAngle), y, z*cos(segmentAngle)}); + + if(textureCoords == TextureCoords::Generate) + textureCoords2D(0)->push_back({j*1.0f/segments, startTextureCoordsV + i*textureCoordsVIncrement}); + } + + /* Duplicate first segment in the ring for additional vertex for texture coordinate */ + if(textureCoords == TextureCoords::Generate) { + vertices(0)->push_back((*vertices(0))[vertices(0)->size()-segments]); + normals(0)->push_back((*normals(0))[normals(0)->size()-segments]); + textureCoords2D(0)->push_back({1.0f, startTextureCoordsV + i*textureCoordsVIncrement}); + } + } +} + +void Capsule::bottomFaceRing() { + for(unsigned int j = 0; j != segments; ++j) { + /* Bottom vertex */ + indices()->push_back(0); + + /* Top right vertex */ + indices()->push_back((j != segments-1 || textureCoords == TextureCoords::Generate) ? + j+2 : 1); + + /* Top left vertex */ + indices()->push_back(j+1); + } +} + +void Capsule::faceRings(unsigned int count) { + unsigned int vertexSegments = segments + (textureCoords == TextureCoords::Generate ? 1 : 0); + + for(unsigned int i = 0; i != count; ++i) { + for(unsigned int j = 0; j != segments; ++j) { + unsigned int bottomLeft = i*vertexSegments+j+1; + unsigned int bottomRight = ((j != segments-1 || textureCoords == TextureCoords::Generate) ? + i*vertexSegments+j+2 : i*segments+1); + unsigned int topLeft = bottomLeft+vertexSegments; + unsigned int topRight = bottomRight+vertexSegments; + + indices()->push_back(bottomLeft); + indices()->push_back(bottomRight); + indices()->push_back(topRight); + indices()->push_back(bottomLeft); + indices()->push_back(topRight); + indices()->push_back(topLeft); + } + } +} + +void Capsule::topFaceRing() { + unsigned int vertexSegments = segments + (textureCoords == TextureCoords::Generate ? 1 : 0); + + for(unsigned int j = 0; j != segments; ++j) { + /* Bottom left vertex */ + indices()->push_back(normals(0)->size()-vertexSegments+j-1); + + /* Bottom right vertex */ + indices()->push_back((j != segments-1 || textureCoords == TextureCoords::Generate) ? + normals(0)->size()-vertexSegments+j : normals(0)->size()-segments-1); + + /* Top vertex */ + indices()->push_back(normals(0)->size()-1); + } +} + +}} diff --git a/src/Primitives/Capsule.h b/src/Primitives/Capsule.h new file mode 100644 index 000000000..f4a199339 --- /dev/null +++ b/src/Primitives/Capsule.h @@ -0,0 +1,69 @@ +#ifndef Magnum_Primitives_Capsule_h +#define Magnum_Primitives_Capsule_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Primitives::Capsule + */ + +#include "Trade/MeshData.h" + +namespace Magnum { namespace Primitives { + +/** +@brief %Capsule primitive + +Cylinder along Y axis with hemispheres instead of caps. +*/ +class Capsule: public Trade::MeshData { + friend class UVSphere; + + public: + /** @brief Whether to generate texture coordinates */ + enum class TextureCoords { + Generate, /**< Generate texture coordinates */ + DontGenerate /**< Don't generate texture coordinates */ + }; + + /** + * @brief Constructor + * @param rings Number of (face) rings for each hemisphere. + * Must be larger or equal to 1. + * @param segments Number of (face) segments. Must be larger or equal to 3. + * @param length Length of the capsule, excluding hemispheres. + * @param textureCoords Whether to generate texture coordinates. + * + * If texture coordinates are generated, vertices of one segment are + * duplicated for texture wrapping. + */ + Capsule(unsigned int rings, unsigned int segments, GLfloat length, TextureCoords textureCoords = TextureCoords::DontGenerate); + + private: + inline Capsule(unsigned int segments, TextureCoords textureCoords): MeshData(Mesh::Primitive::Triangles, new std::vector, {new std::vector()}, {new std::vector()}, textureCoords == TextureCoords::Generate ? std::vector*>{new std::vector()} : std::vector*>()), segments(segments), textureCoords(textureCoords) {} + + void capVertex(GLfloat y, GLfloat normalY, GLfloat textureCoordsV); + void vertexRings(unsigned int count, GLfloat centerY, GLfloat startRingAngle, GLfloat ringAngleIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement); + void bottomFaceRing(); + void faceRings(unsigned int count); + void topFaceRing(); + + unsigned int segments; + TextureCoords textureCoords; +}; + +}} + +#endif diff --git a/src/Primitives/Test/CMakeLists.txt b/src/Primitives/Test/CMakeLists.txt new file mode 100644 index 000000000..dff5ee805 --- /dev/null +++ b/src/Primitives/Test/CMakeLists.txt @@ -0,0 +1,2 @@ +corrade_add_test(CapsuleTest CapsuleTest.h CapsuleTest.cpp ${MAGNUM_PRIMITIVES_LIBRARY}) +corrade_add_test(UVSphereTest UVSphereTest.h UVSphereTest.cpp ${MAGNUM_PRIMITIVES_LIBRARY}) diff --git a/src/Primitives/Test/CapsuleTest.cpp b/src/Primitives/Test/CapsuleTest.cpp new file mode 100644 index 000000000..9347d0bf8 --- /dev/null +++ b/src/Primitives/Test/CapsuleTest.cpp @@ -0,0 +1,151 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/* Less precision */ +#define FLOAT_EQUALITY_PRECISION 1.0e-5 + +#include "CapsuleTest.h" + +#include + +QTEST_APPLESS_MAIN(Magnum::Primitives::Test::CapsuleTest) + +#include "Primitives/Capsule.h" + +using namespace std; + +namespace Magnum { namespace Primitives { namespace Test { + +void CapsuleTest::withoutTextureCoords() { + Capsule capsule(2, 3, 1.0f); + + QVERIFY((*capsule.vertices(0) == vector{ + Vector4(0.0f, -1.5f, 0.0f), + + Vector4(0.0f, -1.20711f, 0.707107f), + Vector4(0.612372f, -1.20711f, -0.353553f), + Vector4(-0.612373f, -1.20711f, -0.353553f), + + Vector4(0.0f, -0.5f, 1.0f), + Vector4(0.866025f, -0.5f, -0.5f), + Vector4(-0.866025f, -0.5f, -0.5f), + + Vector4(0.0f, 0.5f, 1.0f), + Vector4(0.866025f, 0.5f, -0.5f), + Vector4(-0.866025f, 0.5f, -0.5f), + + Vector4(0.0f, 1.20711f, 0.707107f), + Vector4(0.612372f, 1.20711f, -0.353553f), + Vector4(-0.612372f, 1.20711f, -0.353553f), + + Vector4(0.0f, 1.5f, 0.0f) + })); + + QVERIFY((*capsule.normals(0) == vector{ + Vector3(0.0f, -1.0f, 0.0f), + + Vector3(0.0f, -0.707107f, 0.707107f), + Vector3(0.612372f, -0.707107f, -0.353553f), + Vector3(-0.612373f, -0.707107f, -0.353553f), + + Vector3(0.0f, 0.0f, 1.0f), + Vector3(0.866025f, 0.0f, -0.5f), + Vector3(-0.866025f, 0.0f, -0.5f), + + Vector3(0.0f, 0.0f, 1.0f), + Vector3(0.866025f, 0.0f, -0.5f), + Vector3(-0.866025f, 0.0f, -0.5f), + + Vector3(0.0f, 0.707107f, 0.707107f), + Vector3(0.612372f, 0.707107f, -0.353553f), + Vector3(-0.612372f, 0.707107f, -0.353553f), + + Vector3(0.0f, 1.0f, 0.0f) + })); + + QVERIFY((*capsule.indices() == vector{ + 0, 2, 1, 0, 3, 2, 0, 1, 3, + 1, 2, 5, 1, 5, 4, 2, 3, 6, 2, 6, 5, 3, 1, 4, 3, 4, 6, + 4, 5, 8, 4, 8, 7, 5, 6, 9, 5, 9, 8, 6, 4, 7, 6, 7, 9, + 7, 8, 11, 7, 11, 10, 8, 9, 12, 8, 12, 11, 9, 7, 10, 9, 10, 12, + 10, 11, 13, 11, 12, 13, 12, 10, 13 + })); +} + +void CapsuleTest::withTextureCoords() { + Capsule capsule(2, 3, 1.0f, Capsule::TextureCoords::Generate); + + QVERIFY((*capsule.vertices(0) == vector{ + Vector4(0.0f, -1.5f, 0.0f), + + Vector4(0.0f, -1.20711f, 0.707107f), + Vector4(0.612372f, -1.20711f, -0.353553f), + Vector4(-0.612373f, -1.20711f, -0.353553f), + Vector4(0.0f, -1.20711f, 0.707107f), + + Vector4(0.0f, -0.5f, 1.0f), + Vector4(0.866025f, -0.5f, -0.5f), + Vector4(-0.866025f, -0.5f, -0.5f), + Vector4(0.0f, -0.5f, 1.0f), + + Vector4(0.0f, 0.5f, 1.0f), + Vector4(0.866025f, 0.5f, -0.5f), + Vector4(-0.866025f, 0.5f, -0.5f), + Vector4(0.0f, 0.5f, 1.0f), + + Vector4(0.0f, 1.20711f, 0.707107f), + Vector4(0.612372f, 1.20711f, -0.353553f), + Vector4(-0.612372f, 1.20711f, -0.353553f), + Vector4(0.0f, 1.20711f, 0.707107f), + + Vector4(0.0f, 1.5f, 0.0f) + })); + + QVERIFY((*capsule.textureCoords2D(0) == vector{ + Vector2(0.5f, 0.0f), + + Vector2(0.0f, 0.166667f), + Vector2(0.333333f, 0.166667f), + Vector2(0.666667f, 0.166667f), + Vector2(1.0f, 0.166667f), + + Vector2(0.0f, 0.333333f), + Vector2(0.333333f, 0.333333f), + Vector2(0.666667f, 0.333333f), + Vector2(1.0f, 0.333333f), + + Vector2(0.0f, 0.666667f), + Vector2(0.333333f, 0.666667f), + Vector2(0.666667f, 0.666667f), + Vector2(1.0f, 0.666667f), + + Vector2(0.0f, 0.833333f), + Vector2(0.333333f, 0.833333f), + Vector2(0.666667f, 0.833333f), + Vector2(1.0f, 0.833333f), + + Vector2(0.5f, 1.0f) + })); + + QVERIFY((*capsule.indices() == vector{ + 0, 2, 1, 0, 3, 2, 0, 4, 3, + 1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 4, 8, 3, 8, 7, + 5, 6, 10, 5, 10, 9, 6, 7, 11, 6, 11, 10, 7, 8, 12, 7, 12, 11, + 9, 10, 14, 9, 14, 13, 10, 11, 15, 10, 15, 14, 11, 12, 16, 11, 16, 15, + 13, 14, 17, 14, 15, 17, 15, 16, 17 + })); +} + +}}} diff --git a/src/Primitives/Test/CapsuleTest.h b/src/Primitives/Test/CapsuleTest.h new file mode 100644 index 000000000..8eb3789ec --- /dev/null +++ b/src/Primitives/Test/CapsuleTest.h @@ -0,0 +1,32 @@ +#ifndef Magnum_Primitives_Test_CapsuleTest_h +#define Magnum_Primitives_Test_CapsuleTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Primitives { namespace Test { + +class CapsuleTest: public QObject { + Q_OBJECT + + private slots: + void withoutTextureCoords(); + void withTextureCoords(); +}; + +}}} + +#endif diff --git a/src/Primitives/Test/UVSphereTest.cpp b/src/Primitives/Test/UVSphereTest.cpp new file mode 100644 index 000000000..b0ff8090d --- /dev/null +++ b/src/Primitives/Test/UVSphereTest.cpp @@ -0,0 +1,108 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "UVSphereTest.h" + +#include + +#include "Primitives/UVSphere.h" + +using namespace std; + +QTEST_APPLESS_MAIN(Magnum::Primitives::Test::UVSphereTest) + +namespace Magnum { namespace Primitives { namespace Test { + +void UVSphereTest::withoutTextureCoords() { + UVSphere sphere(3, 3); + + QVERIFY((*sphere.vertices(0) == vector{ + Vector4(0.0f, -1.0f, 0.0f), + + Vector4(0.0f, -0.5f, 0.866025f), + Vector4(0.75f, -0.5f, -0.433013f), + Vector4(-0.75f, -0.5f, -0.433013f), + + Vector4(0, 0.5f, 0.866025f), + Vector4(0.75f, 0.5f, -0.433013f), + Vector4(-0.75f, 0.5f, -0.433013f), + + Vector4(0.0f, 1.0f, 0.0f) + })); + + QVERIFY((*sphere.normals(0) == vector{ + Vector3(0.0f, -1.0f, 0.0f), + + Vector3(0.0f, -0.5f, 0.866025f), + Vector3(0.75f, -0.5f, -0.433013f), + Vector3(-0.75f, -0.5f, -0.433013f), + + Vector3(0, 0.5f, 0.866025f), + Vector3(0.75f, 0.5f, -0.433013f), + Vector3(-0.75f, 0.5f, -0.433013f), + + Vector3(0.0f, 1.0f, 0.0f) + })); + + QVERIFY((*sphere.indices() == vector{ + 0, 2, 1, 0, 3, 2, 0, 1, 3, + 1, 2, 5, 1, 5, 4, 2, 3, 6, 2, 6, 5, 3, 1, 4, 3, 4, 6, + 4, 5, 7, 5, 6, 7, 6, 4, 7 + })); +} + +void UVSphereTest::withTextureCoords() { + UVSphere sphere(3, 3, UVSphere::TextureCoords::Generate); + + QVERIFY((*sphere.vertices(0) == vector{ + Vector4(0.0f, -1.0f, 0.0f), + + Vector4(0.0f, -0.5f, 0.866025f), + Vector4(0.75f, -0.5f, -0.433013f), + Vector4(-0.75f, -0.5f, -0.433013f), + Vector4(0.0f, -0.5f, 0.866025f), + + Vector4(0.0f, 0.5f, 0.866025f), + Vector4(0.75f, 0.5f, -0.433013f), + Vector4(-0.75f, 0.5f, -0.433013f), + Vector4(0.0f, 0.5f, 0.866025f), + + Vector4(0.0f, 1.0f, 0.0f) + })); + + QVERIFY((*sphere.textureCoords2D(0) == vector{ + Vector2(0.5f, 0.0f), + + Vector2(0.0f, 0.333333f), + Vector2(0.333333f, 0.333333f), + Vector2(0.666667f, 0.333333f), + Vector2(1.0f, 0.333333f), + + Vector2(0.0f, 0.666667f), + Vector2(0.333333f, 0.666667f), + Vector2(0.666667f, 0.666667f), + Vector2(1.0f, 0.666667f), + + Vector2(0.5f, 1.0f) + })); + + QVERIFY((*sphere.indices() == vector{ + 0, 2, 1, 0, 3, 2, 0, 4, 3, + 1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 4, 8, 3, 8, 7, + 5, 6, 9, 6, 7, 9, 7, 8, 9 + })); +} + +}}} diff --git a/src/Primitives/Test/UVSphereTest.h b/src/Primitives/Test/UVSphereTest.h new file mode 100644 index 000000000..ecfd7e896 --- /dev/null +++ b/src/Primitives/Test/UVSphereTest.h @@ -0,0 +1,32 @@ +#ifndef Magnum_Primitives_Test_UVSphereTest_h +#define Magnum_Primitives_Test_UVSphereTest_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +namespace Magnum { namespace Primitives { namespace Test { + +class UVSphereTest: public QObject { + Q_OBJECT + + private slots: + void withoutTextureCoords(); + void withTextureCoords(); +}; + +}}} + +#endif diff --git a/src/Primitives/UVSphere.cpp b/src/Primitives/UVSphere.cpp new file mode 100644 index 000000000..80d36f718 --- /dev/null +++ b/src/Primitives/UVSphere.cpp @@ -0,0 +1,49 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +#include "UVSphere.h" + +using namespace std; +using namespace Corrade::Utility; + +namespace Magnum { namespace Primitives { + +UVSphere::UVSphere(unsigned int rings, unsigned int segments, TextureCoords textureCoords): Capsule(segments, textureCoords) { + if(rings < 2 || segments < 3) { + Error() << "UVSphere must have at least two rings and three segments"; + assert(0); + } + + GLfloat textureCoordsVIncrement = 1.0f/rings; + GLfloat ringAngleIncrement = PI/rings; + + /* Bottom cap vertex */ + capVertex(-1.0f, -1.0f, 0.0f); + + /* Vertex rings */ + vertexRings(rings-1, 0.0f, -PI/2+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement); + + /* Top cap vertex */ + capVertex(1.0f, 1.0f, 1.0f); + + /* Faces */ + bottomFaceRing(); + faceRings(rings-2); + topFaceRing(); +} + +}} diff --git a/src/Primitives/UVSphere.h b/src/Primitives/UVSphere.h new file mode 100644 index 000000000..4e6be3b63 --- /dev/null +++ b/src/Primitives/UVSphere.h @@ -0,0 +1,43 @@ +#ifndef Magnum_Primitives_UVSphere_h +#define Magnum_Primitives_UVSphere_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Primitives::UVSphere + */ + +#include "Primitives/Capsule.h" + +namespace Magnum { namespace Primitives { + +/** @brief UV Sphere primitive */ +class UVSphere: public Capsule { + public: + /** + * @brief Constructor + * @param rings Number of (face) rings. Must be larger or equal to 2. + * @param segments Number of (face) segments. Must be larger or equal to 3. + * @param textureCoords Whether to generate texture coordinates. + * + * If texture coordinates are generated, vertices of one segment are + * duplicated for texture wrapping. + */ + UVSphere(unsigned int rings, unsigned int segments, TextureCoords textureCoords = TextureCoords::DontGenerate); +}; + +}} + +#endif