Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
VertexArray.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "precompiled.h"
19 
20 #include "lib/alignment.h"
21 #include "lib/ogl.h"
22 #include "lib/sysdep/rtl.h"
23 #include "maths/Vector3D.h"
24 #include "maths/Vector4D.h"
25 #include "graphics/Color.h"
26 #include "graphics/SColor.h"
27 #include "renderer/VertexArray.h"
28 #include "renderer/VertexBuffer.h"
30 
31 
32 VertexArray::VertexArray(GLenum usage, GLenum target)
33 {
34  m_Usage = usage;
35  m_Target = target;
36  m_NumVertices = 0;
37 
38  m_VB = 0;
39  m_BackingStore = 0;
40  m_Stride = 0;
41 }
42 
43 
45 {
46  Free();
47 }
48 
49 // Free all resources on destruction or when a layout parameter changes
51 {
53  m_BackingStore = 0;
54 
55  if (m_VB)
56  {
58  m_VB = 0;
59  }
60 }
61 
62 
63 // Set the number of vertices stored in the array
65 {
66  if (num == m_NumVertices)
67  return;
68 
69  Free();
70  m_NumVertices = num;
71 }
72 
73 
74 // Add vertex attributes like Position, Normal, UV
76 {
77  ENSURE(
78  (attr->type == GL_FLOAT || attr->type == GL_SHORT || attr->type == GL_UNSIGNED_SHORT || attr->type == GL_UNSIGNED_BYTE)
79  && "Unsupported attribute type"
80  );
81  ENSURE(attr->elems >= 1 && attr->elems <= 4);
82 
83  attr->vertexArray = this;
84  m_Attributes.push_back(attr);
85 
86  Free();
87 }
88 
89 
90 // Template specialization for GetIterator().
91 // We can put this into the source file because only a fixed set of types
92 // is supported for type safety.
93 template<>
94 VertexArrayIterator<CVector3D> VertexArray::Attribute::GetIterator<CVector3D>() const
95 {
96  ENSURE(vertexArray);
97  ENSURE(type == GL_FLOAT);
98  ENSURE(elems >= 3);
99 
100  return vertexArray->MakeIterator<CVector3D>(this);
101 }
102 
103 template<>
104 VertexArrayIterator<CVector4D> VertexArray::Attribute::GetIterator<CVector4D>() const
105 {
106  ENSURE(vertexArray);
107  ENSURE(type == GL_FLOAT);
108  ENSURE(elems >= 4);
109 
110  return vertexArray->MakeIterator<CVector4D>(this);
111 }
112 
113 template<>
114 VertexArrayIterator<float[2]> VertexArray::Attribute::GetIterator<float[2]>() const
115 {
116  ENSURE(vertexArray);
117  ENSURE(type == GL_FLOAT);
118  ENSURE(elems >= 2);
119 
120  return vertexArray->MakeIterator<float[2]>(this);
121 }
122 
123 template<>
124 VertexArrayIterator<SColor3ub> VertexArray::Attribute::GetIterator<SColor3ub>() const
125 {
126  ENSURE(vertexArray);
127  ENSURE(type == GL_UNSIGNED_BYTE);
128  ENSURE(elems >= 3);
129 
130  return vertexArray->MakeIterator<SColor3ub>(this);
131 }
132 
133 template<>
134 VertexArrayIterator<SColor4ub> VertexArray::Attribute::GetIterator<SColor4ub>() const
135 {
136  ENSURE(vertexArray);
137  ENSURE(type == GL_UNSIGNED_BYTE);
138  ENSURE(elems >= 4);
139 
140  return vertexArray->MakeIterator<SColor4ub>(this);
141 }
142 
143 template<>
144 VertexArrayIterator<u16> VertexArray::Attribute::GetIterator<u16>() const
145 {
146  ENSURE(vertexArray);
147  ENSURE(type == GL_UNSIGNED_SHORT);
148  ENSURE(elems >= 1);
149 
150  return vertexArray->MakeIterator<u16>(this);
151 }
152 
153 template<>
154 VertexArrayIterator<u16[2]> VertexArray::Attribute::GetIterator<u16[2]>() const
155 {
156  ENSURE(vertexArray);
157  ENSURE(type == GL_UNSIGNED_SHORT);
158  ENSURE(elems >= 2);
159 
160  return vertexArray->MakeIterator<u16[2]>(this);
161 }
162 
163 template<>
164 VertexArrayIterator<u8> VertexArray::Attribute::GetIterator<u8>() const
165 {
166  ENSURE(vertexArray);
167  ENSURE(type == GL_UNSIGNED_BYTE);
168  ENSURE(elems >= 1);
169 
170  return vertexArray->MakeIterator<u8>(this);
171 }
172 
173 template<>
174 VertexArrayIterator<u8[4]> VertexArray::Attribute::GetIterator<u8[4]>() const
175 {
176  ENSURE(vertexArray);
177  ENSURE(type == GL_UNSIGNED_BYTE);
178  ENSURE(elems >= 4);
179 
180  return vertexArray->MakeIterator<u8[4]>(this);
181 }
182 
183 template<>
184 VertexArrayIterator<short> VertexArray::Attribute::GetIterator<short>() const
185 {
186  ENSURE(vertexArray);
187  ENSURE(type == GL_SHORT);
188  ENSURE(elems >= 1);
189 
190  return vertexArray->MakeIterator<short>(this);
191 }
192 
193 template<>
194 VertexArrayIterator<short[2]> VertexArray::Attribute::GetIterator<short[2]>() const
195 {
196  ENSURE(vertexArray);
197  ENSURE(type == GL_SHORT);
198  ENSURE(elems >= 2);
199 
200  return vertexArray->MakeIterator<short[2]>(this);
201 }
202 
203 static size_t RoundStride(size_t stride)
204 {
205  if (stride <= 0)
206  return 0;
207  if (stride <= 4)
208  return 4;
209  if (stride <= 8)
210  return 8;
211  if (stride <= 16)
212  return 16;
213 
214  return Align<32>(stride);
215 }
216 
217 // Re-layout by assigning offsets on a first-come first-serve basis,
218 // then round up to a reasonable stride.
219 // Backing store is also created here, VBOs are created on upload.
221 {
222  Free();
223 
224  m_Stride = 0;
225 
226  //debug_printf(L"Layouting VertexArray\n");
227 
228  for (ssize_t idx = m_Attributes.size()-1; idx >= 0; --idx)
229  {
230  Attribute* attr = m_Attributes[idx];
231 
232  if (!attr->type || !attr->elems)
233  continue;
234 
235  size_t attrSize = 0;
236  switch(attr->type)
237  {
238  case GL_UNSIGNED_BYTE:
239  attrSize = sizeof(GLubyte);
240  break;
241  case GL_SHORT:
242  attrSize = sizeof(GLshort);
243  break;
244  case GL_UNSIGNED_SHORT:
245  attrSize = sizeof(GLushort);
246  break;
247  case GL_FLOAT:
248  attrSize = sizeof(GLfloat);
249  break;
250  default:
251  attrSize = 0;
252  debug_warn(L"Bad Attribute::type"); break;
253  }
254 
255  attrSize *= attr->elems;
256 
257  attr->offset = m_Stride;
258 
259  m_Stride += attrSize;
260 
261  if (m_Target == GL_ARRAY_BUFFER)
262  m_Stride = Align<4>(m_Stride);
263 
264  //debug_printf(L"%i: offset: %u\n", idx, attr->offset);
265  }
266 
267  if (m_Target == GL_ARRAY_BUFFER)
269 
270  //debug_printf(L"Stride: %u\n", m_Stride);
271 
272  if (m_Stride)
274 }
275 
276 
277 // (Re-)Upload the attributes.
278 // Create the VBO if necessary.
280 {
282 
283  if (!m_VB)
285 
286  if (!m_VB) // failed to allocate VBO
287  return;
288 
290 }
291 
292 
293 // Bind this array, returns the base address for calls to glVertexPointer etc.
295 {
296  if (!m_VB)
297  return NULL;
298 
299  u8* base = m_VB->m_Owner->Bind();
300  base += m_VB->m_Index*m_Stride;
301  return base;
302 }
303 
304 
305 // Free the backing store to save some memory
307 {
309  m_BackingStore = 0;
310 }
311 
312 
313 
315  VertexArray(usage, GL_ELEMENT_ARRAY_BUFFER)
316 {
317  m_Attr.type = GL_UNSIGNED_SHORT;
318  m_Attr.elems = 1;
320 }
321 
323 {
324  return m_Attr.GetIterator<u16>();
325 }
void * rtl_AllocateAligned(size_t size, size_t align)
Definition: gcc.cpp:66
GLenum m_Target
Definition: VertexArray.h:197
#define u8
Definition: types.h:39
size_t m_Index
Start index of this chunk in owner.
Definition: VertexBuffer.h:52
VertexArray * vertexArray
Definition: VertexArray.h:145
CVertexBuffer::VBChunk * m_VB
Definition: VertexArray.h:201
VertexArrayIterator< u16 > GetIterator() const
Gets the iterator over the (only) attribute in this array, i.e. a u16.
CVertexBufferManager g_VBMan
VertexIndexArray(GLenum usage)
void AddAttribute(Attribute *attr)
Definition: VertexArray.cpp:75
void FreeBackingStore()
u8 * Bind()
Bind to this buffer; return pointer to address required as parameter to glVertexPointer ( + etc) call...
VertexArray(GLenum usage, GLenum target=GL_ARRAY_BUFFER)
Definition: VertexArray.cpp:32
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
CVertexBuffer::VBChunk * Allocate(size_t vertexSize, size_t numVertices, GLenum usage, GLenum target)
Try to allocate a vertex buffer of the given size and type.
size_t m_Stride
Definition: VertexArray.h:202
static size_t RoundStride(size_t stride)
void SetNumVertices(size_t num)
Definition: VertexArray.cpp:64
void UpdateChunkVertices(VBChunk *chunk, void *data)
Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer...
char * m_BackingStore
Definition: VertexArray.h:203
VertexArrayIterator< T > GetIterator() const
std::vector< Attribute * > m_Attributes
Definition: VertexArray.h:199
Attribute m_Attr
Definition: VertexArray.h:221
intptr_t ssize_t
Definition: wposix_types.h:82
#define u16
Definition: types.h:40
void Release(CVertexBuffer::VBChunk *chunk)
Returns the given chunk to its owning buffer.
CVertexBuffer * m_Owner
Owning (parent) vertex buffer.
Definition: VertexBuffer.h:50
void rtl_FreeAligned(void *alignedPointer)
Definition: gcc.cpp:93
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:324
GLenum m_Usage
Definition: VertexArray.h:196
size_t m_NumVertices
Definition: VertexArray.h:198