Browse Source

Don't confuse vertices and vertex positions.

Mesh consists of vertices, each vertex has position, texture coordinate,
color, normal, etc.
vectorfields
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