Browse Source

Primitives: Ability to specify number of cylinder rings on Capsule.

vectorfields
Vladimír Vondruš 14 years ago
parent
commit
e17835e3b6
  1. 42
      src/Primitives/Capsule.cpp
  2. 9
      src/Primitives/Capsule.h
  3. 28
      src/Primitives/Test/CapsuleTest.cpp
  4. 2
      src/Primitives/UVSphere.cpp

42
src/Primitives/Capsule.cpp

@ -19,28 +19,31 @@ using namespace std;
namespace Magnum { namespace Primitives {
Capsule::Capsule(unsigned int rings, unsigned int segments, GLfloat length, TextureCoords textureCoords): MeshData("", Mesh::Primitive::Triangles, new vector<unsigned int>, {new vector<Vector4>()}, {new vector<Vector3>()}, textureCoords == TextureCoords::Generate ? vector<vector<Vector2>*>{new vector<Vector2>()} : vector<vector<Vector2>*>()), segments(segments), textureCoords(textureCoords) {
CORRADE_ASSERT(rings >= 1 && segments >= 3, "Capsule must have at least one ring and three segments", );
Capsule::Capsule(unsigned int hemisphereRings, unsigned int cylinderRings, unsigned int segments, GLfloat length, TextureCoords textureCoords): MeshData("", Mesh::Primitive::Triangles, new vector<unsigned int>, {new vector<Vector4>()}, {new vector<Vector3>()}, textureCoords == TextureCoords::Generate ? vector<vector<Vector2>*>{new vector<Vector2>()} : vector<vector<Vector2>*>()), segments(segments), textureCoords(textureCoords) {
CORRADE_ASSERT(hemisphereRings >= 1 && cylinderRings >= 1 && segments >= 3, "Capsule must have at least one hemisphere ring, one cylinder ring and three segments", );
GLfloat height = 2.0f+length;
GLfloat textureCoordsVIncrement = 1.0f/(rings*height);
GLfloat ringAngleIncrement = Math::Constants<GLfloat>::pi()/(2*rings);
GLfloat hemisphereTextureCoordsVIncrement = 1.0f/(hemisphereRings*height);
GLfloat hemisphereRingAngleIncrement = Math::Constants<GLfloat>::pi()/(2*hemisphereRings);
/* Bottom cap vertex */
capVertex(-height/2, -1.0f, 0.0f);
/* Rings of bottom hemisphere */
vertexRings(rings, -length/2, -Math::Constants<GLfloat>::pi()/2+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement);
hemisphereVertexRings(hemisphereRings-1, -length/2, -Math::Constants<GLfloat>::pi()/2+hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement);
/* Rings of cylinder */
cylinderVertexRings(cylinderRings+1, -length/2, length/cylinderRings, 1.0f/height, length/(cylinderRings*height));
/* Rings of top hemisphere */
vertexRings(rings, length/2, 0.0f, ringAngleIncrement, (1.0f + length)/height, textureCoordsVIncrement);
hemisphereVertexRings(hemisphereRings-1, length/2, hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, (1.0f + length)/height+hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement);
/* Top cap vertex */
capVertex(height/2, 1.0f, 1.0f);
/* Faces */
bottomFaceRing();
faceRings(rings*2-1);
faceRings(hemisphereRings*2-2+cylinderRings);
topFaceRing();
}
@ -52,7 +55,7 @@ void Capsule::capVertex(GLfloat y, GLfloat normalY, GLfloat textureCoordsV) {
textureCoords2D(0)->push_back({0.5, textureCoordsV});
}
void Capsule::vertexRings(unsigned int count, GLfloat centerY, GLfloat startRingAngle, GLfloat ringAngleIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement) {
void Capsule::hemisphereVertexRings(unsigned int count, GLfloat centerY, GLfloat startRingAngle, GLfloat ringAngleIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement) {
GLfloat segmentAngleIncrement = 2*Math::Constants<GLfloat>::pi()/segments;
GLfloat x, y, z;
for(unsigned int i = 0; i != count; ++i) {
@ -78,6 +81,29 @@ void Capsule::vertexRings(unsigned int count, GLfloat centerY, GLfloat startRing
}
}
void Capsule::cylinderVertexRings(unsigned int count, GLfloat startY, GLfloat yIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement) {
GLfloat segmentAngleIncrement = 2*Math::Constants<GLfloat>::pi()/segments;
for(unsigned int i = 0; i != count; ++i) {
for(unsigned int j = 0; j != segments; ++j) {
GLfloat segmentAngle = j*segmentAngleIncrement;
positions(0)->push_back({sin(segmentAngle), startY, cos(segmentAngle)});
normals(0)->push_back({sin(segmentAngle), 0.0f, cos(segmentAngle)});
if(textureCoords == TextureCoords::Generate)
textureCoords2D(0)->push_back({j*1.0f/segments, startTextureCoordsV + i*textureCoordsVIncrement});
}
/* Duplicate first segment in the ring for additional vertex for texture coordinate */
if(textureCoords == TextureCoords::Generate) {
positions(0)->push_back((*positions(0))[positions(0)->size()-segments]);
normals(0)->push_back((*normals(0))[normals(0)->size()-segments]);
textureCoords2D(0)->push_back({1.0f, startTextureCoordsV + i*textureCoordsVIncrement});
}
startY += yIncrement;
}
}
void Capsule::bottomFaceRing() {
for(unsigned int j = 0; j != segments; ++j) {
/* Bottom vertex */

9
src/Primitives/Capsule.h

@ -40,8 +40,10 @@ class Capsule: public Trade::MeshData {
/**
* @brief Constructor
* @param rings Number of (face) rings for each hemisphere.
* @param hemisphereRings Number of (face) rings for each hemisphere.
* Must be larger or equal to 1.
* @param cylinderRings Number of (face) rings for cylinder. Must be
* larger or equal to 1.
* @param segments Number of (face) segments. Must be larger or equal to 3.
* @param length Length of the capsule, excluding hemispheres.
* @param textureCoords Whether to generate texture coordinates.
@ -49,13 +51,14 @@ class Capsule: public Trade::MeshData {
* If texture coordinates are generated, vertices of one segment are
* duplicated for texture wrapping.
*/
Capsule(unsigned int rings, unsigned int segments, GLfloat length, TextureCoords textureCoords = TextureCoords::DontGenerate);
Capsule(unsigned int hemisphereRings, unsigned int cylinderRings, unsigned int segments, GLfloat length, TextureCoords textureCoords = TextureCoords::DontGenerate);
private:
inline Capsule(unsigned int segments, TextureCoords textureCoords): MeshData("", Mesh::Primitive::Triangles, new std::vector<unsigned int>, {new std::vector<Vector4>()}, {new std::vector<Vector3>()}, textureCoords == TextureCoords::Generate ? std::vector<std::vector<Vector2>*>{new std::vector<Vector2>()} : std::vector<std::vector<Vector2>*>()), segments(segments), textureCoords(textureCoords) {}
void capVertex(GLfloat y, GLfloat normalY, GLfloat textureCoordsV);
void vertexRings(unsigned int count, GLfloat centerY, GLfloat startRingAngle, GLfloat ringAngleIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement);
void hemisphereVertexRings(unsigned int count, GLfloat centerY, GLfloat startRingAngle, GLfloat ringAngleIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement);
void cylinderVertexRings(unsigned int count, GLfloat startY, GLfloat yIncrement, GLfloat startTextureCoordsV, GLfloat textureCoordsVIncrement);
void bottomFaceRing();
void faceRings(unsigned int count);
void topFaceRing();

28
src/Primitives/Test/CapsuleTest.cpp

@ -35,7 +35,7 @@ CapsuleTest::CapsuleTest() {
}
void CapsuleTest::withoutTextureCoords() {
Capsule capsule(2, 3, 1.0f);
Capsule capsule(2, 2, 3, 1.0f);
CORRADE_COMPARE_AS(*capsule.positions(0), (vector<Vector4>{
Vector4(0.0f, -1.5f, 0.0f),
@ -48,6 +48,10 @@ void CapsuleTest::withoutTextureCoords() {
Vector4(0.866025f, -0.5f, -0.5f),
Vector4(-0.866025f, -0.5f, -0.5f),
Vector4(0.0f, 0.0f, 1.0f),
Vector4(0.866025f, 0.0f, -0.5f),
Vector4(-0.866025f, 0.0f, -0.5f),
Vector4(0.0f, 0.5f, 1.0f),
Vector4(0.866025f, 0.5f, -0.5f),
Vector4(-0.866025f, 0.5f, -0.5f),
@ -74,6 +78,10 @@ void CapsuleTest::withoutTextureCoords() {
Vector3(0.866025f, 0.0f, -0.5f),
Vector3(-0.866025f, 0.0f, -0.5f),
Vector3(0.0f, 0.0f, 1.0f),
Vector3(0.866025f, 0.0f, -0.5f),
Vector3(-0.866025f, 0.0f, -0.5f),
Vector3(0.0f, 0.707107f, 0.707107f),
Vector3(0.612372f, 0.707107f, -0.353553f),
Vector3(-0.612372f, 0.707107f, -0.353553f),
@ -86,12 +94,13 @@ void CapsuleTest::withoutTextureCoords() {
1, 2, 5, 1, 5, 4, 2, 3, 6, 2, 6, 5, 3, 1, 4, 3, 4, 6,
4, 5, 8, 4, 8, 7, 5, 6, 9, 5, 9, 8, 6, 4, 7, 6, 7, 9,
7, 8, 11, 7, 11, 10, 8, 9, 12, 8, 12, 11, 9, 7, 10, 9, 10, 12,
10, 11, 13, 11, 12, 13, 12, 10, 13
10, 11, 14, 10, 14, 13, 11, 12, 15, 11, 15, 14, 12, 10, 13, 12, 13, 15,
13, 14, 16, 14, 15, 16, 15, 13, 16
}), Container);
}
void CapsuleTest::withTextureCoords() {
Capsule capsule(2, 3, 1.0f, Capsule::TextureCoords::Generate);
Capsule capsule(2, 2, 3, 1.0f, Capsule::TextureCoords::Generate);
CORRADE_COMPARE_AS(*capsule.positions(0), (vector<Vector4>{
Vector4(0.0f, -1.5f, 0.0f),
@ -106,6 +115,11 @@ void CapsuleTest::withTextureCoords() {
Vector4(-0.866025f, -0.5f, -0.5f),
Vector4(0.0f, -0.5f, 1.0f),
Vector4(0.0f, 0.0f, 1.0f),
Vector4(0.866025f, 0.0f, -0.5f),
Vector4(-0.866025f, 0.0f, -0.5f),
Vector4(0.0f, 0.0f, 1.0f),
Vector4(0.0f, 0.5f, 1.0f),
Vector4(0.866025f, 0.5f, -0.5f),
Vector4(-0.866025f, 0.5f, -0.5f),
@ -132,6 +146,11 @@ void CapsuleTest::withTextureCoords() {
Vector2(0.666667f, 0.333333f),
Vector2(1.0f, 0.333333f),
Vector2(0.0f, 0.5f),
Vector2(0.333333f, 0.5f),
Vector2(0.666667f, 0.5f),
Vector2(1.0f, 0.5f),
Vector2(0.0f, 0.666667f),
Vector2(0.333333f, 0.666667f),
Vector2(0.666667f, 0.666667f),
@ -150,7 +169,8 @@ void CapsuleTest::withTextureCoords() {
1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 4, 8, 3, 8, 7,
5, 6, 10, 5, 10, 9, 6, 7, 11, 6, 11, 10, 7, 8, 12, 7, 12, 11,
9, 10, 14, 9, 14, 13, 10, 11, 15, 10, 15, 14, 11, 12, 16, 11, 16, 15,
13, 14, 17, 14, 15, 17, 15, 16, 17
13, 14, 18, 13, 18, 17, 14, 15, 19, 14, 19, 18, 15, 16, 20, 15, 20, 19,
17, 18, 21, 18, 19, 21, 19, 20, 21
}), Container);
}

2
src/Primitives/UVSphere.cpp

@ -29,7 +29,7 @@ UVSphere::UVSphere(unsigned int rings, unsigned int segments, TextureCoords text
capVertex(-1.0f, -1.0f, 0.0f);
/* Vertex rings */
vertexRings(rings-1, 0.0f, -Math::Constants<GLfloat>::pi()/2+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement);
hemisphereVertexRings(rings-1, 0.0f, -Math::Constants<GLfloat>::pi()/2+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement);
/* Top cap vertex */
capVertex(1.0f, 1.0f, 1.0f);

Loading…
Cancel
Save