xoreos  0.0.5
mesh.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 "src/graphics/mesh/mesh.h"
26 
27 namespace Graphics {
28 
29 namespace Mesh {
30 
31 Mesh::Mesh(GLuint type, GLuint hint) : GLContainer(), _type(type), _hint(hint), _usageCount(0), _vao(0), _radius(0.0f) {
32 }
33 
34 Mesh::~Mesh() {
35  removeFromQueue(kQueueNewTexture); // In case the mesh is destroyed while waiting to be initialised.
36  destroyGL();
37 }
38 
39 VertexBuffer *Mesh::getVertexBuffer() {
40  return &_vertexBuffer;
41 }
42 
43 IndexBuffer *Mesh::getIndexBuffer() {
44  return &_indexBuffer;
45 }
46 
47 void Mesh::setName(const Common::UString &name) {
48  _name = name;
49 }
50 
51 const Common::UString &Mesh::getName() const {
52  return _name;
53 }
54 
55 void Mesh::setType(GLuint type) {
56  _type = type;
57 }
58 
59 GLuint Mesh::getType() const {
60  return _type;
61 }
62 
63 void Mesh::setHint(GLuint hint) {
64  _hint = hint;
65 }
66 
67 GLuint Mesh::getHint() const {
68  return _hint;
69 }
70 
71 void Mesh::init() {
72  float minx = 0.0f, miny = 0.0f, minz = 0.0f, maxx = 0.0f, maxy = 0.0f, maxz = 0.0f;
73  float *vertices = static_cast<float *>(_vertexBuffer.getData());
74  const VertexDecl &decl = _vertexBuffer.getVertexDecl();
75  if (decl.size() >= 1) {
76  // So...for now, just check on the first batch. It's probably going to be the actual vertex data. We hope.
77  if ((decl[0].type == GL_FLOAT) && (decl[0].size == 3)) {
78  // Make sure it's of type float, and that there's reasonable data to go along with it.
79  minx = maxx = *vertices++;
80  miny = maxy = *vertices++;
81  minz = maxz = *vertices++;
82  size_t vertexCount = _vertexBuffer.getCount() / sizeof(float) / 3;
83  for (size_t i = 0; i < vertexCount; ++i) {
84  float vx = *vertices++;
85  float vy = *vertices++;
86  float vz = *vertices++;
87  if (minx > vx) minx = vx;
88  if (miny > vy) miny = vy;
89  if (minz > vz) minz = vz;
90  if (maxx < vx) maxx = vx;
91  if (maxy < vy) maxy = vy;
92  if (maxz < vz) maxz = vz;
93  if (decl[0].stride > (int32)(3 * sizeof(float))) {
94  vertices += (decl[0].stride / sizeof(float)) - 3;
95  }
96  }
97  _min = glm::vec3(minx, miny, minz);
98  _max = glm::vec3(maxx, maxy, maxz);
99  _centre = _min;
100  _centre += _max;
101  _centre *= 0.5f;
102  _radius = (_max - _centre).length();
103  //_centre = 0.5f * (_min + _max);
104  }
105  }
106  // Borrowing kQueueNewTexture for now as a more generic GLContainer initialiser.
109 }
110 
111 void Mesh::initGL() {
114 
115  // GL3.x render path uses Vertex Array (attribute) Objects.
116  if (GfxMan.isGL3()) {
117  glGenVertexArrays(1, &_vao);
118  glBindVertexArray(_vao);
119 
120  const VertexDecl &decl = _vertexBuffer.getVertexDecl();
121 
122  glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer.getVBO());
123  for (uint32 i = 0; i < decl.size(); ++i) {
124  // Using intptr_t to ensure correct bit length for the architecture.
125  intptr_t offset = (intptr_t) (decl[i].pointer);
126  offset -= (intptr_t) (_vertexBuffer.getData());
127  glVertexAttribPointer(decl[i].index,
128  decl[i].size,
129  decl[i].type,
130  GL_FALSE,
131  decl[i].stride,
132  reinterpret_cast<void *>(offset));
133  glEnableVertexAttribArray(decl[i].index);
134  }
135 
136  if (_indexBuffer.getCount()) {
137  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer.getIBO());
138  }
139 
140  // Finish up with the VAO, ready for use.
141  glBindVertexArray(0);
142 
143  // This will eventually not be required, but definitely is when mixing with old-style OpenGL rendering calls.
144  glBindBuffer(GL_ARRAY_BUFFER, 0);
145  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
146 
147  } else {
148  glBindBuffer(GL_ARRAY_BUFFER, 0);
149  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
150  }
151 
152  // TODO: create boundary volume descriptions.
153 }
154 
155 void Mesh::updateGL() {
158 }
159 
160 void Mesh::destroyGL() {
163 
164  // Should only be non-zero on GL3.x contexts anyway.
165  if (_vao) {
166  glDeleteVertexArrays(1, &_vao);
167  _vao = 0;
168  }
169 }
170 
171 void Mesh::renderImmediate() {
172  renderBind();
173  render();
174  renderUnbind();
175 }
176 
177 void Mesh::renderBind() {
178  if (GfxMan.isGL3()) {
179  glBindVertexArray(_vao);
180  } else {
181  const VertexDecl &decl = _vertexBuffer.getVertexDecl();
182  glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer.getVBO());
183  for (size_t i = 0; i < decl.size(); ++i) {
184  intptr_t offset = (intptr_t) (decl[i].pointer);
185  offset -= (intptr_t) (_vertexBuffer.getData());
186  switch (decl[i].index) {
187  case VPOSITION:
188  glEnableClientState(GL_VERTEX_ARRAY);
189  glVertexPointer(decl[i].size, decl[i].type, decl[i].stride, (GLvoid *)(offset));
190  break;
191  case VNORMAL:
192  glEnableClientState(GL_NORMAL_ARRAY);
193  glNormalPointer(decl[i].type, decl[i].stride, (GLvoid *)(offset));
194  break;
195  case VCOLOR:
196  glEnableClientState(GL_COLOR_ARRAY);
197  glColorPointer(decl[i].size, decl[i].type, decl[i].stride, (GLvoid *)(offset));
198  break;
199  default: // VTCOORD
200  glClientActiveTextureARB(GL_TEXTURE0 + decl[i].index - VTCOORD);
201  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
202  glTexCoordPointer(decl[i].size, decl[i].type, decl[i].stride, (GLvoid *)(offset));
203  break;
204  }
205  }
206  }
207 }
208 
209 void Mesh::render() {
210  if (GfxMan.isGL3()) {
211  if (_indexBuffer.getCount()) {
212  glDrawElements(_type, _indexBuffer.getCount(), _indexBuffer.getType(), 0);
213  } else {
214  glDrawArrays(_type, 0, _vertexBuffer.getCount());
215  }
216  } else {
217  if (_indexBuffer.getCount()) {
218  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer.getIBO());
219  glDrawElements(_type, _indexBuffer.getCount(), _indexBuffer.getType(), 0);
220  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
221  } else {
222  glDrawArrays(_type, 0, _vertexBuffer.getCount());
223  }
224  }
225 }
226 
227 void Mesh::renderUnbind() {
228  if (GfxMan.isGL3()) {
229  // So long as each mesh rebinds what it needs, there's actually no need to bind 0 here.
230  glBindVertexArray(0);
231  } else {
232  const VertexDecl &decl = _vertexBuffer.getVertexDecl();
233  for (size_t i = 0; i < decl.size(); ++i) {
234  switch (decl[i].index) {
235  case VPOSITION:
236  glDisableClientState(GL_VERTEX_ARRAY);
237  break;
238  case VNORMAL:
239  glDisableClientState(GL_NORMAL_ARRAY);
240  break;
241  case VCOLOR:
242  glDisableClientState(GL_COLOR_ARRAY);
243  break;
244  default: // VTCOORD
245  glClientActiveTextureARB(GL_TEXTURE0 + decl[i].index - VTCOORD);
246  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
247  break;
248  }
249  }
250  glBindBuffer(GL_ARRAY_BUFFER, 0);
251  }
252 }
253 
254 void Mesh::useIncrement() {
255  ++_usageCount;
256 }
257 
258 void Mesh::useDecrement() {
259  if (_usageCount) {
260  --_usageCount;
261  }
262 }
263 
264 uint32 Mesh::useCount() const {
265  return _usageCount;
266 }
267 
268 const glm::vec3 &Mesh::getCentre() const {
269  return _centre;
270 }
271 
272 float Mesh::getRadius() const {
273  return _radius;
274 }
275 
276 void Mesh::doRebuild() {
277  // We could do some fancy things here, like checking to see if GL resources
278  // have already been built, and just updating them. Let's just be lazy and
279  // force a complete rebuild instead.
280 
281  destroyGL();
282  initGL();
283 }
284 
285 void Mesh::doDestroy() {
286  destroyGL();
287 }
288 
289 } // End of namespace Mesh
290 
291 } // End of namespace Graphics
A newly created texture.
Definition: types.h:73
GLuint _hint
Definition: mesh.h:91
glm::vec3 _max
Definition: mesh.h:100
GLuint _type
Definition: mesh.h:90
uint32 _usageCount
Definition: mesh.h:95
Vertex texture coordinates, VTCOORDi = VTCOORD + i.
Definition: vertexbuffer.h:39
void destroyGL()
Clear (destroy) GL resources associated with the buffer.
A class holding an UTF-8 string.
Definition: ustring.h:48
uint32 getCount() const
Get vertex count.
Vertex position.
Definition: vertexbuffer.h:36
Vertex color.
Definition: vertexbuffer.h:38
Generic mesh handling class.
IndexBuffer _indexBuffer
Definition: mesh.h:82
void addToQueue(QueueType queue)
Definition: queueable.cpp:45
std::vector< VertexAttrib > VertexDecl
Vertex data layout.
Definition: vertexbuffer.h:63
const VertexDecl & getVertexDecl() const
Access vertex declaration.
Vertex normal.
Definition: vertexbuffer.h:37
void updateGL()
Update existing GL buffer object.
void destroyGL()
Clear (destroy) GL resources associated with the buffer.
void renderUnbind()
Definition: mesh.cpp:227
void initGL(GLuint hint=GL_STATIC_DRAW)
Initialise internal buffer object for GL handling.
Definition: indexbuffer.cpp:94
Buffer containing vertex data.
Definition: vertexbuffer.h:68
GLenum getType() const
Get element type.
Definition: indexbuffer.cpp:90
glm::vec3 _centre
Definition: mesh.h:99
void removeFromQueue(QueueType queue)
Definition: queueable.cpp:56
uint32 getCount() const
Get element count.
Definition: indexbuffer.cpp:86
void renderBind()
Follows the steps of renderImmediate, but broken into different functions.
Definition: mesh.cpp:177
VertexBuffer _vertexBuffer
Definition: mesh.h:81
glm::vec3 _min
Definition: mesh.h:101
uint32_t uint32
Definition: types.h:204
static void init()
Definition: xoreos.cpp:284
GLvoid * getData()
Access buffer data.
A container of OpenGL elements.
Definition: glcontainer.h:35
Common::UString _name
Definition: mesh.h:94
Buffer containing indices data.
Definition: indexbuffer.h:33
GLuint getIBO() const
void initGL(GLuint hint=GL_STATIC_DRAW)
Initialise internal buffer object for GL handling.
void updateGL()
Update existing GL buffer object.
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
int32_t int32
Definition: types.h:203
GLuint _vao
Vertex Array Object handle. GL3.x only.
Definition: mesh.h:97