diff --git a/doc/changelog.dox b/doc/changelog.dox index 98d0fb02c..da66e21a0 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -53,7 +53,8 @@ See also: @subsubsection changelog-latest-new-primitives Primitives library -- New @ref Primitives::circle3DSolid() and @ref Primitives::circle3DWireframe() +- New @ref Primitives::circle3DSolid(), @ref Primitives::circle3DWireframe(), + @ref Primitives::coneSolid() and @ref Primitives::coneWireframe() primitives @subsection changelog-latest-deprecated Deprecated APIs diff --git a/doc/generated/primitives.cpp b/doc/generated/primitives.cpp index 0d16ac2b7..0b1fee72c 100644 --- a/doc/generated/primitives.cpp +++ b/doc/generated/primitives.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,7 @@ struct PrimitiveVisualizer: Platform::WindowlessApplication { std::pair capsule3DWireframe(); std::pair circle3DWireframe(); std::pair crosshair3D(); + std::pair coneWireframe(); std::pair cubeWireframe(); std::pair cylinderWireframe(); std::pair line3D(); @@ -103,6 +105,7 @@ struct PrimitiveVisualizer: Platform::WindowlessApplication { std::pair capsule3DSolid(); std::pair circle3DSolid(); + std::pair coneSolid(); std::pair cubeSolid(); std::pair cylinderSolid(); std::pair icosphereSolid(); @@ -251,6 +254,7 @@ int PrimitiveVisualizer::exec() { for(auto fun: {&PrimitiveVisualizer::capsule3DWireframe, &PrimitiveVisualizer::circle3DWireframe, &PrimitiveVisualizer::crosshair3D, + &PrimitiveVisualizer::coneWireframe, &PrimitiveVisualizer::cubeWireframe, &PrimitiveVisualizer::cylinderWireframe, &PrimitiveVisualizer::line3D, @@ -330,6 +334,7 @@ int PrimitiveVisualizer::exec() { for(auto fun: {&PrimitiveVisualizer::capsule3DSolid, &PrimitiveVisualizer::circle3DSolid, + &PrimitiveVisualizer::coneSolid, &PrimitiveVisualizer::cubeSolid, &PrimitiveVisualizer::cylinderSolid, &PrimitiveVisualizer::icosphereSolid, @@ -404,6 +409,10 @@ std::pair PrimitiveVisualizer::crosshair3D() { return {Primitives::crosshair3D(), "crosshair3d.png"}; } +std::pair PrimitiveVisualizer::coneWireframe() { + return {Primitives::coneWireframe(32, 1.25f), "conewireframe.png"}; +} + std::pair PrimitiveVisualizer::cubeWireframe() { return {Primitives::cubeWireframe(), "cubewireframe.png"}; } @@ -444,6 +453,10 @@ std::pair PrimitiveVisualizer::circle3DSolid() { return {Primitives::circle3DSolid(16), "circle3dsolid.png"}; } +std::pair PrimitiveVisualizer::coneSolid() { + return {Primitives::coneSolid(1, 12, 1.25f, Primitives::ConeFlag::CapEnd), "conesolid.png"}; +} + std::pair PrimitiveVisualizer::cubeSolid() { return {Primitives::cubeSolid(), "cubesolid.png"}; } diff --git a/doc/primitives-conesolid.png b/doc/primitives-conesolid.png new file mode 100644 index 000000000..41a979f1e Binary files /dev/null and b/doc/primitives-conesolid.png differ diff --git a/doc/primitives-conewireframe.png b/doc/primitives-conewireframe.png new file mode 100644 index 000000000..209c1394a Binary files /dev/null and b/doc/primitives-conewireframe.png differ diff --git a/src/Magnum/Primitives/CMakeLists.txt b/src/Magnum/Primitives/CMakeLists.txt index e6391f7a6..7ab1d453f 100644 --- a/src/Magnum/Primitives/CMakeLists.txt +++ b/src/Magnum/Primitives/CMakeLists.txt @@ -28,6 +28,7 @@ set(MagnumPrimitives_SRCS Capsule.cpp Circle.cpp Crosshair.cpp + Cone.cpp Cube.cpp Cylinder.cpp Icosphere.cpp @@ -44,6 +45,7 @@ set(MagnumPrimitives_HEADERS Capsule.h Circle.h Crosshair.h + Cone.h Cube.h Cylinder.h Icosphere.h diff --git a/src/Magnum/Primitives/Capsule.cpp b/src/Magnum/Primitives/Capsule.cpp index f6d123a2c..c0295b893 100644 --- a/src/Magnum/Primitives/Capsule.cpp +++ b/src/Magnum/Primitives/Capsule.cpp @@ -112,7 +112,7 @@ Trade::MeshData3D capsule3DSolid(const UnsignedInt hemisphereRings, const Unsign capsule.hemisphereVertexRings(hemisphereRings-1, -halfLength, -Rad(Constants::piHalf())+hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement); /* Rings of cylinder */ - capsule.cylinderVertexRings(cylinderRings+1, -halfLength, 2.0f*halfLength/cylinderRings, 1.0f/height, 2.0f*halfLength/(cylinderRings*height)); + capsule.cylinderVertexRings(cylinderRings+1, -halfLength, {0.0f, 2.0f*halfLength/cylinderRings}, 1.0f/height, 2.0f*halfLength/(cylinderRings*height)); /* Rings of top hemisphere */ capsule.hemisphereVertexRings(hemisphereRings-1, halfLength, hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, (1.0f + 2.0f*halfLength)/height+hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement); diff --git a/src/Magnum/Primitives/Cone.cpp b/src/Magnum/Primitives/Cone.cpp new file mode 100644 index 000000000..a680e64aa --- /dev/null +++ b/src/Magnum/Primitives/Cone.cpp @@ -0,0 +1,73 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Cone.h" + +#include "Magnum/Mesh.h" +#include "Magnum/Math/Color.h" +#include "Magnum/Primitives/Implementation/Spheroid.h" +#include "Magnum/Primitives/Implementation/WireframeSpheroid.h" +#include "Magnum/Trade/MeshData3D.h" + +namespace Magnum { namespace Primitives { + +Trade::MeshData3D coneSolid(const UnsignedInt rings, const UnsignedInt segments, const Float halfLength, const ConeFlags flags) { + CORRADE_ASSERT(rings >= 1 && segments >= 3, + "Primitives::coneSolid(): at least one ring and three segments expected", + (Trade::MeshData3D{MeshPrimitive::Triangles, {}, {}, {}, {}, {}, nullptr})); + + Implementation::Spheroid cone{segments, flags & ConeFlag::GenerateTextureCoords ? Implementation::Spheroid::TextureCoords::Generate : Implementation::Spheroid::TextureCoords::DontGenerate}; + + const Float length = 2.0f*halfLength; + const Float textureCoordsV = flags & ConeFlag::CapEnd ? 1.0f/(length + 1.0f) : 0.0f; + + /* Bottom cap */ + if(flags & ConeFlag::CapEnd) { + cone.capVertex(-halfLength, -1.0f, 0.0f); + cone.capVertexRing(-halfLength, textureCoordsV, Vector3::yAxis(-1.0f)); + } + + /* Vertex rings */ + cone.cylinderVertexRings(rings+1, -halfLength, {-1.0f/rings, length/rings}, textureCoordsV, length/(rings*(flags & ConeFlag::CapEnd ? length + 1.0f : length))); + + /* Faces */ + if(flags & ConeFlag::CapEnd) cone.bottomFaceRing(); + cone.faceRings(rings, flags & ConeFlag::CapEnd ? (1 + segments) : 0); + + return cone.finalize(); +} + +Trade::MeshData3D coneWireframe(const UnsignedInt segments, const Float halfLength) { + CORRADE_ASSERT(segments >= 4 && segments%4 == 0, + "Primitives::cylinderWireframe(): multiples of 4 segments expected", + (Trade::MeshData3D{MeshPrimitive::Lines, {}, {}, {}, {}, {}, nullptr})); + + Implementation::WireframeSpheroid cone{segments/4}; + cone.ring(-halfLength); + cone.topHemisphere(halfLength - 1.0f, 1); + return cone.finalize(); +} + +}} diff --git a/src/Magnum/Primitives/Cone.h b/src/Magnum/Primitives/Cone.h new file mode 100644 index 000000000..e25a79e6e --- /dev/null +++ b/src/Magnum/Primitives/Cone.h @@ -0,0 +1,100 @@ +#ifndef Magnum_Primitives_Cone_h +#define Magnum_Primitives_Cone_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Function @ref Magnum::Primitives::coneSolid(), @ref Magnum::Primitives::coneWireframe() + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Primitives/visibility.h" +#include "Magnum/Trade/Trade.h" + +namespace Magnum { namespace Primitives { + +/** +@brief Cone flag + +@see @ref ConeFlags, @ref coneSolid() +*/ +enum class ConeFlag { + GenerateTextureCoords = 1 << 0, /**< Generate texture coordinates */ + CapEnd = 1 << 1 /**< Cap end */ +}; + +/** +@brief Cone flags + +@see @ref coneSolid() +*/ +typedef Containers::EnumSet ConeFlags; + +CORRADE_ENUMSET_OPERATORS(ConeFlags) + +/** +@brief Solid 3D cone +@param rings Number of (face) rings. Must be larger or equal to + @cpp 1 @ce. +@param segments Number of (face) segments. Must be larger or equal to + @cpp 3 @ce. +@param halfLength Half the cone length +@param flags Flags + +Cone along Y axis of radius @cpp 1.0f @ce. Indexed +@ref MeshPrimitive::Triangles. Note that in order to have properly smooth +normals over the whole area, the tip consists of @cpp segments*2 @ce vertices +instead of just one. + +@image html primitives-conesolid.png + +The cone is by default created with radius set to @f$ 1.0 @f$. In order to get +radius @f$ r @f$, length @f$ l @f$ and preserve correct normals, set +@p halfLength to @f$ 0.5 \frac{l}{r} @f$ and then scale all +@ref Trade::MeshData3D::positions() by @f$ r @f$, for example using +@ref MeshTools::transformPointsInPlace(). +@see @ref coneWireframe(), @ref cylinderSolid() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D coneSolid(UnsignedInt rings, UnsignedInt segments, Float halfLength, ConeFlags flags = {}); + +/** +@brief Wireframe 3D cone +@param segments Number of (line) segments. Must be larger or equal to + @cpp 4 @ce and multiple of @cpp 4 @ce. +@param halfLength Half the cone length + +Cone along Y axis of radius @cpp 1.0f @ce. Indexed @ref MeshPrimitive::Lines. + +@image html primitives-conewireframe.png + +@see @ref coneSolid(), @ref cylinderWireframe() +*/ +MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D coneWireframe(UnsignedInt segments, Float halfLength); + +}} + +#endif diff --git a/src/Magnum/Primitives/Cylinder.cpp b/src/Magnum/Primitives/Cylinder.cpp index a7781e47a..09c3ea894 100644 --- a/src/Magnum/Primitives/Cylinder.cpp +++ b/src/Magnum/Primitives/Cylinder.cpp @@ -50,7 +50,7 @@ Trade::MeshData3D cylinderSolid(const UnsignedInt rings, const UnsignedInt segme } /* Vertex rings */ - cylinder.cylinderVertexRings(rings+1, -halfLength, length/rings, textureCoordsV, length/(rings*(flags & CylinderFlag::CapEnds ? length + 2.0f : length))); + cylinder.cylinderVertexRings(rings+1, -halfLength, {0.0f, length/rings}, textureCoordsV, length/(rings*(flags & CylinderFlag::CapEnds ? length + 2.0f : length))); /* Top cap */ if(flags & CylinderFlag::CapEnds) { diff --git a/src/Magnum/Primitives/Cylinder.h b/src/Magnum/Primitives/Cylinder.h index b466125e7..e57ae14d0 100644 --- a/src/Magnum/Primitives/Cylinder.h +++ b/src/Magnum/Primitives/Cylinder.h @@ -44,7 +44,7 @@ namespace Magnum { namespace Primitives { */ enum class CylinderFlag { GenerateTextureCoords = 1 << 0, /**< Generate texture coordinates */ - CapEnds = 1 << 1 /**< Cap ends */ + CapEnds = 1 << 1 /**< Cap ends */ }; /** @@ -77,7 +77,7 @@ get radius @f$ r @f$, length @f$ l @f$ and preserve correct normals, set @p halfLength to @f$ 0.5 \frac{l}{r} @f$ and then scale all @ref Trade::MeshData3D::positions() by @f$ r @f$, for example using @ref MeshTools::transformPointsInPlace(). -@see @ref cylinderWireframe() +@see @ref cylinderWireframe(), @ref coneSolid() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D cylinderSolid(UnsignedInt rings, UnsignedInt segments, Float halfLength, CylinderFlags flags = {}); @@ -94,7 +94,7 @@ Cylinder along Y axis of radius @cpp 1.0f @ce. Indexed @image html primitives-cylinderwireframe.png -@see @ref cylinderSolid() +@see @ref cylinderSolid(), @ref coneWireframe() */ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D cylinderWireframe(UnsignedInt rings, UnsignedInt segments, Float halfLength); diff --git a/src/Magnum/Primitives/Implementation/Spheroid.cpp b/src/Magnum/Primitives/Implementation/Spheroid.cpp index 026f59f13..acfe9ae02 100644 --- a/src/Magnum/Primitives/Implementation/Spheroid.cpp +++ b/src/Magnum/Primitives/Implementation/Spheroid.cpp @@ -68,13 +68,16 @@ void Spheroid::hemisphereVertexRings(UnsignedInt count, Float centerY, Rad start } } -void Spheroid::cylinderVertexRings(UnsignedInt count, Float startY, Float yIncrement, Float startTextureCoordsV, Float textureCoordsVIncrement) { +void Spheroid::cylinderVertexRings(const UnsignedInt count, const Float startY, const Vector2& increment, const Float startTextureCoordsV, const Float textureCoordsVIncrement) { + const Vector2 baseNormal = -increment.perpendicular().normalized(); + Vector2 base = {1.0f, startY}; + Rad segmentAngleIncrement(Constants::tau()/segments); for(UnsignedInt i = 0; i != count; ++i) { for(UnsignedInt j = 0; j != segments; ++j) { Rad segmentAngle = Float(j)*segmentAngleIncrement; - positions.emplace_back(Math::sin(segmentAngle), startY, Math::cos(segmentAngle)); - normals.emplace_back(Math::sin(segmentAngle), 0.0f, Math::cos(segmentAngle)); + positions.emplace_back(base.x()*Math::sin(segmentAngle), base.y(), base.x()*Math::cos(segmentAngle)); + normals.emplace_back(baseNormal.x()*Math::sin(segmentAngle), baseNormal.y(), baseNormal.x()*Math::cos(segmentAngle)); if(textureCoords == TextureCoords::Generate) textureCoords2D.emplace_back(j*1.0f/segments, startTextureCoordsV + i*textureCoordsVIncrement); @@ -87,7 +90,7 @@ void Spheroid::cylinderVertexRings(UnsignedInt count, Float startY, Float yIncre textureCoords2D.emplace_back(1.0f, startTextureCoordsV + i*textureCoordsVIncrement); } - startY += yIncrement; + base += increment; } } diff --git a/src/Magnum/Primitives/Implementation/Spheroid.h b/src/Magnum/Primitives/Implementation/Spheroid.h index ad6e3f244..dbabebbca 100644 --- a/src/Magnum/Primitives/Implementation/Spheroid.h +++ b/src/Magnum/Primitives/Implementation/Spheroid.h @@ -43,7 +43,7 @@ class Spheroid { void capVertex(Float y, Float normalY, Float textureCoordsV); void hemisphereVertexRings(UnsignedInt count, Float centerY, Rad startRingAngle, Rad ringAngleIncrement, Float startTextureCoordsV, Float textureCoordsVIncrement); - void cylinderVertexRings(UnsignedInt count, Float startY, Float yIncrement, Float startTextureCoordsV, Float textureCoordsVIncrement); + void cylinderVertexRings(UnsignedInt count, Float startY, const Vector2& increment, Float startTextureCoordsV, Float textureCoordsVIncrement); void bottomFaceRing(); void faceRings(UnsignedInt count, UnsignedInt offset = 1); void topFaceRing(); diff --git a/src/Magnum/Primitives/Test/CMakeLists.txt b/src/Magnum/Primitives/Test/CMakeLists.txt index b7bc7476c..28eb3a469 100644 --- a/src/Magnum/Primitives/Test/CMakeLists.txt +++ b/src/Magnum/Primitives/Test/CMakeLists.txt @@ -28,6 +28,7 @@ corrade_add_test(PrimitivesCapsuleTest CapsuleTest.cpp LIBRARIES MagnumPrimitive corrade_add_test(PrimitivesCircleTest CircleTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesCrosshairTest CrosshairTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesCubeTest CubeTest.cpp LIBRARIES MagnumPrimitives) +corrade_add_test(PrimitivesConeTest ConeTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesCylinderTest CylinderTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesIcosphereTest IcosphereTest.cpp LIBRARIES MagnumPrimitives) corrade_add_test(PrimitivesLineTest LineTest.cpp LIBRARIES MagnumPrimitives) @@ -41,6 +42,7 @@ set_target_properties( PrimitivesCircleTest PrimitivesCrosshairTest PrimitivesCubeTest + PrimitivesConeTest PrimitivesCylinderTest PrimitivesIcosphereTest PrimitivesLineTest diff --git a/src/Magnum/Primitives/Test/ConeTest.cpp b/src/Magnum/Primitives/Test/ConeTest.cpp new file mode 100644 index 000000000..bf55db3a2 --- /dev/null +++ b/src/Magnum/Primitives/Test/ConeTest.cpp @@ -0,0 +1,200 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "Magnum/Math/Vector3.h" +#include "Magnum/Primitives/Cone.h" +#include "Magnum/Trade/MeshData3D.h" + +namespace Magnum { namespace Primitives { namespace Test { + +struct ConeTest: TestSuite::Tester { + explicit ConeTest(); + + void solidWithoutAnything(); + void solidWithTextureCoordsAndCaps(); + void wireframe(); +}; + +ConeTest::ConeTest() { + addTests({&ConeTest::solidWithoutAnything, + &ConeTest::solidWithTextureCoordsAndCaps, + &ConeTest::wireframe}); +} + +void ConeTest::solidWithoutAnything() { + Trade::MeshData3D cone = coneSolid(2, 3, 1.0f); + + CORRADE_COMPARE_AS(cone.positions(0), (std::vector{ + {0.0f, -1.0f, 1.0f}, + {0.866025f, -1.0f, -0.5f}, + {-0.866025f, -1.0f, -0.5f}, + + {0.0f, 0.0f, 0.5f}, + {0.433013f, 0.0f, -0.25f}, + {-0.433013f, 0.0f, -0.25f}, + + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(cone.normals(0), (std::vector{ + {0.0f, 0.447214f, 0.894427f}, + {0.774597f, 0.447214f, -0.447214f}, + {-0.774597f, 0.447214f, -0.447214f}, + + {0.0f, 0.447214f, 0.894427f}, + {0.774597f, 0.447214f, -0.447214f}, + {-0.774597f, 0.447214f, -0.447214f}, + + {0.0f, 0.447214f, 0.894427f}, + {0.774597f, 0.447214f, -0.447214f}, + {-0.774597f, 0.447214f, -0.447214f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(cone.indices(), (std::vector{ + 0, 1, 4, 0, 4, 3, 1, 2, 5, 1, 5, 4, 2, 0, 3, 2, 3, 5, + 3, 4, 7, 3, 7, 6, 4, 5, 8, 4, 8, 7, 5, 3, 6, 5, 6, 8 + }), TestSuite::Compare::Container); +} + +void ConeTest::solidWithTextureCoordsAndCaps() { + Trade::MeshData3D cone = coneSolid(2, 3, 1.0f, ConeFlag::GenerateTextureCoords|ConeFlag::CapEnd); + + /* Bottom ring duplicated because it has different normals, first vertex of + each ring duplicated because it has different texture coordinates */ + CORRADE_COMPARE_AS(cone.positions(0), (std::vector{ + {0.0f, -1.0f, 0.0f}, + + {0.0f, -1.0f, 1.0f}, + {0.866025f, -1.0f, -0.5f}, + {-0.866025f, -1.0f, -0.5f}, + {0.0f, -1.0f, 1.0f}, + + {0.0f, -1.0f, 1.0f}, + {0.866025f, -1.0f, -0.5f}, + {-0.866025f, -1.0f, -0.5f}, + {0.0f, -1.0f, 1.0f}, + + {0.0f, 0.0f, 0.5f}, + {0.433013f, 0.0f, -0.25f}, + {-0.433013f, 0.0f, -0.25f}, + {0.0f, 0.0f, 0.5f}, + + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(cone.normals(0), (std::vector{ + {0.0f, -1.0f, 0.0f}, + + {0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + + {0.0f, 0.447214f, 0.894427f}, + {0.774597f, 0.447214f, -0.447214f}, + {-0.774597f, 0.447214f, -0.447214f}, + {0.0f, 0.447214f, 0.894427f}, + + {0.0f, 0.447214f, 0.894427f}, + {0.774597f, 0.447214f, -0.447214f}, + {-0.774597f, 0.447214f, -0.447214f}, + {0.0f, 0.447214f, 0.894427f}, + + {0.0f, 0.447214f, 0.894427f}, + {0.774597f, 0.447214f, -0.447214f}, + {-0.774597f, 0.447214f, -0.447214f}, + {0.0f, 0.447214f, 0.894427f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE_AS(cone.textureCoords2D(0), (std::vector{ + {0.5f, 0.0f}, + + {0.0f, 0.333333f}, + {0.333333f, 0.333333f}, + {0.666667f, 0.333333f}, + {1.0f, 0.333333f}, + + {0.0f, 0.333333f}, + {0.333333f, 0.333333f}, + {0.666667f, 0.333333f}, + {1.0f, 0.333333f}, + + {0.0f, 0.666667f}, + {0.333333f, 0.666667f}, + {0.666667f, 0.666667f}, + {1.0f, 0.666667f}, + + {0.0f, 1.0f}, + {0.333333f, 1.0f}, + {0.666667f, 1.0f}, + {1.0f, 1.0f}, + }), TestSuite::Compare::Container); + + /* Faces of the caps and sides do not share any vertices due to different + normals */ + CORRADE_COMPARE_AS(cone.indices(), (std::vector{ + 0, 2, 1, 0, 3, 2, 0, 4, 3, + 4, 5, 9, 4, 9, 8, 5, 6, 10, 5, 10, 9, 6, 7, 11, 6, 11, 10, + 8, 9, 13, 8, 13, 12, 9, 10, 14, 9, 14, 13, 10, 11, 15, 10, 15, 14 + }), TestSuite::Compare::Container); +} + +void ConeTest::wireframe() { + Trade::MeshData3D cone = coneWireframe(8, 1.5f); + + CORRADE_COMPARE_AS(cone.positions(0), (std::vector{ + {0.0f, -1.5f, 1.0f}, + {1.0f, -1.5f, 0.0f}, + {0.0f, -1.5f, -1.0f}, + {-1.0f, -1.5f, 0.0f}, + {0.707107f, -1.5f, 0.707107f}, + {0.707107f, -1.5f, -0.707107f}, + {-0.707107f, -1.5f, -0.707107f}, + {-0.707107f, -1.5f, 0.707107f}, + + {0.0f, 1.5f, 0.0f} + }), TestSuite::Compare::Container); + + CORRADE_COMPARE(cone.normalArrayCount(), 0); + + CORRADE_COMPARE_AS(cone.indices(), (std::vector{ + 0, 4, 1, 5, 2, 6, 3, 7, + 4, 1, 5, 2, 6, 3, 7, 0, + + 0, 8, 1, 8, 2, 8, 3, 8 + }), TestSuite::Compare::Container); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Primitives::Test::ConeTest) diff --git a/src/Magnum/Primitives/Test/CylinderTest.cpp b/src/Magnum/Primitives/Test/CylinderTest.cpp index 959e4181d..cc7ea4fe4 100644 --- a/src/Magnum/Primitives/Test/CylinderTest.cpp +++ b/src/Magnum/Primitives/Test/CylinderTest.cpp @@ -86,7 +86,8 @@ void CylinderTest::solidWithoutAnything() { void CylinderTest::solidWithTextureCoordsAndCaps() { Trade::MeshData3D cylinder = cylinderSolid(2, 3, 1.5f, CylinderFlag::GenerateTextureCoords|CylinderFlag::CapEnds); - /* First and last ring are duplicated because they have different normals */ + /* Bottom ring duplicated because it has different normals, first vertex of + each ring duplicated because it has different texture coordinates */ CORRADE_COMPARE_AS(cylinder.positions(0), (std::vector{ {0.0f, -1.5f, 0.0f},