ArrayBuffer.hh 9.02 KB
Newer Older
Robert Menzel's avatar
Robert Menzel committed
1
2
3
4
5
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Computer Graphics Group RWTH Aachen University         //
// All rights reserved.                                                       //
////////////////////////////////////////////////////////////////////////////////

6
7
#ifndef ACGL_OPENGL_OBJECTS_ARRAYBUFFER_HH
#define ACGL_OPENGL_OBJECTS_ARRAYBUFFER_HH
Robert Menzel's avatar
Robert Menzel committed
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * 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.
 */

Robert Menzel's avatar
Robert Menzel committed
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/***************************************************************************************************************
 * 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!
 *
 **************************************************************************************************************/

Robert Menzel's avatar
Robert Menzel committed
54
55
#include <ACGL/ACGL.hh>

56
#include <ACGL/Base/Macros.hh>
Robert Menzel's avatar
Robert Menzel committed
57
58
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Tools.hh>
Robert Menzel's avatar
Robert Menzel committed
59
60
61
62

#include <string>
#include <vector>

63
64
#include <ACGL/OpenGL/Objects/Buffer.hh>

Robert Menzel's avatar
Robert Menzel committed
65
namespace ACGL{
Robert Menzel's avatar
Robert Menzel committed
66
namespace OpenGL{
Robert Menzel's avatar
Robert Menzel committed
67

68
class ArrayBuffer : public Buffer
69
70
71
72
73
74
75
76
77
78
{
    // ==================================================================================================== \/
    // ============================================================================================ 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.
Robert Menzel's avatar
Robert Menzel committed
79
        GLint       size;       // #elements per attribute, size in bytes would be: size*sizeof(type)
80
        GLuint      offset;     // offset in bytes into the array
Robert Menzel's avatar
Robert Menzel committed
81
        GLboolean   normalized; // int types can get normalzed to 0..1 / -1..1 by GL, useful e.g. for colors
82
83
84
85
86
87
88
89
90
91
92
93
    };

    // ===================================================================================================== \/
    // ============================================================================================ TYPEDEFS \/
    // ===================================================================================================== \/
public:
    typedef std::vector< Attribute > AttributeVec;

    // ========================================================================================================= \/
    // ============================================================================================ CONSTRUCTORS \/
    // ========================================================================================================= \/
public:
94
    ArrayBuffer()
95
96
97
98
99
        : Buffer(GL_ARRAY_BUFFER),
        mStride(0),
        mAttributes()
    {}

100
    ArrayBuffer( SharedBufferObject _pBuffer )
101
102
103
104
105
106
107
108
109
        : Buffer(_pBuffer, GL_ARRAY_BUFFER),
        mStride(0),
        mAttributes()
    {}

    // ==================================================================================================== \/
    // ============================================================================================ GETTERS \/
    // ==================================================================================================== \/
public:
Robert Menzel's avatar
Robert Menzel committed
110
111

    //! often the number of vertices:
112
    inline       GLsizei       getElements   (void) const { return mSize/mStride; }
Robert Menzel's avatar
Robert Menzel committed
113
114

    //! size in bytes of all attributes that make up one element (vertex):
115
    inline       GLsizei       getStride     (void) const { return mStride;     }
Robert Menzel's avatar
Robert Menzel committed
116
117

    //! Returns the definitions of the attributes:
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
    inline const AttributeVec& getAttributes (void) const { return mAttributes; }

    // ==================================================================================================== \/
    // ============================================================================================ 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 offset = mStride;
        Attribute attribute = { _name, _type, _size, offset, _normalized };
        defineAttribute(attribute);
    }

    //! Adds the attribute at the end of the existing attributes, stride gets computed automatically
Robert Menzel's avatar
Robert Menzel committed
137
    //! + extra padding in bytes at the end
138
139
140
141
142
143
144
    void defineAttributeWithPadding(
        const std::string& _name,
        GLenum _type,
        GLint  _size,
        GLuint _padding,
        GLboolean _normalized = GL_FALSE)
    {
Robert Menzel's avatar
Robert Menzel committed
145
146
        GLuint offset = mStride;
        Attribute attribute = { _name, _type, _size, offset, _normalized };
147
148
149
150
151
152
153
        defineAttribute(attribute);
        // defineAttribute will shift the mStride to the end of this attribute, so we only have to
        // add the explicit padding:
        mStride += _padding;
    }

    //! Adds an attribute defined by an offset: this way an attribute can get added at arbitrary
Robert Menzel's avatar
Robert Menzel committed
154
155
    //! 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...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    void defineAttributeWithOffset(
        const std::string& _name,
        GLenum _type,
        GLint  _size,
        GLuint _offset,
        GLboolean _normalized = GL_FALSE)
    {
        Attribute attribute = { _name, _type, _size, _offset, _normalized };
        defineAttribute(attribute);
    }

    //! Takes care of a valid stride size and adds the attribute
    void defineAttribute( const Attribute &_attribute )
    {
        // this way attribute definitions don't have to be in order!
Robert Menzel's avatar
Robert Menzel committed
171
172
        GLsizei attributeWidth = getGLTypeSize(_attribute.type)*_attribute.size; // in bytes
        mStride = std::max( (GLsizei)_attribute.offset + attributeWidth, mStride);
173
174
175
        mAttributes.push_back( _attribute );
    }

176
177
178
    //! Returns the index of a named attribute
    int_t getAttributeIndexByName(const std::string& _nameInArray) const;

179
180
181
182
183
184
185
186
187
188
189
190
    //! Setting of the stride size explicitly is not needed if the attributes are defined correctly (with padding)
    inline void setStride( GLsizei _stride ) {
        mStride = _stride;
    }

    //! removes all attributes
    inline void removeAttributes(void)
    {
        mStride = 0;
        mAttributes.clear();
    }

191
192
193
194
195
196
    //! Set data for this buffer for a given number of elements
    //! 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 );
    }

197
198
199
200
201
202
203
204
205
206
207
208
209
    //! 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;
};

210
ACGL_SHARED_TYPEDEF(ArrayBuffer)
211
212


Robert Menzel's avatar
Robert Menzel committed
213
} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
214
215
} // ACGL

216
#endif // ACGL_OPENGL_OBJECTS_ARRAYBUFFER_HH