mirror of https://github.com/mosra/magnum.git
15 changed files with 407 additions and 12 deletions
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
@ -0,0 +1,73 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
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(); |
||||||
|
} |
||||||
|
|
||||||
|
}} |
||||||
@ -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š <mosra@centrum.cz> |
||||||
|
|
||||||
|
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 <Corrade/Containers/EnumSet.h> |
||||||
|
|
||||||
|
#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<ConeFlag> 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 |
||||||
@ -0,0 +1,200 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 |
||||||
|
Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
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 <Corrade/TestSuite/Tester.h> |
||||||
|
#include <Corrade/TestSuite/Compare/Container.h> |
||||||
|
|
||||||
|
#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<Vector3>{ |
||||||
|
{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<Vector3>{ |
||||||
|
{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<UnsignedInt>{ |
||||||
|
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<Vector3>{ |
||||||
|
{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<Vector3>{ |
||||||
|
{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<Vector2>{ |
||||||
|
{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<UnsignedInt>{ |
||||||
|
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<Vector3>{ |
||||||
|
{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<UnsignedInt>{ |
||||||
|
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) |
||||||
Loading…
Reference in new issue