Browse Source

Don't confuse vertices and vertex positions.

Mesh consists of vertices, each vertex has position, texture coordinate,
color, normal, etc.
pull/279/head
Vladimír Vondruš 14 years ago
parent
commit
30032a5971
  1. 6
      src/AbstractShaderProgram.h
  2. 6
      src/MeshTools/GenerateFlatNormals.cpp
  3. 8
      src/MeshTools/GenerateFlatNormals.h
  4. 4
      src/MeshTools/Interleave.h
  5. 6
      src/MeshTools/Test/CleanTest.cpp
  6. 42
      src/MeshTools/Test/SubdivideCleanBenchmark.cpp
  7. 16
      src/MeshTools/Test/SubdivideTest.cpp
  8. 6
      src/Primitives/Capsule.cpp
  9. 2
      src/Primitives/Cube.cpp
  10. 2
      src/Primitives/Icosphere.cpp
  11. 2
      src/Primitives/Icosphere.h
  12. 4
      src/Primitives/Test/CapsuleTest.cpp
  13. 4
      src/Primitives/Test/UVSphereTest.cpp
  14. 2
      src/Shaders/PhongShader.h
  15. 2
      src/Trade/MeshData.cpp
  16. 22
      src/Trade/MeshData.h

6
src/AbstractShaderProgram.h

@ -35,7 +35,7 @@ functions and properties:
- <strong>%Attribute location</strong> typedefs defining locations and types
for attribute binding with Mesh::bindAttribute(), for example:
@code
typedef Attribute<0, Vector4> Vertex;
typedef Attribute<0, Vector4> Position;
typedef Attribute<1, Vector3> Normal;
typedef Attribute<2, Vector2> TextureCoords;
@endcode
@ -82,7 +82,7 @@ shader code, e.g.:
@code
#version 330
// or #extension GL_ARB_explicit_attrib_location: enable
layout(location = 0) in vec4 vertex;
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 textureCoords;
@endcode
@ -110,7 +110,7 @@ attaching the shaders and linking the program:
@code
// Shaders attached...
bindAttributeLocation(Vertex::Location, "vertex");
bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(Normal::Location, "normal");
bindAttributeLocation(TextureCoords::Location, "textureCoords");

6
src/MeshTools/GenerateFlatNormals.cpp

@ -21,7 +21,7 @@ using namespace std;
namespace Magnum { namespace MeshTools {
tuple<vector<unsigned int>, vector<Vector3>> generateFlatNormals(const std::vector< unsigned int >& indices, const vector< Vector4 >& vertices) {
tuple<vector<unsigned int>, vector<Vector3>> generateFlatNormals(const vector<unsigned int>& indices, const vector<Vector4>& positions) {
CORRADE_ASSERT(!(indices.size()%3), "MeshTools::generateFlatNormals(): index count is not divisible by 3!", (tuple<vector<unsigned int>, vector<Vector3>>()));
/* Create normal for every triangle (assuming counterclockwise winding) */
@ -30,8 +30,8 @@ tuple<vector<unsigned int>, vector<Vector3>> generateFlatNormals(const std::vect
vector<Vector3> normals;
normals.reserve(indices.size()/3);
for(size_t i = 0; i != indices.size(); i += 3) {
Vector3 normal = Vector3::cross(vertices[indices[i+2]].xyz()-vertices[indices[i+1]].xyz(),
vertices[indices[i]].xyz()-vertices[indices[i+1]].xyz()).normalized();
Vector3 normal = Vector3::cross(positions[indices[i+2]].xyz()-positions[indices[i+1]].xyz(),
positions[indices[i]].xyz()-positions[indices[i+1]].xyz()).normalized();
/* Use the same normal for all three vertices of the face */
normalIndices.push_back(normals.size());

8
src/MeshTools/GenerateFlatNormals.h

@ -29,18 +29,18 @@ namespace Magnum { namespace MeshTools {
/**
@brief Generate flat normals
@param indices Array of triangle face indexes
@param vertices Vertex array
@param positions Array of vertex positions
@return Normal indices and vectors
For each face generates one normal vector, removes duplicates before
returning. Example usage:
@code
std::vector<unsigned int> vertexIndices;
std::vector<Vector4> vertices;
std::vector<Vector4> positions;
std::vector<unsigned int> normalIndices;
std::vector<Vector3> normals;
std::tie(normalIndices, normals) = MeshTools::generateFlatNormals(vertexIndices, vertices);
std::tie(normalIndices, normals) = MeshTools::generateFlatNormals(vertexIndices, positions);
@endcode
You can then use combineIndexedArrays() to combine normal and vertex array to
use the same indices.
@ -48,7 +48,7 @@ use the same indices.
@attention Index count must be divisible by 3, otherwise zero length result
is generated.
*/
std::tuple<std::vector<unsigned int>, std::vector<Vector3>> MESHTOOLS_EXPORT generateFlatNormals(const std::vector<unsigned int>& indices, const std::vector<Vector4>& vertices);
std::tuple<std::vector<unsigned int>, std::vector<Vector3>> MESHTOOLS_EXPORT generateFlatNormals(const std::vector<unsigned int>& indices, const std::vector<Vector4>& positions);
}}

4
src/MeshTools/Interleave.h

@ -108,12 +108,12 @@ so data for each attribute are in continuous place in memory. Size of the data
buffer can be computed from attribute count and stride, as shown below. Example
usage:
@code
std::vector<Vector4> vertices;
std::vector<Vector4> positions;
std::vector<Vector2> textureCoordinates;
size_t attributeCount;
size_t stride;
char* data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(vertices, textureCoordinates);
std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, textureCoordinates);
size_t dataSize = attributeCount*stride;
// ...
delete[] data;

6
src/MeshTools/Test/CleanTest.cpp

@ -28,12 +28,12 @@ CleanTest::CleanTest() {
}
void CleanTest::cleanMesh() {
vector<Vector1> vertices{1, 2, 1, 4};
vector<Vector1> positions{1, 2, 1, 4};
vector<unsigned int> indices{0, 1, 2, 1, 2, 3};
MeshTools::clean(indices, vertices);
MeshTools::clean(indices, positions);
/* Verify cleanup */
CORRADE_VERIFY(vertices == (vector<Vector1>{1, 2, 4}));
CORRADE_VERIFY(positions == (vector<Vector1>{1, 2, 4}));
CORRADE_COMPARE(indices, (vector<unsigned int>{0, 1, 0, 1, 0, 2}));
}

42
src/MeshTools/Test/SubdivideCleanBenchmark.cpp

@ -30,11 +30,11 @@ void SubdivideCleanBenchmark::subdivide() {
Primitives::Icosphere<0> icosphere;
/* Subdivide 5 times */
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
}
}
@ -43,13 +43,13 @@ void SubdivideCleanBenchmark::subdivideAndCleanMeshAfter() {
Primitives::Icosphere<0> icosphere;
/* Subdivide 5 times */
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.vertices(0));
MeshTools::clean(*icosphere.indices(), *icosphere.positions(0));
}
}
@ -58,16 +58,16 @@ void SubdivideCleanBenchmark::subdivideAndCleanMeshBetween() {
Primitives::Icosphere<0> icosphere;
/* Subdivide 5 times */
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.vertices(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.vertices(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.vertices(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.vertices(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.vertices(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.vertices(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.positions(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.positions(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.positions(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.positions(0));
MeshTools::subdivide(*icosphere.indices(), *icosphere.positions(0), interpolator);
MeshTools::clean(*icosphere.indices(), *icosphere.positions(0));
}
}

16
src/MeshTools/Test/SubdivideTest.cpp

@ -35,26 +35,26 @@ void SubdivideTest::wrongIndexCount() {
stringstream ss;
Error::setOutput(&ss);
vector<Vector1> vertices;
vector<Vector1> positions;
vector<unsigned int> indices{0, 1};
MeshTools::subdivide(indices, vertices, interpolator);
MeshTools::subdivide(indices, positions, interpolator);
CORRADE_COMPARE(ss.str(), "MeshTools::subdivide(): index count is not divisible by 3!\n");
}
void SubdivideTest::subdivide() {
vector<Vector1> vertices{0, 2, 6, 8};
vector<Vector1> positions{0, 2, 6, 8};
vector<unsigned int> indices{0, 1, 2, 1, 2, 3};
MeshTools::subdivide(indices, vertices, interpolator);
MeshTools::subdivide(indices, positions, interpolator);
CORRADE_COMPARE(indices.size(), 24);
CORRADE_VERIFY(vertices == (vector<Vector1>{0, 2, 6, 8, 1, 4, 3, 4, 7, 5}));
CORRADE_VERIFY(positions == (vector<Vector1>{0, 2, 6, 8, 1, 4, 3, 4, 7, 5}));
CORRADE_COMPARE(indices, (vector<unsigned int>{4, 5, 6, 7, 8, 9, 0, 4, 6, 4, 1, 5, 6, 5, 2, 1, 7, 9, 7, 2, 8, 9, 8, 3}));
MeshTools::clean(indices, vertices);
MeshTools::clean(indices, positions);
/* Vertices 0, 1, 2, 3, 4, 5, 6, 7, 8 */
CORRADE_COMPARE(vertices.size(), 9);
/* Positions 0, 1, 2, 3, 4, 5, 6, 7, 8 */
CORRADE_COMPARE(positions.size(), 9);
}
}}}

6
src/Primitives/Capsule.cpp

@ -45,7 +45,7 @@ Capsule::Capsule(unsigned int rings, unsigned int segments, GLfloat length, Text
}
void Capsule::capVertex(GLfloat y, GLfloat normalY, GLfloat textureCoordsV) {
vertices(0)->push_back({0.0f, y, 0.0f});
positions(0)->push_back({0.0f, y, 0.0f});
normals(0)->push_back({0.0f, normalY, 0.0f});
if(textureCoords == TextureCoords::Generate)
@ -62,7 +62,7 @@ void Capsule::vertexRings(unsigned int count, GLfloat centerY, GLfloat startRing
for(unsigned int j = 0; j != segments; ++j) {
GLfloat segmentAngle = j*segmentAngleIncrement;
vertices(0)->push_back({x*sin(segmentAngle), centerY+y, z*cos(segmentAngle)});
positions(0)->push_back({x*sin(segmentAngle), centerY+y, z*cos(segmentAngle)});
normals(0)->push_back({x*sin(segmentAngle), y, z*cos(segmentAngle)});
if(textureCoords == TextureCoords::Generate)
@ -71,7 +71,7 @@ void Capsule::vertexRings(unsigned int count, GLfloat centerY, GLfloat startRing
/* Duplicate first segment in the ring for additional vertex for texture coordinate */
if(textureCoords == TextureCoords::Generate) {
vertices(0)->push_back((*vertices(0))[vertices(0)->size()-segments]);
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});
}

2
src/Primitives/Cube.cpp

@ -42,7 +42,7 @@ Cube::Cube(): MeshData("", Mesh::Primitive::Triangles, new vector<unsigned int>{
{-1.0f, 1.0f, 1.0f},
{ 1.0f, 1.0f, 1.0f}
}}, {}) {
vertices(0)->assign(normals(0)->begin(), normals(0)->end());
positions(0)->assign(normals(0)->begin(), normals(0)->end());
}
}}

2
src/Primitives/Icosphere.cpp

@ -54,7 +54,7 @@ Icosphere<0>::Icosphere(): MeshData("", Mesh::Primitive::Triangles, new vector<u
Vector3(0, 0.525731f, -0.850651f),
Vector3(0, 0.525731f, 0.850651f)
}}, {}) {
vertices(0)->assign(normals(0)->begin(), normals(0)->end());
positions(0)->assign(normals(0)->begin(), normals(0)->end());
}
}}

2
src/Primitives/Icosphere.h

@ -57,7 +57,7 @@ template<size_t subdivisions> class Icosphere {
});
MeshTools::clean(*indices(), *normals(0));
vertices(0)->assign(normals(0)->begin(), normals(0)->end());
positions(0)->assign(normals(0)->begin(), normals(0)->end());
}
};

4
src/Primitives/Test/CapsuleTest.cpp

@ -34,7 +34,7 @@ CapsuleTest::CapsuleTest() {
void CapsuleTest::withoutTextureCoords() {
Capsule capsule(2, 3, 1.0f);
CORRADE_COMPARE(*capsule.vertices(0), (vector<Vector4>{
CORRADE_COMPARE(*capsule.positions(0), (vector<Vector4>{
Vector4(0.0f, -1.5f, 0.0f),
Vector4(0.0f, -1.20711f, 0.707107f),
@ -90,7 +90,7 @@ void CapsuleTest::withoutTextureCoords() {
void CapsuleTest::withTextureCoords() {
Capsule capsule(2, 3, 1.0f, Capsule::TextureCoords::Generate);
CORRADE_COMPARE(*capsule.vertices(0), (vector<Vector4>{
CORRADE_COMPARE(*capsule.positions(0), (vector<Vector4>{
Vector4(0.0f, -1.5f, 0.0f),
Vector4(0.0f, -1.20711f, 0.707107f),

4
src/Primitives/Test/UVSphereTest.cpp

@ -31,7 +31,7 @@ UVSphereTest::UVSphereTest() {
void UVSphereTest::withoutTextureCoords() {
UVSphere sphere(3, 3);
CORRADE_COMPARE(*sphere.vertices(0), (vector<Vector4>{
CORRADE_COMPARE(*sphere.positions(0), (vector<Vector4>{
Vector4(0.0f, -1.0f, 0.0f),
Vector4(0.0f, -0.5f, 0.866025f),
@ -69,7 +69,7 @@ void UVSphereTest::withoutTextureCoords() {
void UVSphereTest::withTextureCoords() {
UVSphere sphere(3, 3, UVSphere::TextureCoords::Generate);
CORRADE_COMPARE(*sphere.vertices(0), (vector<Vector4>{
CORRADE_COMPARE(*sphere.positions(0), (vector<Vector4>{
Vector4(0.0f, -1.0f, 0.0f),
Vector4(0.0f, -0.5f, 0.866025f),

2
src/Shaders/PhongShader.h

@ -32,7 +32,7 @@ namespace Magnum { namespace Shaders {
*/
class SHADERS_EXPORT PhongShader: public AbstractShaderProgram {
public:
typedef Attribute<0, Vector4> Vertex; /**< @brief Vertex position */
typedef Attribute<0, Vector4> Position; /**< @brief Vertex position */
typedef Attribute<1, Vector3> Normal; /**< @brief Normal direction */
/** @brief Constructor */

2
src/Trade/MeshData.cpp

@ -19,7 +19,7 @@ namespace Magnum { namespace Trade {
MeshData::~MeshData() {
delete _indices;
for(auto i: _vertices) delete i;
for(auto i: _positions) delete i;
for(auto i: _normals) delete i;
for(auto i: _textureCoords2D) delete i;
}

22
src/Trade/MeshData.h

@ -42,13 +42,13 @@ class MAGNUM_EXPORT MeshData {
* @param primitive Primitive
* @param indices Array with indices or 0, if this is not
* indexed mesh
* @param vertices Array with vertex arrays. At least one
* vertex array should be present.
* @param positions Array with vertex positions. At least one
* position array should be present.
* @param normals Array with normal arrays or empty array
* @param textureCoords2D Array with two-dimensional texture
* coordinate arrays or empty array
*/
inline MeshData(const std::string& name, Mesh::Primitive primitive, std::vector<unsigned int>* indices, std::vector<std::vector<Vector4>*> vertices, std::vector<std::vector<Vector3>*> normals, std::vector<std::vector<Vector2>*> textureCoords2D): _name(name), _primitive(primitive), _indices(indices), _vertices(vertices), _normals(normals), _textureCoords2D(textureCoords2D) {}
inline MeshData(const std::string& name, Mesh::Primitive primitive, std::vector<unsigned int>* indices, std::vector<std::vector<Vector4>*> positions, std::vector<std::vector<Vector3>*> normals, std::vector<std::vector<Vector2>*> textureCoords2D): _name(name), _primitive(primitive), _indices(indices), _positions(positions), _normals(normals), _textureCoords2D(textureCoords2D) {}
/** @brief Destructor */
~MeshData();
@ -66,17 +66,17 @@ class MAGNUM_EXPORT MeshData {
inline std::vector<unsigned int>* indices() { return _indices; }
inline const std::vector<unsigned int>* indices() const { return _indices; } /**< @overload */
/** @brief Count of vertex arrays */
inline unsigned int vertexArrayCount() const { return _vertices.size(); }
/** @brief Count of vertex position arrays */
inline unsigned int positionArrayCount() const { return _positions.size(); }
/**
* @brief Vertices
* @param id ID of vertex data array
* @return Vertices or nullptr if there is no vertex array with given
* @brief Positions
* @param id ID of position data array
* @return Positions or nullptr if there is no vertex array with given
* ID.
*/
inline std::vector<Vector4>* vertices(unsigned int id) { return _vertices[id]; }
inline const std::vector<Vector4>* vertices(unsigned int id) const { return _vertices[id]; } /**< @overload */
inline std::vector<Vector4>* positions(unsigned int id) { return _positions[id]; }
inline const std::vector<Vector4>* positions(unsigned int id) const { return _positions[id]; } /**< @overload */
/** @brief Count of normal arrays */
inline unsigned int normalArrayCount() const { return _normals.size(); }
@ -106,7 +106,7 @@ class MAGNUM_EXPORT MeshData {
std::string _name;
Mesh::Primitive _primitive;
std::vector<unsigned int>* _indices;
std::vector<std::vector<Vector4>*> _vertices;
std::vector<std::vector<Vector4>*> _positions;
std::vector<std::vector<Vector3>*> _normals;
std::vector<std::vector<Vector2>*> _textureCoords2D;
};

Loading…
Cancel
Save