Browse Source

Class for managing non-indexed meshes.

vectorfields
Vladimír Vondruš 16 years ago
parent
commit
9317d089e9
  1. 1
      src/CMakeLists.txt
  2. 156
      src/Mesh.cpp
  3. 200
      src/Mesh.h

1
src/CMakeLists.txt

@ -9,6 +9,7 @@ set(Magnum_SRCS
AbstractObject.cpp
AbstractShaderProgram.cpp
Camera.cpp
Mesh.cpp
Scene.cpp
Shader.cpp
)

156
src/Mesh.cpp

@ -0,0 +1,156 @@
/*
Copyright © 2010 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include "Mesh.h"
#include "Buffer.h"
#include <iostream>
using namespace std;
namespace Magnum {
Mesh::~Mesh() {
for(map<Buffer*, pair<bool, vector<Attribute> > >::iterator it = buffers.begin(); it != buffers.end(); ++it)
delete it->first;
}
Buffer* Mesh::addBuffer(bool interleaved) {
Buffer* buffer = new Buffer(Buffer::ArrayBuffer);
buffers.insert(pair<Buffer*, pair<bool, vector<Attribute> > >(
buffer,
pair<bool, vector<Attribute> >(interleaved, vector<Attribute>())
));
return buffer;
}
void Mesh::draw() {
/* Finalize the mesh, if it is not already */
finalize();
/* Enable vertex arrays for all attributes */
for(set<GLuint>::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
glEnableVertexAttribArray(*it);
/* Bind attributes to vertex buffers */
for(map<Buffer*, pair<bool, vector<Attribute> > >::iterator it = buffers.begin(); it != buffers.end(); ++it) {
/* Bind buffer */
it->first->bind();
/* Bind all attributes to this buffer */
for(vector<Attribute>::const_iterator ait = it->second.second.begin(); ait != it->second.second.end(); ++ait)
switch(ait->type) {
case GL_BYTE:
case GL_UNSIGNED_BYTE:
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_INT:
case GL_UNSIGNED_INT:
glVertexAttribIPointer(ait->location, ait->size, ait->type, ait->stride, ait->pointer);
break;
default:
glVertexAttribPointer(ait->location, ait->size, ait->type, GL_FALSE, ait->stride, ait->pointer);
}
/* Unbind buffer */
it->first->unbind();
}
glDrawArrays(primitive, 0, count);
/* Disable vertex arrays for all attributes */
for(set<GLuint>::const_iterator it = attributes.begin(); it != attributes.end(); ++it)
glDisableVertexAttribArray(*it);
}
void Mesh::finalize() {
/* Already finalized */
if(finalized) return;
/* Finalize attribute positions for every buffer */
for(map<Buffer*, pair<bool, vector<Attribute> > >::iterator it = buffers.begin(); it != buffers.end(); ++it) {
/* Avoid confustion */
bool interleaved = it->second.first;
vector<Attribute>& attributes = it->second.second;
/* Interleaved buffer, set stride and position of first attribute */
if(interleaved) {
/* Set attribute position and compute stride */
GLsizei stride = 0;
for(vector<Attribute>::iterator ait = attributes.begin(); ait != attributes.end(); ++ait) {
/* The attribute is positioned at the end of previous */
ait->pointer = reinterpret_cast<const GLvoid*>(stride);
/* Add attribute size (per vertex) to stride */
stride += ait->size*sizeOf(ait->type);
}
/* Set computed stride for all attributes */
for(vector<Attribute>::iterator ait = attributes.begin(); ait != attributes.end(); ++ait)
ait->stride = stride;
/* Non-interleaved buffer, set position of every attribute */
} else {
/* Set attribute position */
GLsizei position = 0;
for(vector<Attribute>::iterator ait = attributes.begin(); ait != attributes.end(); ++ait) {
/* The attribute is positioned at the end of previous attribute array */
ait->pointer = reinterpret_cast<const GLvoid*>(position);
/* Add attribute size (for all vertices) to position */
position += ait->size*sizeOf(ait->type)*count;
}
}
}
/* Mesh is now finalized, attribute binding is not allowed */
finalized = true;
}
void Mesh::bindAttribute(Buffer* buffer, GLuint attribute, GLint size, GLenum type) {
/* The mesh is finalized or attribute is already bound, nothing to do */
if(finalized || attributes.find(attribute) != attributes.end()) return;
/* If buffer is not managed by this mesh, nothing to do */
map<Buffer*, pair<bool, vector<Attribute> > >::iterator found = buffers.find(buffer);
if(found == buffers.end()) return;
Attribute a;
a.location = attribute;
a.size = size;
a.type = type;
a.stride = 0;
a.pointer = 0;
found->second.second.push_back(a);
attributes.insert(attribute);
}
GLsizei Mesh::sizeOf(GLenum type) {
switch(type) {
case GL_BYTE: return sizeof(GLbyte);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
case GL_SHORT: return sizeof(GLshort);
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
case GL_INT: return sizeof(GLint);
case GL_UNSIGNED_INT: return sizeof(GLuint);
case GL_FLOAT: return sizeof(GLfloat);
case GL_DOUBLE: return sizeof(GLdouble);
default: return 0;
}
}
}

200
src/Mesh.h

@ -0,0 +1,200 @@
#ifndef Magnum_Mesh_h
#define Magnum_Mesh_h
/*
Copyright © 2010 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Mesh
*/
#include <map>
#include <vector>
#include <set>
#include "Magnum.h"
namespace Magnum {
class Buffer;
/**
* @brief Base class for managing non-indexed meshes
*
* @todo Support for normalized values (e.g. for color as char[4] passed to
* shader as floating-point vec4)
*/
class Mesh {
public:
/** @brief Primitive type */
enum Primitive {
/**
* Single points
*/
Points = GL_POINTS,
/**
* Each pair of vertices defines a single line, lines aren't
* connected together.
*/
Lines = GL_LINES,
/**
* Polyline
*/
LineStrip = GL_LINE_STRIP,
/**
* Polyline, last vertex is connected to first.
*/
LineLoop = GL_LINE_LOOP,
/**
* Each three vertices define one triangle.
*/
Triangles = GL_TRIANGLES,
/**
* First three vertices define first triangle, each following
* vertex defines another triangle.
*/
TriangleStrip = GL_TRIANGLE_STRIP,
/**
* First vertex is center, each following vertex is connected to
* previous and center vertex.
*/
TriangleFan = GL_TRIANGLE_FAN
};
/**
* @brief Constructor
* @param _primitive Primitive type
* @param _count Vertex count
*/
inline Mesh(Primitive _primitive, GLsizei _count): primitive(_primitive), count(_count), finalized(false) {}
/**
* @brief Destructor
*
* Deletes all associated buffers.
*/
~Mesh();
/**
* @brief Add buffer
* @param interleaved If storing more than one attribute data in the
* buffer, the data of one attribute can be either kept together
* or interleaved with data for another attributes, so data for
* every vertex will be in one continuous place.
*
* Adds new buffer to the mesh. The buffer can be then filled with
* Buffer::setData().
*/
Buffer* addBuffer(bool interleaved);
/**
* @brief Bind attribute
* @param buffer Buffer where bind the attribute to (pointer
* returned by addBuffer())
* @param attribute Attribute
*
* Binds attribute of given type with given buffer. If the attribute is
* already bound, given buffer isn't managed with this mesh (wasn't
* initialized with addBuffer) or the mesh was already drawn, the
* function does nothing.
*/
template<class T> void bindAttribute(Buffer* buffer, GLuint attribute);
/**
* @brief Draw a mesh
*
* Binds attributes to buffers and draws the mesh. Expects an active
* shader with all uniforms set.
*/
void draw();
protected:
/**
* @brief Finalize the mesh
*
* Computes location and stride of each attribute in its buffer. After
* this function is called, no new attribute can be bound.
*/
void finalize();
private:
struct Attribute {
GLuint location;
GLint size;
GLenum type;
GLsizei stride;
const GLvoid* pointer;
};
std::map<Buffer*, std::pair<bool, std::vector<Attribute> > > buffers;
std::set<GLuint> attributes;
GLenum primitive;
GLsizei count;
bool finalized;
void bindAttribute(Buffer* buffer, GLuint attribute, GLint size, GLenum type);
GLsizei sizeOf(GLenum type);
};
template<> inline void Mesh::bindAttribute<GLbyte>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_BYTE);
}
template<> inline void Mesh::bindAttribute<GLubyte>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_UNSIGNED_BYTE);
}
template<> inline void Mesh::bindAttribute<GLshort>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_SHORT);
}
template<> inline void Mesh::bindAttribute<GLushort>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_UNSIGNED_SHORT);
}
template<> inline void Mesh::bindAttribute<GLint>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_INT);
}
template<> inline void Mesh::bindAttribute<GLuint>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_UNSIGNED_INT);
}
template<> inline void Mesh::bindAttribute<GLfloat>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_FLOAT);
}
template<> inline void Mesh::bindAttribute<GLdouble>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 1, GL_DOUBLE);
}
template<> inline void Mesh::bindAttribute<Vector3>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 3, GL_FLOAT);
}
template<> inline void Mesh::bindAttribute<Vector4>(Buffer* buffer, GLuint attribute) {
bindAttribute(buffer, attribute, 4, GL_FLOAT);
}
}
#endif
Loading…
Cancel
Save