Browse Source

Primitives: textured circle primitive.

pull/364/head
Vladimír Vondruš 7 years ago
parent
commit
8ef975616f
  1. 5
      doc/changelog.dox
  2. 32
      src/Magnum/Primitives/Circle.cpp
  3. 25
      src/Magnum/Primitives/Circle.h
  4. 70
      src/Magnum/Primitives/Test/CircleTest.cpp

5
doc/changelog.dox

@ -207,6 +207,11 @@ See also:
bootstrap project for using Magnum together with wxWidgets (see bootstrap project for using Magnum together with wxWidgets (see
[mosra/magnum-bootstrap#19](https://github.com/mosra/magnum-bootstrap/pull/19)) [mosra/magnum-bootstrap#19](https://github.com/mosra/magnum-bootstrap/pull/19))
@subsubsection changelog-latest-new-primitives Primitives library
- @ref Primitives::circle2DSolid() and @ref Primitives::circle3DSolid()
can now generate a textured mesh
@subsubsection changelog-latest-new-scenegraph SceneGraph library @subsubsection changelog-latest-new-scenegraph SceneGraph library
- Added @ref SceneGraph::AbstractObject::Type / - Added @ref SceneGraph::AbstractObject::Type /

32
src/Magnum/Primitives/Circle.cpp

@ -33,15 +33,21 @@
namespace Magnum { namespace Primitives { namespace Magnum { namespace Primitives {
Trade::MeshData2D circle2DSolid(const UnsignedInt segments) { Trade::MeshData2D circle2DSolid(const UnsignedInt segments, CircleTextureCoords textureCoords) {
CORRADE_ASSERT(segments >= 3, "Primitives::circle2DSolid(): segments must be >= 3", CORRADE_ASSERT(segments >= 3, "Primitives::circle2DSolid(): segments must be >= 3",
(Trade::MeshData2D{MeshPrimitive::TriangleFan, {}, {}, {}, {}, nullptr})); (Trade::MeshData2D{MeshPrimitive::TriangleFan, {}, {}, {}, {}, nullptr}));
std::vector<Vector2> positions; std::vector<Vector2> positions;
positions.reserve(segments + 2); positions.reserve(segments + 2);
std::vector<std::vector<Vector2>> textureCoordinates;
if(textureCoords == CircleTextureCoords::Generate)
textureCoordinates.emplace_back();
/* Central point */ /* Central point */
positions.emplace_back(); positions.emplace_back();
if(textureCoords == CircleTextureCoords::Generate)
textureCoordinates.front().emplace_back(0.5f, 0.5f);
/* Points on circle. The first/last point is here twice to close the circle /* Points on circle. The first/last point is here twice to close the circle
properly. */ properly. */
@ -49,10 +55,14 @@ Trade::MeshData2D circle2DSolid(const UnsignedInt segments) {
for(UnsignedInt i = 0; i != segments + 1; ++i) { for(UnsignedInt i = 0; i != segments + 1; ++i) {
const Rad angle(Float(i)*angleIncrement); const Rad angle(Float(i)*angleIncrement);
const std::pair<Float, Float> sincos = Math::sincos(angle); const std::pair<Float, Float> sincos = Math::sincos(angle);
positions.emplace_back(sincos.second, sincos.first); Vector2 position{sincos.second, sincos.first};
positions.emplace_back(position);
if(textureCoords == CircleTextureCoords::Generate)
textureCoordinates.front().emplace_back(position*0.5f + Vector2{0.5f});
} }
return Trade::MeshData2D{MeshPrimitive::TriangleFan, {}, {std::move(positions)}, {}, {}, nullptr}; return Trade::MeshData2D{MeshPrimitive::TriangleFan, {}, {std::move(positions)}, std::move(textureCoordinates), {}, nullptr};
} }
Trade::MeshData2D circle2DWireframe(const UnsignedInt segments) { Trade::MeshData2D circle2DWireframe(const UnsignedInt segments) {
@ -73,15 +83,21 @@ Trade::MeshData2D circle2DWireframe(const UnsignedInt segments) {
return Trade::MeshData2D{MeshPrimitive::LineLoop, {}, {std::move(positions)}, {}, {}, nullptr}; return Trade::MeshData2D{MeshPrimitive::LineLoop, {}, {std::move(positions)}, {}, {}, nullptr};
} }
Trade::MeshData3D circle3DSolid(const UnsignedInt segments) { Trade::MeshData3D circle3DSolid(const UnsignedInt segments, CircleTextureCoords textureCoords) {
CORRADE_ASSERT(segments >= 3, "Primitives::circle3DSolid(): segments must be >= 3", CORRADE_ASSERT(segments >= 3, "Primitives::circle3DSolid(): segments must be >= 3",
(Trade::MeshData3D{MeshPrimitive::TriangleFan, {}, {}, {}, {}, {}, nullptr})); (Trade::MeshData3D{MeshPrimitive::TriangleFan, {}, {}, {}, {}, {}, nullptr}));
std::vector<Vector3> positions; std::vector<Vector3> positions;
positions.reserve(segments + 2); positions.reserve(segments + 2);
std::vector<std::vector<Vector2>> textureCoordinates;
if(textureCoords == CircleTextureCoords::Generate)
textureCoordinates.emplace_back();
/* Central point */ /* Central point */
positions.emplace_back(); positions.emplace_back();
if(textureCoords == CircleTextureCoords::Generate)
textureCoordinates.front().emplace_back(0.5f, 0.5f);
/* Points on circle. The first/last point is here twice to close the circle /* Points on circle. The first/last point is here twice to close the circle
properly. */ properly. */
@ -89,13 +105,17 @@ Trade::MeshData3D circle3DSolid(const UnsignedInt segments) {
for(UnsignedInt i = 0; i != segments + 1; ++i) { for(UnsignedInt i = 0; i != segments + 1; ++i) {
const Rad angle(Float(i)*angleIncrement); const Rad angle(Float(i)*angleIncrement);
const std::pair<Float, Float> sincos = Math::sincos(angle); const std::pair<Float, Float> sincos = Math::sincos(angle);
positions.emplace_back(sincos.second, sincos.first, 0.0f); Vector3 position{sincos.second, sincos.first, 0.0f};
positions.emplace_back(position);
if(textureCoords == CircleTextureCoords::Generate)
textureCoordinates.front().emplace_back(position.xy()*0.5f + Vector2{0.5f});
} }
/* Normals. All pointing in the same direction. */ /* Normals. All pointing in the same direction. */
std::vector<Vector3> normals{segments + 2, Vector3::zAxis(1.0f)}; std::vector<Vector3> normals{segments + 2, Vector3::zAxis(1.0f)};
return Trade::MeshData3D{MeshPrimitive::TriangleFan, {}, {std::move(positions)}, {std::move(normals)}, {}, {}, nullptr}; return Trade::MeshData3D{MeshPrimitive::TriangleFan, {}, {std::move(positions)}, {std::move(normals)}, std::move(textureCoordinates), {}, nullptr};
} }
Trade::MeshData3D circle3DWireframe(const UnsignedInt segments) { Trade::MeshData3D circle3DWireframe(const UnsignedInt segments) {

25
src/Magnum/Primitives/Circle.h

@ -34,9 +34,21 @@
namespace Magnum { namespace Primitives { namespace Magnum { namespace Primitives {
/**
@brief Whether to generate circle texture coordinates
@see @ref circle2DSolid(), @ref circle3DSolid()
*/
enum class CircleTextureCoords: UnsignedByte {
DontGenerate, /**< Don't generate texture coordinates */
Generate /**< Generate texture coordinates */
};
/** /**
@brief Solid 2D circle @brief Solid 2D circle
@param segments Number of segments. Must be greater or equal to @cpp 3 @ce. @param segments Number of segments. Must be greater or equal to
@cpp 3 @ce.
@param textureCoords Whether to generate texture coordinates
Circle with radius @cpp 1.0f @ce. Non-indexed @ref MeshPrimitive::TriangleFan. Circle with radius @cpp 1.0f @ce. Non-indexed @ref MeshPrimitive::TriangleFan.
@ -44,11 +56,12 @@ Circle with radius @cpp 1.0f @ce. Non-indexed @ref MeshPrimitive::TriangleFan.
@see @ref circle2DWireframe(), @ref circle3DSolid() @see @ref circle2DWireframe(), @ref circle3DSolid()
*/ */
MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D circle2DSolid(UnsignedInt segments); MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D circle2DSolid(UnsignedInt segments, CircleTextureCoords textureCoords = CircleTextureCoords::DontGenerate);
/** /**
@brief Wireframe 2D circle @brief Wireframe 2D circle
@param segments Number of segments. Must be greater or equal to @cpp 3 @ce. @param segments Number of segments. Must be greater or equal to
@cpp 3 @ce.
Circle with radius @cpp 1.0f @ce. Non-indexed @ref MeshPrimitive::LineLoop. Circle with radius @cpp 1.0f @ce. Non-indexed @ref MeshPrimitive::LineLoop.
@ -60,7 +73,9 @@ MAGNUM_PRIMITIVES_EXPORT Trade::MeshData2D circle2DWireframe(UnsignedInt segment
/** /**
@brief Solid 3D circle @brief Solid 3D circle
@param segments Number of segments. Must be greater or equal to @cpp 3 @ce. @param segments Number of segments. Must be greater or equal to
@cpp 3 @ce.
@param textureCoords Whether to generate texture coordinates
Circle on the XY plane with radius @cpp 1.0f @ce. Non-indexed Circle on the XY plane with radius @cpp 1.0f @ce. Non-indexed
@ref MeshPrimitive::TriangleFan with normals in positive Z direction. @ref MeshPrimitive::TriangleFan with normals in positive Z direction.
@ -69,7 +84,7 @@ Circle on the XY plane with radius @cpp 1.0f @ce. Non-indexed
@see @ref circle3DWireframe(), @ref circle2DSolid() @see @ref circle3DWireframe(), @ref circle2DSolid()
*/ */
MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D circle3DSolid(UnsignedInt segments); MAGNUM_PRIMITIVES_EXPORT Trade::MeshData3D circle3DSolid(UnsignedInt segments, CircleTextureCoords textureCoords = CircleTextureCoords::DontGenerate);
/** /**
@brief Wireframe 3D circle @brief Wireframe 3D circle

70
src/Magnum/Primitives/Test/CircleTest.cpp

@ -38,14 +38,22 @@ struct CircleTest: TestSuite::Tester {
explicit CircleTest(); explicit CircleTest();
void solid2D(); void solid2D();
void solid2DTextureCoords();
void solid3D(); void solid3D();
void solid3DTextureCoords();
void wireframe2D(); void wireframe2D();
void wireframe3D(); void wireframe3D();
}; };
CircleTest::CircleTest() { CircleTest::CircleTest() {
addTests({&CircleTest::solid2D, addTests({&CircleTest::solid2D,
&CircleTest::solid2DTextureCoords,
&CircleTest::solid3D, &CircleTest::solid3D,
&CircleTest::solid3DTextureCoords,
&CircleTest::wireframe2D, &CircleTest::wireframe2D,
&CircleTest::wireframe3D}); &CircleTest::wireframe3D});
} }
@ -63,6 +71,31 @@ void CircleTest::solid2D() {
{ 0.0f, -1.0f}, { Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f}, { 0.0f, -1.0f}, { Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f},
{ 1.0f, 0.0f} { 1.0f, 0.0f}
}), TestSuite::Compare::Container); }), TestSuite::Compare::Container);
CORRADE_COMPARE(circle.textureCoords2DArrayCount(), 0);
}
void CircleTest::solid2DTextureCoords() {
Trade::MeshData2D circle = Primitives::circle2DSolid(8, Primitives::CircleTextureCoords::Generate);
CORRADE_VERIFY(!circle.isIndexed());
CORRADE_COMPARE(circle.primitive(), MeshPrimitive::TriangleFan);
CORRADE_COMPARE_AS(circle.positions(0), (std::vector<Vector2>{
{ 0.0f, 0.0f},
{ 1.0f, 0.0f}, { Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f},
{ 0.0f, 1.0f}, {-Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f},
{-1.0f, 0.0f}, {-Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f},
{ 0.0f, -1.0f}, { Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f},
{ 1.0f, 0.0f}
}), TestSuite::Compare::Container);
CORRADE_COMPARE(circle.textureCoords2DArrayCount(), 1);
CORRADE_COMPARE_AS(circle.textureCoords2D(0), (std::vector<Vector2>{
{0.5f, 0.5f},
{1.0f, 0.5f}, {0.5f + Constants::sqrt2()/4.0f, 0.5f + Constants::sqrt2()/4.0f},
{0.5f, 1.0f}, {0.5f - Constants::sqrt2()/4.0f, 0.5f + Constants::sqrt2()/4.0f},
{0.0f, 0.5f}, {0.5f - Constants::sqrt2()/4.0f, 0.5f - Constants::sqrt2()/4.0f},
{0.5f, 0.0f}, {0.5f + Constants::sqrt2()/4.0f, 0.5f - Constants::sqrt2()/4.0f},
{1.0f, 0.5f}
}), TestSuite::Compare::Container);
} }
void CircleTest::solid3D() { void CircleTest::solid3D() {
@ -90,6 +123,43 @@ void CircleTest::solid3D() {
{ 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f},
{ 0.0f, 0.0f, 1.0f} { 0.0f, 0.0f, 1.0f}
}), TestSuite::Compare::Container); }), TestSuite::Compare::Container);
CORRADE_COMPARE(circle.textureCoords2DArrayCount(), 0);
}
void CircleTest::solid3DTextureCoords() {
Trade::MeshData3D circle = Primitives::circle3DSolid(8, Primitives::CircleTextureCoords::Generate);
CORRADE_VERIFY(!circle.isIndexed());
CORRADE_COMPARE(circle.primitive(), MeshPrimitive::TriangleFan);
CORRADE_COMPARE_AS(circle.positions(0), (std::vector<Vector3>{
{ 0.0f, 0.0f, 0.0f},
{ 1.0f, 0.0f, 0.0f}, { Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f, 0.0f},
{ 0.0f, 1.0f, 0.0f}, {-Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f, 0.0f},
{-1.0f, 0.0f, 0.0f}, {-Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f, 0.0f},
{ 0.0f, -1.0f, 0.0f}, { Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f, 0.0f},
{ 1.0f, 0.0f, 0.0f}
}), TestSuite::Compare::Container);
CORRADE_COMPARE_AS(circle.normals(0), (std::vector<Vector3>{
{ 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, 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, 1.0f}
}), TestSuite::Compare::Container);
CORRADE_COMPARE(circle.textureCoords2DArrayCount(), 1);
CORRADE_COMPARE_AS(circle.textureCoords2D(0), (std::vector<Vector2>{
{0.5f, 0.5f},
{1.0f, 0.5f}, {0.5f + Constants::sqrt2()/4.0f, 0.5f + Constants::sqrt2()/4.0f},
{0.5f, 1.0f}, {0.5f - Constants::sqrt2()/4.0f, 0.5f + Constants::sqrt2()/4.0f},
{0.0f, 0.5f}, {0.5f - Constants::sqrt2()/4.0f, 0.5f - Constants::sqrt2()/4.0f},
{0.5f, 0.0f}, {0.5f + Constants::sqrt2()/4.0f, 0.5f - Constants::sqrt2()/4.0f},
{1.0f, 0.5f}
}), TestSuite::Compare::Container);
} }
void CircleTest::wireframe2D() { void CircleTest::wireframe2D() {

Loading…
Cancel
Save