Saxum/extern/acgl/include/ACGL/OpenGL/Objects/ArrayBuffer.hh

195 lines
9.4 KiB
C++
Raw Normal View History

2014-10-20 15:31:26 +00:00
/***********************************************************************
* Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#ifndef ACGL_OPENGL_OBJECTS_ARRAYBUFFER_HH
#define ACGL_OPENGL_OBJECTS_ARRAYBUFFER_HH
/**
* An ArrayBuffer holds an array of per-vertex data. In its simplest form an
* array of one attribute, for example the vertex position or texture-coordinate.
* An ArrayBuffer however can also hold multiple attributes in an interleaved
* way.
*
* An ArrayBuffer can be drawn directly or indexed in combination with an
* ElementArrayBuffer.
*
* The combination of (multiple) attributes of (multiple) ArrayBuffers
* and one (optional) ElementArrayBuffer is a VertexBufferObject or VertexArrayObject.
*
* Note: In some documents ArrayBuffers (and sometimes ElementArrayBuffers) are
* called VertexBufferObjects, VBOs. The original extension that introduced
* these two new buffer types was called ARB_vertex_buffer_object but the buffers
* itself are called ArrayBuffer and ElementArrayBuffer.
*
***************************************************************************************************************
* Attributes:
*************
*
* _type is the GL type
* _size the number of elements in this attribute (1..4)
* _normalized is the attribute normalization for int types
*
* Want to add tightly packed attributes in order?
* -> use defineAttribute()
*
* Want to add attributes with individual padding in order?
* -> use defineAttributeWithPadding()
*
* Want to add attributes out-of-order?
* -> use defineAttributeWithOffset()
*
* The stride size gets always set to the minimal stride size that covers all defined attributes (/w padding).
* All define methods can get mixed!
*
*
* ab->defineAttribute( "pos", GL_FLOAT, 3 ); // stride: 12 bytes
* ab->defineAttributeWithPadding( "color", GL_CHAR, 3, 1 ); // stride: 12 + 3 + 1 = 16 bytes
* ab->defineAttributeWithOffset( "colorNorm", GL_CHAR, 3, 12, GL_TRUE ); // stride is still 16 as 12+3 <= 16!
*
**************************************************************************************************************/
#include <ACGL/ACGL.hh>
#include <ACGL/Base/Macros.hh>
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Tools.hh>
#include <algorithm>
#include <string>
#include <vector>
#include <ACGL/OpenGL/Objects/Buffer.hh>
namespace ACGL{
namespace OpenGL{
class GeometryData;
ACGL_SMARTPOINTER_TYPEDEFS(GeometryData)
class ArrayBuffer : public Buffer
{
// ==================================================================================================== \/
// ============================================================================================ STRUCTS \/
// ==================================================================================================== \/
public:
//! Each attribute has a size (#components, e.g. normal with x/y/z => 3) and an offset in the stride (in bytes)
struct Attribute
{
std::string name; // human readable name, can be used to match the attribute to shader programs
GLenum type; // GL_FLOAT, GL_UNSIGNED_BYTE etc.
GLint size; // #elements per attribute, size in bytes would be: size*sizeof(type)
GLuint offset; // offset in bytes into the array
GLboolean normalized; // int types can get normalzed to 0..1 / -1..1 by GL, useful e.g. for colors
GLuint divisor; // vertex divisor for instancing, supported since OpenGL 3.3. Default is 0 (== off)
GLboolean isIntegerInShader; // should the data get read as vec or ivec ?
};
// ===================================================================================================== \/
// ============================================================================================ TYPEDEFS \/
// ===================================================================================================== \/
public:
typedef std::vector< Attribute > AttributeVec;
// ========================================================================================================= \/
// ============================================================================================ CONSTRUCTORS \/
// ========================================================================================================= \/
public:
//! creates an ArrayBuffer with a new OpenGL Buffer object
ArrayBuffer()
: Buffer(GL_ARRAY_BUFFER),
mStride(0),
mAttributes()
{}
//! creates an ArrayBuffer with a pre-existing OpenGL Buffer
ArrayBuffer( SharedBufferObject _pBuffer )
: Buffer(_pBuffer, GL_ARRAY_BUFFER),
mStride(0),
mAttributes()
{}
// ==================================================================================================== \/
// ============================================================================================ GETTERS \/
// ==================================================================================================== \/
public:
//! elements is the number of vertices or instances (if the divisor is != 0):
inline GLsizei getElements (void) const { return (GLsizei) (mStride==0?0:(mSize/mStride)); }
//! size in bytes of all attributes that make up one element (vertex):
inline GLsizei getStride (void) const { return mStride; }
//! Returns the definitions of the attributes:
inline const AttributeVec& getAttributes (void) const { return mAttributes; }
//! Returns one attribute:
inline Attribute getAttribute( uint_t i ) const { return mAttributes[i]; }
// ==================================================================================================== \/
// ============================================================================================ METHODS \/
// ==================================================================================================== \/
public:
//! Adds the attribute at the end of the existing attributes, stride gets computed automatically
void defineAttribute( const std::string& _name, GLenum _type, GLint _size, GLboolean _normalized = GL_FALSE, GLuint _divisor = 0);
void defineIntegerAttribute( const std::string& _name, GLenum _type, GLint _size, GLboolean _normalized = GL_FALSE, GLuint _divisor = 0);
//! Adds the attribute at the end of the existing attributes, stride gets computed automatically
//! + extra padding in bytes at the end
void defineAttributeWithPadding( const std::string& _name, GLenum _type, GLint _size, GLuint _padding, GLboolean _normalized = GL_FALSE, GLuint _divisor = 0);
void defineIntegerAttributeWithPadding( const std::string& _name, GLenum _type, GLint _size, GLuint _padding, GLboolean _normalized = GL_FALSE, GLuint _divisor = 0);
//! Adds an attribute defined by an offset: this way an attribute can get added at arbitrary
//! locations in the stride. If it's added at the end, the stride gets resized. This way attributes can even
//! overlap, hope you know what you're doing...
void defineAttributeWithOffset( const std::string& _name, GLenum _type, GLint _size, GLuint _offset, GLboolean _normalized = GL_FALSE, GLuint _divisor = 0);
void defineIntegerAttributeWithOffset( const std::string& _name, GLenum _type, GLint _size, GLuint _offset, GLboolean _normalized = GL_FALSE, GLuint _divisor = 0);
//! Takes care of a valid stride size and adds the attribute
void defineAttribute( const Attribute &_attribute );
//! Returns the index of a named attribute
int32_t getAttributeIndexByName(const std::string& _nameInArray) const;
//! Setting of the stride size explicitly is not needed if the attributes are defined correctly (with padding)
inline void setStride( GLsizei _stride ) { mStride = _stride; }
//! Sets all data (attributes, stride, size) to those specified in _geometryData. All previous data are overwritten.
void setGeometryData( SharedGeometryData _geometryData );
//! removes all attributes
inline void removeAttributes(void)
{
mStride = 0;
mAttributes.clear();
}
//! Set data for this buffer for a given number of elements (_elements*mStride == size in bytes)
//! Use only after all attributes have been defined
inline void setDataElements( uint_t _elements, const GLvoid *_pData = NULL, GLenum _usage = GL_STATIC_DRAW ) {
setData( mTarget, _elements * mStride, _pData, _usage );
}
//! Overloaded from the base class to _prevent_ redefining of the binding target! (see Buffer)
inline void setTarget( GLenum ) {
ACGL::Utils::error() << "DON'T redefine the target binding point of an ArrayBuffer" << std::endl;
}
// =================================================================================================== \/
// ============================================================================================ FIELDS \/
// =================================================================================================== \/
protected:
GLsizei mStride;
AttributeVec mAttributes;
};
ACGL_SMARTPOINTER_TYPEDEFS(ArrayBuffer)
} // OpenGL
} // ACGL
#endif // ACGL_OPENGL_OBJECTS_ARRAYBUFFER_HH