Browse Source

Primitives: 2D capsule primitive.

Will be used for shape debug rendering.
pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
3c75ba7748
  1. 61
      src/Primitives/Capsule.cpp
  2. 22
      src/Primitives/Capsule.h
  3. 72
      src/Primitives/Test/CapsuleTest.cpp

61
src/Primitives/Capsule.cpp

@ -25,13 +25,70 @@
#include "Capsule.h"
#include "Math/Vector3.h"
#include "Math/Functions.h"
#include "Primitives/Implementation/Spheroid.h"
#include "Primitives/Implementation/WireframeSpheroid.h"
#include "Trade/MeshData2D.h"
#include "Trade/MeshData3D.h"
namespace Magnum { namespace Primitives {
Trade::MeshData3D Capsule::solid(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, UnsignedInt segments, Float halfLength, TextureCoords textureCoords) {
Trade::MeshData2D Capsule2D::wireframe(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, Float halfLength) {
CORRADE_ASSERT(hemisphereRings >= 1 && cylinderRings >= 1, "Capsule must have at least one hemisphere ring, one cylinder ring and three segments", Trade::MeshData2D(Mesh::Primitive::Lines, {}, {}, {}));
std::vector<Vector2> positions;
positions.reserve(hemisphereRings*4+2+(cylinderRings-1)*2);
const Rad angleIncrement(Constants::pi()/(2.0f*hemisphereRings));
const Float cylinderIncrement = 2.0f*halfLength/cylinderRings;
/* Bottom cap vertex */
positions.emplace_back(0.0f, -halfLength-1.0f);
/* Bottom hemisphere */
for(UnsignedInt i = 0; i != hemisphereRings; ++i) {
const Rad angle((i+1)*angleIncrement);
const Float x = Math::sin(angle);
const Float y = -Math::cos(angle)-halfLength;
positions.insert(positions.end(), {{-x, y}, {x, y}});
}
/* Cylinder (bottom and top vertices are done within caps */
for(UnsignedInt i = 0; i != cylinderRings-1; ++i) {
const Float y = (i+1)*cylinderIncrement-halfLength;
positions.insert(positions.end(), {{-1.0f, y}, {1.0f, y}});
}
/* Top hemisphere */
for(UnsignedInt i = 0; i != hemisphereRings; ++i) {
const Rad angle(i*angleIncrement);
const Float x = Math::cos(angle);
const Float y = Math::sin(angle)+halfLength;
positions.insert(positions.end(), {{-x, y}, {x, y}});
}
/* Top cap vertex */
positions.emplace_back(0.0f, halfLength+1.0f);
std::vector<UnsignedInt> indices;
indices.reserve(hemisphereRings*8+cylinderRings*4);
/* Bottom cap indices */
indices.insert(indices.end(), {0, 1, 0, 2});
/* Side indices */
for(UnsignedInt i = 0; i != cylinderRings+hemisphereRings*2-2; ++i)
indices.insert(indices.end(), {i*2+1, i*2+3,
i*2+2, i*2+4});
/* Top cap indices */
indices.insert(indices.end(),
{UnsignedInt(positions.size())-3, UnsignedInt(positions.size())-1,
UnsignedInt(positions.size())-2, UnsignedInt(positions.size())-1});
return Trade::MeshData2D(Mesh::Primitive::Lines, std::move(indices), {std::move(positions)}, {});
}
Trade::MeshData3D Capsule3D::solid(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, UnsignedInt segments, Float halfLength, TextureCoords textureCoords) {
CORRADE_ASSERT(hemisphereRings >= 1 && cylinderRings >= 1 && segments >= 3, "Capsule must have at least one hemisphere ring, one cylinder ring and three segments", Trade::MeshData3D(Mesh::Primitive::Triangles, {}, {}, {}, {}));
Implementation::Spheroid capsule(segments, textureCoords == TextureCoords::Generate ?
@ -65,7 +122,7 @@ Trade::MeshData3D Capsule::solid(UnsignedInt hemisphereRings, UnsignedInt cylind
return capsule.finalize();
}
Trade::MeshData3D Capsule::wireframe(const UnsignedInt hemisphereRings, const UnsignedInt cylinderRings, const UnsignedInt segments, const Float halfLength) {
Trade::MeshData3D Capsule3D::wireframe(const UnsignedInt hemisphereRings, const UnsignedInt cylinderRings, const UnsignedInt segments, const Float halfLength) {
CORRADE_ASSERT(hemisphereRings >= 1 && cylinderRings >= 1 && segments >= 4 && segments%4 == 0, "Primitives::Capsule::wireframe(): improper parameters", Trade::MeshData3D(Mesh::Primitive::Lines, {}, {}, {}, {}));
Implementation::WireframeSpheroid capsule(segments/4);

22
src/Primitives/Capsule.h

@ -33,12 +33,32 @@
namespace Magnum { namespace Primitives {
/**
@brief 2D capsule primitive
%Cylinder of radius `1` along Y axis with hemispheres instead of caps.
*/
class MAGNUM_PRIMITIVES_EXPORT Capsule2D {
public:
/**
* @brief Wireframe capsule
* @param hemisphereRings Number of (line) rings for each hemisphere.
* Must be larger or equal to 1.
* @param cylinderRings Number of (line) rings for cylinder. Must be
* larger or equal to 1.
* @param halfLength Half the length of cylinder part
*
* Indexed @ref Mesh::Primitive "Lines".
*/
static Trade::MeshData2D wireframe(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, Float halfLength);
};
/**
@brief 3D capsule primitive
%Cylinder of radius `1` along Y axis with hemispheres instead of caps.
*/
class MAGNUM_PRIMITIVES_EXPORT Capsule {
class MAGNUM_PRIMITIVES_EXPORT Capsule3D {
public:
/** @brief Whether to generate texture coordinates */
enum class TextureCoords: UnsignedByte {

72
src/Primitives/Test/CapsuleTest.cpp

@ -29,6 +29,7 @@
#include <TestSuite/Compare/Container.h>
#include "Math/Vector3.h"
#include "Trade/MeshData2D.h"
#include "Trade/MeshData3D.h"
#include "Primitives/Capsule.h"
@ -38,19 +39,66 @@ class CapsuleTest: public TestSuite::Tester {
public:
CapsuleTest();
void solidWithoutTextureCoords();
void solidWithTextureCoords();
void wireframe();
void wireframe2D();
void solid3DWithoutTextureCoords();
void solid3DWithTextureCoords();
void wireframe3D();
};
CapsuleTest::CapsuleTest() {
addTests({&CapsuleTest::solidWithoutTextureCoords,
&CapsuleTest::solidWithTextureCoords,
&CapsuleTest::wireframe});
addTests({&CapsuleTest::wireframe2D,
&CapsuleTest::solid3DWithoutTextureCoords,
&CapsuleTest::solid3DWithTextureCoords,
&CapsuleTest::wireframe3D});
}
void CapsuleTest::wireframe2D() {
Trade::MeshData2D capsule = Capsule2D::wireframe(2, 4, 0.5f);
CORRADE_COMPARE_AS(capsule.positions(0), (std::vector<Vector2>{
{0.0f, -1.5f},
{-0.707107f, -1.20711f},
{0.707107f, -1.20711f},
{-1.0f, -0.5f},
{1.0f, -0.5f},
{-1.0f, -0.25f},
{1.0f, -0.25f},
{-1.0f, 0.0f},
{1.0f, 0.0f},
{-1.0f, 0.25f},
{1.0f, 0.25f},
{-1.0f, 0.5f},
{1.0f, 0.5f},
{-0.707107f, 1.20711f},
{0.707107f, 1.20711f},
{0.0f, 1.5f}
}), TestSuite::Compare::Container);
CORRADE_COMPARE_AS(capsule.indices(), (std::vector<UnsignedInt>{
0, 1, 0, 2,
1, 3, 2, 4,
3, 5, 4, 6,
5, 7, 6, 8,
7, 9, 8, 10,
9, 11, 10, 12,
11, 13, 12, 14,
13, 15, 14, 15
}), TestSuite::Compare::Container);
}
void CapsuleTest::solidWithoutTextureCoords() {
Trade::MeshData3D capsule = Capsule::solid(2, 4, 3, 1.0f);
void CapsuleTest::solid3DWithoutTextureCoords() {
Trade::MeshData3D capsule = Capsule3D::solid(2, 4, 3, 0.5f);
CORRADE_COMPARE_AS(capsule.positions(0), (std::vector<Vector3>{
{0.0f, -1.5f, 0.0f},
@ -132,8 +180,8 @@ void CapsuleTest::solidWithoutTextureCoords() {
}), TestSuite::Compare::Container);
}
void CapsuleTest::solidWithTextureCoords() {
Trade::MeshData3D capsule = Capsule::solid(2, 2, 3, 1.0f, Capsule::TextureCoords::Generate);
void CapsuleTest::solid3DWithTextureCoords() {
Trade::MeshData3D capsule = Capsule3D::solid(2, 2, 3, 0.5f, Capsule3D::TextureCoords::Generate);
CORRADE_COMPARE_AS(capsule.positions(0), (std::vector<Vector3>{
{0.0f, -1.5f, 0.0f},
@ -207,8 +255,8 @@ void CapsuleTest::solidWithTextureCoords() {
}), TestSuite::Compare::Container);
}
void CapsuleTest::wireframe() {
Trade::MeshData3D capsule = Capsule::wireframe(2, 2, 8, 1.0f);
void CapsuleTest::wireframe3D() {
Trade::MeshData3D capsule = Capsule3D::wireframe(2, 2, 8, 0.5f);
CORRADE_COMPARE_AS(capsule.positions(0), (std::vector<Vector3>{
{0.0f, -1.5f, 0.0f},

Loading…
Cancel
Save