Browse Source

Mesh rework, part 1: better vertex attribute management.

* Instead of "binding attributes" the user now "adds vertex buffer". It
   corresponds better with what OpenGL itself does.
 * Vertex buffers now must be managed by the user.
 * Shader attributes are now static const members instead of typedefs to
   allow more convenient add*VertexBuffer*() calls.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
21acb3edc6
  1. 33
      src/AbstractShaderProgram.h
  2. 117
      src/Mesh.cpp
  3. 261
      src/Mesh.h
  4. 8
      src/MeshTools/Interleave.h
  5. 3
      src/Physics/DebugDrawResourceManager.cpp
  6. 5
      src/Physics/DebugDrawResourceManager.h
  7. 22
      src/Physics/Implementation/BoxRenderer.cpp
  8. 7
      src/Physics/Implementation/BoxRenderer.h
  9. 7
      src/Shaders/PhongShader.cpp
  10. 4
      src/Shaders/PhongShader.h

33
src/AbstractShaderProgram.h

@ -44,12 +44,12 @@ class Shader;
This class is designed to be used via subclassing. Subclasses define these
functions and properties:
- <strong>%Attribute location</strong> typedefs defining locations and types
for attribute binding with Mesh::bindAttribute(), for example:
- <strong>%Attribute definitions</strong> with location and type for
configuring meshes, for example:
@code
typedef Attribute<0, Point3D> Position;
typedef Attribute<1, Vector3> Normal;
typedef Attribute<2, Vector2> TextureCoords;
static const Attribute<0, Point3D> Position;
static const Attribute<1, Vector3> Normal;
static const Attribute<2, Vector2> TextureCoordinates;
@endcode
@todoc Output attribute location (for bindFragmentDataLocationIndexed(),
referenced also from Framebuffer::mapDefaultForDraw() / Framebuffer::mapForDraw())
@ -103,7 +103,7 @@ shader code, e.g.:
// or #extension GL_ARB_explicit_attrib_location: enable
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 textureCoords;
layout(location = 2) in vec2 textureCoordinates;
@endcode
Similarly for ouput attributes, you can also specify blend equation color
index for them (see Framebuffer::BlendFunction for more information about
@ -131,9 +131,9 @@ attaching the shaders and linking the program:
@code
// Shaders attached...
bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(Normal::Location, "normal");
bindAttributeLocation(TextureCoords::Location, "textureCoords");
bindAttributeLocation(Position.Location, "position");
bindAttributeLocation(Normal.Location, "normal");
bindAttributeLocation(TextureCoords.Location, "textureCoordinates");
bindFragmentDataLocationIndexed(0, 0, "color");
bindFragmentDataLocationIndexed(1, 1, "ambient");
@ -185,10 +185,11 @@ setUniform(SpecularTextureUniform, SpecularTextureLayer);
@section AbstractShaderProgram-rendering-workflow Rendering workflow
Basic workflow with %AbstractShaderProgram subclasses is: instancing the class
(once at the beginning), then in draw event setting uniforms and marking the
shader for use, binding required textures to their respective layers using
AbstractTexture::bind(GLint) and calling Mesh::draw(). For example:
Basic workflow with %AbstractShaderProgram subclasses is to instance the class
and configuring attribute binding in meshes (see @ref Mesh-configuration "Mesh documentation"
for more information) at the beginning, then in draw event setting uniforms
and marking the shader for use, binding required textures to their respective
layers using AbstractTexture::bind(GLint) and calling Mesh::draw(). Example:
@code
shader->setTransformation(transformation)
->setProjection(projection)
@ -205,9 +206,9 @@ The engine tracks currently used shader program to avoid unnecessary calls to
@fn_gl{UseProgram}.
If extension @extension{ARB,separate_shader_objects} or
@extension{EXT,direct_state_access} is available, uniform setting
functions use DSA functions to avoid unnecessary calls to @fn_gl{UseProgram}.
See setUniform(GLint, GLfloat) documentation for more information.
@extension{EXT,direct_state_access} is available, uniform setting functions
use DSA functions to avoid unnecessary calls to @fn_gl{UseProgram}. See
setUniform(GLint, GLfloat) documentation for more information.
To achieve least state changes, set all uniforms in one run -- method chaining
comes in handy.

117
src/Mesh.cpp

@ -27,7 +27,7 @@ Mesh::Mesh(Mesh&& other):
#ifndef MAGNUM_TARGET_GLES
vao(other.vao),
#endif
_primitive(other._primitive), _vertexCount(other._vertexCount), finalized(other.finalized), _buffers(other._buffers), _attributes(other._attributes)
_primitive(other._primitive), _vertexCount(other._vertexCount), finalized(other.finalized), attributes(other.attributes)
{
#ifndef MAGNUM_TARGET_GLES
other.vao = 0;
@ -35,9 +35,6 @@ Mesh::Mesh(Mesh&& other):
}
void Mesh::destroy() {
for(auto& it: _buffers)
delete it.first;
#ifndef MAGNUM_TARGET_GLES
glDeleteVertexArrays(1, &vao);
#endif
@ -52,8 +49,7 @@ Mesh& Mesh::operator=(Mesh&& other) {
_primitive = other._primitive;
_vertexCount = other._vertexCount;
finalized = other.finalized;
_buffers = other._buffers;
_attributes = other._attributes;
attributes = other.attributes;
#ifndef MAGNUM_TARGET_GLES
other.vao = 0;
@ -62,13 +58,6 @@ Mesh& Mesh::operator=(Mesh&& other) {
return *this;
}
Buffer* Mesh::addBuffer(BufferType interleaved) {
Buffer* buffer = new Buffer(Buffer::Target::Array);
_buffers.insert(make_pair(buffer, make_pair(interleaved, vector<Attribute>())));
return buffer;
}
void Mesh::draw() {
/* Vertex array must be bound before finalization */
#ifndef MAGNUM_TARGET_GLES
@ -102,8 +91,8 @@ void Mesh::unbind() {
#ifndef MAGNUM_TARGET_GLES
glBindVertexArray(0);
#else
for(set<GLuint>::const_iterator it = _attributes.begin(); it != _attributes.end(); ++it)
glDisableVertexAttribArray(*it);
for(const Attribute& attribute: attributes)
glDisableVertexAttribArray(attribute.location);
#endif
}
@ -111,45 +100,8 @@ void Mesh::finalize() {
/* Already finalized */
if(finalized) return;
CORRADE_ASSERT(_vertexCount, "Mesh: the mesh has zero vertex count!", );
/* Finalize attribute positions for every buffer */
for(auto& it: _buffers) {
/* Avoid confustion */
bool interleaved = it.second.first == BufferType::Interleaved;
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*TypeInfo::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*TypeInfo::sizeOf(ait->type)*_vertexCount;
}
}
}
CORRADE_ASSERT((_vertexCount == 0) == attributes.empty(), "Mesh: vertex count is non-zero, but no attributes are bound", );
/* Mesh is now finalized, attribute binding is not allowed */
finalized = true;
#ifndef MAGNUM_TARGET_GLES
@ -158,46 +110,33 @@ void Mesh::finalize() {
}
void Mesh::bindBuffers() {
/* Enable vertex arrays for all attributes */
for(set<GLuint>::const_iterator it = _attributes.begin(); it != _attributes.end(); ++it)
glEnableVertexAttribArray(*it);
for(auto& it: _buffers) {
/* Avoid confusion */
vector<Attribute>& attributes = it.second.second;
/* Bind buffer */
it.first->bind();
/* Bind all attributes to this buffer */
for(vector<Attribute>::const_iterator ait = attributes.begin(); ait != attributes.end(); ++ait)
#ifndef MAGNUM_TARGET_GLES
if(TypeInfo::isIntegral(ait->type))
glVertexAttribIPointer(ait->attribute, ait->size, static_cast<GLenum>(ait->type), ait->stride, ait->pointer);
else
#endif
glVertexAttribPointer(ait->attribute, ait->size, static_cast<GLenum>(ait->type), GL_FALSE, ait->stride, ait->pointer);
/* Bind all attributes to this buffer */
for(const Attribute& attribute: attributes) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
#ifndef MAGNUM_TARGET_GLES
if(TypeInfo::isIntegral(attribute.type))
glVertexAttribIPointer(attribute.location, attribute.count, static_cast<GLenum>(attribute.type), attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
else
#endif
glVertexAttribPointer(attribute.location, attribute.count, static_cast<GLenum>(attribute.type), GL_FALSE, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
}
}
#endif
void Mesh::bindAttribute(Buffer* buffer, GLuint attribute, GLint size, Type 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 */
auto found = _buffers.find(buffer);
if(found == _buffers.end()) return;
Attribute a;
a.attribute = attribute;
a.size = size;
a.type = type;
a.stride = 0;
a.pointer = nullptr;
found->second.second.push_back(a);
_attributes.insert(attribute);
void Mesh::addVertexAttribute(Buffer* buffer, GLuint location, GLint count, Type type, GLintptr offset, GLsizei stride) {
CORRADE_ASSERT(_vertexCount != 0, "Mesh: vertex count must be set before binding attributes", );
attributes.push_back({
buffer,
location,
count,
type,
offset,
stride
});
}
}

261
src/Mesh.h

@ -19,11 +19,9 @@
* @brief Class Magnum::Mesh
*/
#include <map>
#include <vector>
#include <set>
#include "Magnum.h"
#include "AbstractShaderProgram.h"
#include "TypeTraits.h"
namespace Magnum {
@ -33,6 +31,52 @@ class Buffer;
/**
@brief Base class for managing non-indexed meshes
@section Mesh-configuration Mesh configuration
To properly configure mesh, you have to set primitive and vertex count, either
in constructor or using setPrimitive() and setVertexCount(). Then create
vertex buffers, fill them with vertex data and assign them to mesh and given
shader locations using addVertexBuffer() or addInterleavedVertexBuffer(). You
can also use MeshTools::interleave() to conveniently set vertex count and
buffer data.
Note that the buffer is not managed (e.g. deleted on destruction) by the mesh,
so you have to manage it on your own. On the other hand it allows you to use
one buffer for more meshes (each mesh for example configured for different
shader) or store more than only vertex data in one buffer.
Example usage -- filling buffer with position data, configuring the mesh and
assigning the buffer to mesh to use with custom shader:
@code
Buffer* buffer;
Mesh* mesh;
static constexpr Point3D positions[30] = {
// ...
};
buffer->setData(positions, Buffer::Usage::StaticDraw);
mesh->setPrimitve(Mesh::Primitive::Triangles)
->setVertexCount(30)
->addVertexBuffer(buffer, MyShader::Position);
@endcode
Example usage -- creating a plane mesh and assigning buffer with interleaved
vertex attributes for use with phong shader:
@code
Buffer* buffer;
Mesh* mesh;
Primitives::Plane plane;
MeshTools::interleave(mesh, buffer, Buffer::Usage::StaticDraw, *plane.positions(0), *plane.normals(0));
mesh->setPrimitive(plane.primitive())
->addInterleavedVertexBuffer(buffer, 0, Shaders::PhongShader::Position, Shaders::PhongShader::Normal);
@endcode
@section Mesh-drawing Rendering meshes
Basic workflow is to set up respective shader (see @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" for more infromation) and call Mesh::draw().
VAOs are used for desktop OpenGL (not in OpenGL ES).
@requires_gl30 Extension @extension{APPLE,vertex_array_object}
@requires_gl30 Extension @extension{EXT,gpu_shader4} (for unsigned integer attributes)
@ -282,20 +326,6 @@ class MAGNUM_EXPORT Mesh {
TriangleFan = GL_TRIANGLE_FAN
};
/**
* @brief %Buffer type
*
* 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.
* @see addBuffer()
*/
enum class BufferType: bool {
Interleaved, /**< Interleaved buffer */
NonInterleaved /**< Non-interleaved buffer */
};
/**
* @brief Implicit constructor
* @param primitive Primitive type
@ -330,7 +360,6 @@ class MAGNUM_EXPORT Mesh {
/**
* @brief Destructor
*
* Deletes all associated buffers.
* @see @fn_gl{DeleteVertexArrays}
*/
inline virtual ~Mesh() { destroy(); }
@ -364,52 +393,127 @@ class MAGNUM_EXPORT Mesh {
* @brief Set vertex count
* @return Pointer to self (for method chaining)
*
* This forces recalculation of attribute positions upon next drawing.
* @attention All bound attributes are reset after calling this
* function, so you must call
* addVertexBuffer()/addInterleavedVertexBuffer() afterwards.
* @see MeshTools::interleave()
*/
inline Mesh* setVertexCount(GLsizei vertexCount) {
_vertexCount = vertexCount;
finalized = false;
attributes.clear();
return this;
}
/**
* @brief Add buffer
* @param interleaved Whether the buffer is interleaved
* @brief Add buffer with non-interleaved vertex attributes for use with given shader
*
* Attribute list is combination of attribute definitions (specified
* in implementation of given shader) and offsets between attribute
* arrays.
*
* Adds new buffer to the mesh. The buffer can be then filled with
* Buffer::setData(). See also isInterleaved().
* See @ref Mesh-configuration "class documentation" for simple usage
* example. For more involved example imagine that you have buffer
* with 35 bytes of some other data at the beginning (possibly material
* configuration), then position array, then texture coordinate array
* and then normal array. You want to draw it with Shaders::PhongShader,
* but it accepts only position and normal, so you have to skip the
* texture coordinate array:
* @code
* Mesh* mesh;
* Buffer* buffer;
* mesh->addVertexBuffer(buffer,
* 35, // skip other data
* Shaders::PhongShader::Position, // position array
* sizeof(Vector2)*mesh->vertexCount(), // skip texture coordinate array
* Shaders::PhongShader::Normal); // normal array
* @endcode
*
* @todo Move interleaveability to Buffer itself?
* Vou can also achieve the same effect by calling this function more
* times with absolute offsets:
* @code
* mesh->addVertexBuffer(buffer, 35, Shaders::PhongShader::Position);
* ->addVertexBuffer(buffer, 35 + (sizeof(Shaders::PhongShader::Position::Type) + sizeof(Vector2))*
* mesh->vertexCount(), Shaders::PhongShader::Normal);
* @endcode
*
* @attention Non-zero vertex count must be set before calling this
* function.
* @attention The buffer passed as parameter is not managed by the
* mesh, you must ensure it will exist for whole lifetime of the
* mesh and delete it afterwards.
*
* @see addInterleavedVertexBuffer()
*/
Buffer* addBuffer(BufferType interleaved);
template<class ...T> inline Mesh* addVertexBuffer(Buffer* buffer, const T&... attributes) {
addVertexBufferInternal(buffer, 0, attributes...);
return this;
}
/**
* @brief Whether given buffer is interleaved
* @return True if the buffer belongs to the mesh and the buffer is
* interleaved, false otherwise.
* @brief Add buffer with interleaved vertex attributes for use with given shader
*
* Parameter @p offset is offset of the interleaved array from the
* beginning, attribute list is combination of attribute definitions
* (specified in implementation of given shader) and offsets between
* attributes.
*
* See @ref Mesh-configuration "class documentation" for simple usage
* example. For more involved example imagine that you have buffer
* with 35 bytes of some other data at the beginning (possibly material
* configuration) and then the interleaved vertex array. Each vertex
* consists of weight, position, texture coordinate and normal. You
* want to draw it with Shaders::PhongShader, but it accepts only
* position and normal, so you have to skip weight and texture
* coordinate in each vertex:
* @code
* Mesh* mesh;
* Buffer* buffer;
* mesh->addInterleavedVertexBuffer(buffer,
* 35, // skip other data
* sizeof(GLfloat), // skip vertex weight
* Shaders::PhongShader::Position, // vertex position
* sizeof(Vector2), // skip texture coordinates
* Shaders::PhongShader::Normal); // vertex normal
* @endcode
*
* You can also achieve the same effect by calling addVertexBufferStride()
* more times with absolute offset from the beginning and stride
* between vertex attributes:
* @code
* GLsizei stride = // size of one vertex
* sizeof(GLfloat) +
* sizeof(Shaders::PhongShader::Position::Type) +
* sizeof(Vector2) +
* sizeof(Shaders::PhongShader::Normal::Type);
*
* mesh->addVertexBufferStride(buffer, 35 + sizeof(GLfloat),
* stride, Shaders::PhongShader::Position);
* ->addVertexBufferStride(buffer, 35 + sizeof(GLfloat) +
* sizeof(Shaders::PhongShader::Position::Type) + sizeof(Vector2),
* stride, Shaders::PhongShader::Normal);
* @endcode
*
* @attention Non-zero vertex count must be set before calling this
* function.
* @attention The buffer passed as parameter is not managed by the
* mesh, you must ensure it will exist for whole lifetime of the
* mesh and delete it afterwards.
*
* See also addBuffer().
* @see addVertexBufferStride(), addVertexBuffer()
*/
inline bool isInterleaved(Buffer* buffer) const {
auto found = _buffers.find(buffer);
return found != _buffers.end() && found->second.first == BufferType::Interleaved;
template<class ...T> inline Mesh* addInterleavedVertexBuffer(Buffer* buffer, GLintptr offset, const T&... attributes) {
addInterleavedVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), attributes...);
return this;
}
/**
* @brief Bind attribute
* @tparam attribute Attribute, defined in the shader
* @param buffer Buffer where bind the attribute to (pointer
* returned by addBuffer())
* @return Pointer to self (for method chaining)
* @brief Add buffer with interleaved vertex attributes for use with given shader
*
* 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.
* See addInterleavedVertexBuffer() for more information.
*/
template<class Attribute> inline Mesh* bindAttribute(Buffer* buffer) {
bindAttribute(buffer, Attribute::Location, TypeTraits<typename Attribute::Type>::count(), TypeTraits<typename Attribute::Type>::type());
template<GLuint location, class T> inline Mesh* addVertexBufferStride(Buffer* buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>& attribute) {
addInterleavedVertexBufferInternal(buffer, offset, stride, attribute);
return this;
}
@ -453,15 +557,54 @@ class MAGNUM_EXPORT Mesh {
MAGNUM_LOCAL void finalize();
private:
/** @brief Vertex attribute */
struct MAGNUM_LOCAL Attribute {
GLuint attribute; /**< @brief %Attribute ID */
GLint size; /**< @brief How many items of `type` are in the attribute */
Type type; /**< @brief %Attribute item type */
GLsizei stride; /**< @brief Distance of two adjacent attributes of this type in interleaved buffer */
const GLvoid* pointer; /**< @brief Pointer to first attribute of this type in the buffer */
Buffer* buffer;
GLuint location;
GLint count;
Type type;
GLintptr offset;
GLsizei stride;
};
/* Adding non-interleaved vertex attributes */
template<GLuint location, class T, class ...U> inline void addVertexBufferInternal(Buffer* buffer, GLintptr offset, const AbstractShaderProgram::Attribute<location, T>&, const U&... attributes) {
addVertexAttribute(buffer, location, TypeTraits<T>::count(), TypeTraits<T>::type(), offset, 0);
/* Add size of this attribute array to offset for next attribute */
addVertexBufferInternal(buffer, offset+TypeTraits<T>::count()*TypeTraits<T>::size()*_vertexCount, attributes...);
}
template<class ...T> inline void addVertexBufferInternal(Buffer* buffer, GLintptr offset, GLintptr gap, const T&... attributes) {
/* Add the gap to offset for next attribute */
addVertexBufferInternal(buffer, offset+gap, attributes...);
}
inline void addVertexBufferInternal(Buffer*, GLintptr) {}
/* Computing stride of interleaved vertex attributes */
template<GLuint location, class T, class ...U> inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute<location, T>&, const U&... attributes) {
return TypeTraits<T>::count()*TypeTraits<T>::size() + strideOfInterleaved(attributes...);
}
template<class ...T> inline static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) {
return gap + strideOfInterleaved(attributes...);
}
inline static GLsizei strideOfInterleaved() { return 0; }
/* Adding interleaved vertex attributes */
template<GLuint location, class T, class ...U> inline void addInterleavedVertexBufferInternal(Buffer* buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>&, const U&... attributes) {
addVertexAttribute(buffer, location, TypeTraits<T>::count(), TypeTraits<T>::type(), offset, stride);
/* Add size of this attribute to offset for next attribute */
addInterleavedVertexBufferInternal(buffer, offset+TypeTraits<T>::count()*TypeTraits<T>::size(), stride, attributes...);
}
template<class ...T> inline void addInterleavedVertexBufferInternal(Buffer* buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) {
/* Add the gap to offset for next attribute */
addInterleavedVertexBufferInternal(buffer, offset+gap, stride, attributes...);
}
inline void addInterleavedVertexBufferInternal(Buffer*, GLsizei, GLintptr) {}
void MAGNUM_EXPORT addVertexAttribute(Buffer* buffer, GLuint location, GLint count, Type type, GLintptr offset, GLsizei stride);
void destroy();
#ifndef MAGNUM_TARGET_GLES
GLuint vao;
#endif
@ -469,25 +612,7 @@ class MAGNUM_EXPORT Mesh {
GLsizei _vertexCount;
bool finalized;
/**
* @brief Buffers with their attributes
*
* Map of associated buffers, evey buffer has:
* - boolean value which signalizes whether the buffer is interleaved
* - list of bound attributes
*/
std::map<Buffer*, std::pair<BufferType, std::vector<Attribute> > > _buffers;
/**
* @brief List of all bound attributes
*
* List of all bound attributes bound with bindAttribute().
*/
std::set<GLuint> _attributes;
MAGNUM_EXPORT void bindAttribute(Buffer* buffer, GLuint attribute, GLint size, Type type);
void destroy();
std::vector<Attribute> attributes;
};
}

8
src/MeshTools/Interleave.h

@ -53,8 +53,6 @@ class Interleave {
}
template<class ...T> void operator()(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const T&... attributes) {
CORRADE_ASSERT(mesh->isInterleaved(buffer), "MeshTools::interleave(): the buffer is not interleaved, nothing done", );
operator()(attributes...);
mesh->setVertexCount(_attributeCount);
@ -153,7 +151,7 @@ output to given array buffer and updates vertex count in the mesh accordingly,
so you don't have to call Mesh::setVertexCount() on your own.
@attention Setting primitive type and binding the attributes to shader is left
to user - see Mesh::setPrimitive() and Mesh::bindAttribute().
to user - see @ref Mesh-configuration "Mesh documentation".
For only one attribute array this function is convenient equivalent to the
following, without any performance loss:
@ -162,10 +160,6 @@ buffer->setData(attribute, usage);
mesh->setVertexCount(attribute.size());
@endcode
@attention If there is more than one attribute array, the buffer must be set
as interleaved (see Mesh::addBuffer()), otherwise this function does
nothing.
@see MeshTools::compressIndices()
*/
template<class ...T> inline void interleave(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const T&... attributes) {

3
src/Physics/DebugDrawResourceManager.cpp

@ -16,6 +16,7 @@
#include "DebugDrawResourceManager.h"
#include "AbstractShaderProgram.h"
#include "Buffer.h"
#include "Mesh.h"
#include "AbstractShape.h"
#include "Box.h"
@ -27,7 +28,7 @@
namespace Magnum {
template class ResourceManager<AbstractShaderProgram, Mesh, Physics::Implementation::Options>;
template class ResourceManager<AbstractShaderProgram, Buffer, Mesh, Physics::Implementation::Options>;
namespace Physics {

5
src/Physics/DebugDrawResourceManager.h

@ -28,6 +28,7 @@
namespace Magnum {
class AbstractShaderProgram;
class Buffer;
class Mesh;
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -38,7 +39,7 @@ namespace Physics { namespace Implementation {
template<std::uint8_t> class AbstractDebugRenderer;
}}
extern template class PHYSICS_EXPORT ResourceManager<AbstractShaderProgram, Mesh, Physics::Implementation::Options>;
extern template class PHYSICS_EXPORT ResourceManager<AbstractShaderProgram, Buffer, Mesh, Physics::Implementation::Options>;
#endif
namespace SceneGraph {
@ -83,7 +84,7 @@ DebugDrawResourceManager::createDebugRenderer(object->shape(), "red")
->setParent(object);
@endcode
*/
class PHYSICS_EXPORT DebugDrawResourceManager: public ResourceManager<AbstractShaderProgram, Mesh, Physics::Implementation::Options> {
class PHYSICS_EXPORT DebugDrawResourceManager: public ResourceManager<AbstractShaderProgram, Buffer, Mesh, Physics::Implementation::Options> {
public:
#ifdef DOXYGEN_GENERATING_OUTPUT
/** @brief %Options */

22
src/Physics/Implementation/BoxRenderer.cpp

@ -31,14 +31,13 @@ namespace {
constexpr static char shader[] = "shader2d";
constexpr static char key[] = "box2d";
static Mesh* mesh() {
static Mesh* mesh(Buffer* buffer) {
Primitives::Square square;
Mesh* mesh = new Mesh;
Buffer* buffer = mesh->addBuffer(Mesh::BufferType::NonInterleaved);
buffer->setData(*square.positions(0), Buffer::Usage::StaticDraw);
return mesh->setPrimitive(square.primitive())
->bindAttribute<typename Implementation::ShapeShader<2>::Position>(buffer)
->setVertexCount(square.positions(0)->size());
->setVertexCount(square.positions(0)->size())
->addVertexBuffer(buffer, Implementation::ShapeShader<2>::Position());
}
};
@ -46,14 +45,13 @@ namespace {
constexpr static char shader[] = "shader3d";
constexpr static char key[] = "box3d";
static Mesh* mesh() {
static Mesh* mesh(Buffer* buffer) {
Primitives::Cube cube;
Mesh* mesh = new Mesh;
Buffer* buffer = mesh->addBuffer(Mesh::BufferType::NonInterleaved);
buffer->setData(*cube.positions(0), Buffer::Usage::StaticDraw);
return mesh->setPrimitive(cube.primitive())
->bindAttribute<typename Implementation::ShapeShader<2>::Position>(buffer)
->setVertexCount(cube.positions(0)->size());
->setVertexCount(cube.positions(0)->size())
->addVertexBuffer(buffer, Implementation::ShapeShader<2>::Position());
}
};
}
@ -63,9 +61,11 @@ constexpr char BoxMesh<2>::key[];
constexpr char BoxMesh<3>::shader[];
constexpr char BoxMesh<3>::key[];
template<std::uint8_t dimensions> BoxRenderer<dimensions>::BoxRenderer(Box<dimensions>& box, ResourceKey options, typename SceneGraph::AbstractObject<dimensions>::ObjectType* parent): AbstractDebugRenderer<dimensions>(BoxMesh<dimensions>::shader, BoxMesh<dimensions>::key, options, parent), box(box) {
if(!this->mesh)
DebugDrawResourceManager::instance()->set<Mesh>(this->mesh.key(), BoxMesh<dimensions>::mesh(), ResourceDataState::Final, ResourcePolicy::Manual);
template<std::uint8_t dimensions> BoxRenderer<dimensions>::BoxRenderer(Box<dimensions>& box, ResourceKey options, typename SceneGraph::AbstractObject<dimensions>::ObjectType* parent): AbstractDebugRenderer<dimensions>(BoxMesh<dimensions>::shader, BoxMesh<dimensions>::key, options, parent), buffer(DebugDrawResourceManager::instance()->get<Buffer>(BoxMesh<dimensions>::key)), box(box) {
if(!this->mesh) {
DebugDrawResourceManager::instance()->set(this->buffer.key(), new Buffer, ResourceDataState::Final, ResourcePolicy::Manual);
DebugDrawResourceManager::instance()->set<Mesh>(this->mesh.key(), BoxMesh<dimensions>::mesh(buffer), ResourceDataState::Final, ResourcePolicy::Manual);
}
}
template<std::uint8_t dimensions> void BoxRenderer<dimensions>::draw(const typename DimensionTraits<dimensions, GLfloat>::MatrixType&, typename SceneGraph::AbstractObject<dimensions>::CameraType* camera) {

7
src/Physics/Implementation/BoxRenderer.h

@ -17,7 +17,11 @@
#include "AbstractDebugRenderer.h"
namespace Magnum { namespace Physics {
namespace Magnum {
class Buffer;
namespace Physics {
template<std::uint8_t> class Box;
@ -30,6 +34,7 @@ template<std::uint8_t dimensions> class BoxRenderer: public AbstractDebugRendere
void draw(const typename DimensionTraits<dimensions, GLfloat>::MatrixType& transformation, typename SceneGraph::AbstractObject<dimensions>::CameraType* camera);
private:
Resource<Buffer> buffer;
Box<dimensions>& box;
};

7
src/Shaders/PhongShader.cpp

@ -22,6 +22,9 @@
namespace Magnum { namespace Shaders {
const PhongShader::Attribute<0, Point3D> PhongShader::Position;
const PhongShader::Attribute<1, Vector3> PhongShader::Normal;
PhongShader::PhongShader() {
Corrade::Utility::Resource rs("MagnumShaders");
Version v = Context::current()->isVersionSupported(Version::GL320) ? Version::GL320 : Version::GL210;
@ -29,8 +32,8 @@ PhongShader::PhongShader() {
attachShader(Shader::fromData(v, Shader::Type::Fragment, rs.get("PhongShader.frag")));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>()) {
bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(Normal::Location, "normal");
bindAttributeLocation(Position.Location, "position");
bindAttributeLocation(Normal.Location, "normal");
}
link();

4
src/Shaders/PhongShader.h

@ -35,8 +35,8 @@ otherwise falls back to GLSL 1.20.
*/
class SHADERS_EXPORT PhongShader: public AbstractShaderProgram {
public:
typedef Attribute<0, Point3D> Position; /**< @brief Vertex position */
typedef Attribute<1, Vector3> Normal; /**< @brief Normal direction */
static const Attribute<0, Point3D> Position; /**< @brief Vertex position */
static const Attribute<1, Vector3> Normal; /**< @brief Normal direction */
PhongShader();

Loading…
Cancel
Save