xoreos  0.0.5
vertexbuffer.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <cstdlib>
26 #include <cstring>
27 #include <cassert>
28 
31 
32 namespace Graphics {
33 
35  return const_cast<GLvoid *>(pointer);
36 }
37 
38 const GLvoid *VertexAttrib::getData() const {
39  return pointer;
40 }
41 
42 void VertexAttrib::enable() const {
43  switch (index) {
44  case VPOSITION:
45  glEnableClientState(GL_VERTEX_ARRAY);
46  glVertexPointer(size, type, stride, pointer);
47  break;
48 
49  case VNORMAL:
50  assert(size == 3);
51  glEnableClientState(GL_NORMAL_ARRAY);
52  glNormalPointer(type, stride, pointer);
53  break;
54 
55  case VCOLOR:
56  glEnableClientState(GL_COLOR_ARRAY);
57  glColorPointer(size, type, stride, pointer);
58  break;
59 
60  default:
61  assert(index >= VTCOORD);
62  glClientActiveTextureARB(GL_TEXTURE0 + index - VTCOORD);
63  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
64  glTexCoordPointer(size, type, stride, pointer);
65  break;
66  }
67 }
68 
69 void VertexAttrib::disable() const {
70  switch (index) {
71  case VPOSITION:
72  glDisableClientState(GL_VERTEX_ARRAY);
73  break;
74 
75  case VNORMAL:
76  glDisableClientState(GL_NORMAL_ARRAY);
77  break;
78 
79  case VCOLOR:
80  glDisableClientState(GL_COLOR_ARRAY);
81  break;
82 
83  default:
84  assert(index >= VTCOORD);
85  glClientActiveTextureARB(GL_TEXTURE0 + index - VTCOORD);
86  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
87  break;
88  }
89 }
90 
91 
92 VertexBuffer::VertexBuffer() : _count(0), _size(0), _data(0), _vbo(0), _hint(GL_STATIC_DRAW) {
93 }
94 
95 VertexBuffer::VertexBuffer(const VertexBuffer &other) : _data(0), _vbo(0), _hint(GL_STATIC_DRAW) {
96  *this = other;
97 }
98 
100  destroyGL(); // Dangerous if GL components not already freed and we're not in the GL context thread.
101  delete[] _data;
102 }
103 
105  if (this == &other)
106  return *this;
107 
108  setVertexDecl(other._decl);
109  setSize(other._count, other._size);
110 
111  /* _data, _count and _size are always only ever set by the setSize() method,
112  * which is also called above to replicate the situation in the right-hand
113  * side VertexBuffer of the assignment. _data is set to a new allocated block
114  * of memory of count * size size, but only if both count and size > 0.
115  *
116  * We can never run into a situation here where _data == 0 and other._data
117  * != 0 or vice versa. Either both are == 0 (in which case count * size == 0)
118  * or both are != 0. */
119 
120  if (!_data || !other._data)
121  return *this;
122 
123  memcpy(_data, other._data, other._count * other._size);
124 
125  // Fix up the data pointers
126 
127  std::vector<VertexAttrib>::const_iterator src = other._decl.begin();
128  std::vector<VertexAttrib>::iterator dest = _decl.begin();
129  while ((src != other._decl.end()) && (dest != _decl.end())) {
130  const byte *ptr = _data + (reinterpret_cast<const byte *>(src->pointer) - other._data);
131 
132  dest->pointer = reinterpret_cast<const GLvoid *>(ptr);
133 
134  ++src;
135  ++dest;
136  }
137 
138  return *this;
139 }
140 
141 void VertexBuffer::setSize(uint32 vertCount, uint32 vertSize) {
142  _count = vertCount;
143  _size = vertSize;
144 
145  delete[] _data;
146  _data = 0;
147 
148  if (_count && _size) {
149  _data = new byte[_count * _size];
150  }
151 }
152 
154  _decl = decl;
155 }
156 
158  switch (type) {
159  case GL_UNSIGNED_BYTE:
160  return 1;
161  case GL_SHORT:
162  case GL_UNSIGNED_SHORT:
163  case GL_2_BYTES:
164  return 2;
165  case GL_3_BYTES:
166  return 3;
167  case GL_INT:
168  case GL_UNSIGNED_INT:
169  case GL_FLOAT:
170  case GL_4_BYTES:
171  return 4;
172  case GL_DOUBLE:
173  return 8;
174  default:
175  break;
176  }
177 
178  return 0;
179 }
180 
182  uint32 vertSize = 0;
183  _decl.clear();
184  for (VertexDecl::iterator a = decl.begin(); a != decl.end(); ++a)
185  vertSize += a->size * getTypeSize(a->type);
186 
187  setSize(vertCount, vertSize);
188 
189  byte *data = _data;
190  for (VertexDecl::iterator a = decl.begin(); a != decl.end(); ++a) {
191  a->stride = 0;
192  a->pointer = data;
193 
194  data += vertCount * a->size * getTypeSize(a->type);
195  _decl.push_back(*a);
196  }
197 }
198 
200  uint32 vertSize = 0;
201  _decl.clear();
202  for (VertexDecl::iterator a = decl.begin(); a != decl.end(); ++a)
203  vertSize += a->size * getTypeSize(a->type);
204 
205  setSize(vertCount, vertSize);
206 
207  uint32 offset = 0;
208  for (VertexDecl::iterator a = decl.begin(); a != decl.end(); ++a) {
209  a->stride = vertSize;
210  a->pointer = _data + offset;
211 
212  offset += a->size * getTypeSize(a->type);
213  _decl.push_back(*a);
214  }
215 }
216 
218  return static_cast<GLvoid *>(_data);
219 }
220 
221 const GLvoid *VertexBuffer::getData() const {
222  return static_cast<const GLvoid *>(_data);
223 }
224 
225 GLvoid *VertexBuffer::getData(size_t vertexDecl) {
226  assert(vertexDecl < _decl.size());
227 
228  return _decl[vertexDecl].getData();
229 }
230 
231 const GLvoid *VertexBuffer::getData(size_t vertexDecl) const {
232  assert(vertexDecl < _decl.size());
233 
234  return _decl[vertexDecl].getData();
235 }
236 
238  return _decl;
239 }
240 
242  return _count;
243 }
244 
246  return _size;
247 }
248 
249 void VertexBuffer::initGL(GLuint hint) {
250  if (_vbo != 0) {
251  return; // Already initialised.
252  }
253 
254  _hint = hint;
255  if (_count) {
256  glGenBuffers(1, &_vbo);
257  glBindBuffer(GL_ARRAY_BUFFER, _vbo);
258  glBufferData(GL_ARRAY_BUFFER, _count * _size, _data, _hint);
259  glBindBuffer(GL_ARRAY_BUFFER, 0); // Return to default buffer.
260  }
261 }
262 
264  if (_count) {
265  glBindBuffer(GL_ARRAY_BUFFER, _vbo);
266  glBufferData(GL_ARRAY_BUFFER, _count * _size, _data, _hint);
267  glBindBuffer(GL_ARRAY_BUFFER, 0); // Return to default buffer. Maybe this isn't required.
268  }
269 }
270 
272  glBufferSubData(GL_ARRAY_BUFFER, 0, _count * _size, _data);
273 }
274 
276  if (_vbo != 0) {
277  glDeleteBuffers(1, &_vbo);
278  _vbo = 0;
279  }
280 }
281 
282 GLuint VertexBuffer::getVBO() const {
283  return _vbo;
284 }
285 
286 void VertexBuffer::draw(GLenum mode, const IndexBuffer &indexBuffer) const {
287  if ((getCount() == 0) || (indexBuffer.getCount() == 0))
288  return;
289 
290  for (VertexDecl::const_iterator d = _decl.begin(); d != _decl.end(); ++d)
291  d->enable();
292 
293  glDrawElements(mode, indexBuffer.getCount(), indexBuffer.getType(), indexBuffer.getData());
294 
295  for (VertexDecl::const_iterator d = _decl.begin(); d != _decl.end(); ++d)
296  d->disable();
297 }
298 
299 } // End of namespace Graphics
GLvoid * getData()
Access buffer data.
Definition: indexbuffer.cpp:78
Vertex texture coordinates, VTCOORDi = VTCOORD + i.
Definition: vertexbuffer.h:39
uint32 getCount() const
Get vertex count.
Vertex position.
Definition: vertexbuffer.h:36
uint32 _size
Size of a buffer element in bytes (vertex attributes size sum).
Definition: vertexbuffer.h:140
GLuint index
Index of the vertex attribute (see VertexAttribIdEnum).
Definition: vertexbuffer.h:44
GLuint _vbo
Vertex Buffer Object.
Definition: vertexbuffer.h:143
GLenum type
Data type of each attribute component in the array.
Definition: vertexbuffer.h:46
Vertex color.
Definition: vertexbuffer.h:38
void updateGLBound() const
Update an existing GL buffer object, assuming it is already bound.
void setVertexDeclInterleave(uint32 vertCount, VertexDecl &decl)
Set the interleaved vertex declaration for this buffer.
void setVertexDecl(const VertexDecl &decl)
Set vertex declaration for this buffer.
const GLvoid * pointer
Offset of the first component of the first generic vertex attribute.
Definition: vertexbuffer.h:48
std::vector< VertexAttrib > VertexDecl
Vertex data layout.
Definition: vertexbuffer.h:63
A index buffer.
const VertexDecl & getVertexDecl() const
Access vertex declaration.
static uint32 getTypeSize(GLenum type)
Vertex normal.
Definition: vertexbuffer.h:37
void destroyGL()
Clear (destroy) GL resources associated with the buffer.
void setVertexDeclLinear(uint32 vertCount, VertexDecl &decl)
Set the linear vertex declaration for this buffer.
uint32 getSize() const
Get vertex element size in bytes.
byte * _data
Buffer data.
Definition: vertexbuffer.h:141
Buffer containing vertex data.
Definition: vertexbuffer.h:68
GLenum getType() const
Get element type.
Definition: indexbuffer.cpp:90
GLuint _hint
GL hint for static or dynamic data.
Definition: vertexbuffer.h:144
uint32 getCount() const
Get element count.
Definition: indexbuffer.cpp:86
VertexDecl _decl
Vertex declaration.
Definition: vertexbuffer.h:138
GLint size
Number of components per vertex attribute, must be 1, 2, 3, 4.
Definition: vertexbuffer.h:45
VertexBuffer & operator=(const VertexBuffer &other)
uint32_t uint32
Definition: types.h:204
GLvoid * getData()
Access buffer data.
uint32 _count
Number of elements in buffer.
Definition: vertexbuffer.h:139
void draw(GLenum mode, const IndexBuffer &indexBuffer) const
Draw this IndexBuffer/VertexBuffer combination.
Buffer containing indices data.
Definition: indexbuffer.h:33
void initGL(GLuint hint=GL_STATIC_DRAW)
Initialise internal buffer object for GL handling.
GLsizei stride
Byte offset between consecutive vertex attributes.
Definition: vertexbuffer.h:47
void updateGL()
Update existing GL buffer object.
A vertex buffer.
uint8 byte
Definition: types.h:209
void setSize(uint32 vertCount, uint32 vertSize)
Change buffer size.