ArrayBuffer.hh 8.59 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
#include <ACGL/ACGL.hh>

29
#include <ACGL/Base/Macros.hh>
Robert Menzel's avatar
Robert Menzel committed
30
31
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Tools.hh>
Robert Menzel's avatar
Robert Menzel committed
32
33
34
35

#include <string>
#include <vector>

36
37
#include <ACGL/OpenGL/Objects/Buffer.hh>

Robert Menzel's avatar
Robert Menzel committed
38
namespace ACGL{
Robert Menzel's avatar
Robert Menzel committed
39
namespace OpenGL{
Robert Menzel's avatar
Robert Menzel committed
40

41
class ArrayBuffer : public Buffer
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
{
    // ==================================================================================================== \/
    // ============================================================================================ 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
        GLuint      offset;     // offset in bytes into the array
        GLboolean   normalized; // int types can get normalzed to 0..1 / -1..1 by GL
    };

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

    // ========================================================================================================= \/
    // ============================================================================================ CONSTRUCTORS \/
    // ========================================================================================================= \/
public:
67
    ArrayBuffer()
68
69
70
71
72
        : Buffer(GL_ARRAY_BUFFER),
        mStride(0),
        mAttributes()
    {}

73
    ArrayBuffer( SharedBufferObject _pBuffer )
74
75
76
77
78
79
80
81
82
        : Buffer(_pBuffer, GL_ARRAY_BUFFER),
        mStride(0),
        mAttributes()
    {}

    // ==================================================================================================== \/
    // ============================================================================================ GETTERS \/
    // ==================================================================================================== \/
public:
83
    inline       GLsizei       getElements   (void) const { return mSize/mStride; }
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
    inline       GLsizei       getStride     (void) const { return mStride;     }
    inline const AttributeVec& getAttributes (void) const { return mAttributes; }

    // ==================================================================================================== \/
    // ============================================================================================ METHODS \/
    // ==================================================================================================== \/
public:
    //int_t getAttributeIndexByName(const std::string& _nameInArray) const;

    /* 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!
     */
    //! 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
    //! + extra padding in bytes
    void defineAttributeWithPadding(
        const std::string& _name,
        GLenum _type,
        GLint  _size,
        GLuint _padding,
        GLboolean _normalized = GL_FALSE)
    {
        Attribute attribute = { _name, _type, _size, (GLuint)mStride, _normalized };
        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
    //! locations in the stride. If it's added at the end, the stride gets resized.
    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!
        mStride = std::max( (GLsizei)_attribute.offset + getGLTypeSize(_attribute.type)*_attribute.size,
                                     mStride);
        mAttributes.push_back( _attribute );
    }

167
168
169
    //! Returns the index of a named attribute
    int_t getAttributeIndexByName(const std::string& _nameInArray) const;

170
171
172
173
174
175
176
177
178
179
180
181
    //! 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();
    }

182
183
184
185
186
187
    //! 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 );
    }

188
189
190
191
192
193
194
195
196
197
198
199
200
    //! 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;
};

201
ACGL_SHARED_TYPEDEF(ArrayBuffer)
202
203


Robert Menzel's avatar
Robert Menzel committed
204
} // OpenGL
Robert Menzel's avatar
Robert Menzel committed
205
206
} // ACGL

207
#endif // ACGL_OPENGL_OBJECTS_ARRAYBUFFER_HH