diff --git a/src/Primitives/CMakeLists.txt b/src/Primitives/CMakeLists.txt index f2869e0a7..e8e613f92 100644 --- a/src/Primitives/CMakeLists.txt +++ b/src/Primitives/CMakeLists.txt @@ -1,5 +1,6 @@ set(MagnumPrimitives_SRCS Cube.cpp + Icosphere.cpp ) add_library(MagnumPrimitives STATIC ${MagnumPrimitives_SRCS}) diff --git a/src/Primitives/Icosphere.cpp b/src/Primitives/Icosphere.cpp new file mode 100644 index 000000000..021c52acc --- /dev/null +++ b/src/Primitives/Icosphere.cpp @@ -0,0 +1,64 @@ +/* + Copyright © 2010, 2011 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 "Icosphere.h" + +namespace Magnum { namespace Primitives { + +/** + * @todo Use own computed (and more precise) icosahedron data, not these stolen + * from Blender. + */ + +#ifndef DOXYGEN_GENERATING_OUTPUT +const Vector4 _AbstractIcosphere::initialVertices[] = { + Vector4(0, -0.525731f, 0.850651f), + Vector4(0.850651f, 0, 0.525731f), + Vector4(0.850651f, 0, -0.525731f), + Vector4(-0.850651f, 0, -0.525731f), + Vector4(-0.850651f, 0, 0.525731f), + Vector4(-0.525731f, 0.850651f, 0), + Vector4(0.525731f, 0.850651f, 0), + Vector4(0.525731f, -0.850651f, 0), + Vector4(-0.525731f, -0.850651f, 0), + Vector4(0, -0.525731f, -0.850651f), + Vector4(0, 0.525731f, -0.850651f), + Vector4(0, 0.525731f, 0.850651f), +}; +const GLubyte _AbstractIcosphere::initialIndices[] = { + 1, 2, 6, + 1, 7, 2, + 3, 4, 5, + 4, 3, 8, + 6, 5, 11, + 5, 6, 10, + 9, 10, 2, + 10, 9, 3, + 7, 8, 9, + 8, 7, 0, + 11, 0, 1, + 0, 11, 4, + 6, 2, 10, + 1, 6, 11, + 3, 5, 10, + 5, 4, 11, + 2, 7, 9, + 7, 1, 0, + 3, 9, 8, + 4, 8, 0 +}; +#endif + +}} diff --git a/src/Primitives/Icosphere.h b/src/Primitives/Icosphere.h new file mode 100644 index 000000000..4eb6e74e8 --- /dev/null +++ b/src/Primitives/Icosphere.h @@ -0,0 +1,79 @@ +#ifndef Magnum_Primitives_Icosphere_h +#define Magnum_Primitives_Icosphere_h +/* + Copyright © 2010, 2011 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::Icosphere + */ + +#include "AbstractPrimitive.h" +#include "MeshBuilder.h" +#include "SizeTraits.h" + +namespace Magnum { namespace Primitives { + +#ifndef DOXYGEN_GENERATING_OUTPUT +class _AbstractIcosphere { + public: + ~_AbstractIcosphere() {} + + protected: + static const Vector4 initialVertices[]; + static const GLubyte initialIndices[]; +}; +#endif + +/** + * @brief Icosphere primitive + * @tparam subdivisions Number of subdivisions + */ +template class Icosphere: public AbstractPrimitive::value*20*3>::value>::SizeType>, _AbstractIcosphere { + public: + Icosphere() { + if(vertexCount() == 0) subdivide(); + } + + inline Mesh::Primitive primitive() const { return Mesh::Triangles; } + inline size_t vertexCount() const { return builder()->vertexCount(); } + inline size_t indexCount() const { return builder()->faceCount()*3; } + + inline void build(IndexedMesh* mesh, Buffer* vertexBuffer) { + /* mesh is prepared by the builder, no need to call prepareMesh */ + builder()->build(mesh, vertexBuffer, Buffer::DrawStatic, Buffer::DrawStatic); + } + + private: + static MeshBuilder* builder() { + static MeshBuilder* _builder = nullptr; + if(!_builder) _builder = new MeshBuilder(); + return _builder; + } + + static void subdivide() { + builder()->setData(initialVertices, initialIndices, 12, 60); + + for(size_t i = 0; i != subdivisions; ++i) + builder()->subdivide([](const Vector4& a, const Vector4& b) { + return (a+b).xyz().normalized(); + }); + + if(subdivisions) builder()->cleanMesh(); + } +}; + +}} + +#endif