xoreos  0.0.5
graphics.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 <cassert>
26 #include <cstring>
27 
28 #include <boost/bind.hpp>
29 
30 #include "glm/gtc/type_ptr.hpp"
31 #include "glm/gtc/matrix_transform.hpp"
32 
33 #include "src/version/version.h"
34 
35 #include "src/common/util.h"
36 #include "src/common/maths.h"
37 #include "src/common/error.h"
38 #include "src/common/configman.h"
39 #include "src/common/debugman.h"
40 #include "src/common/threads.h"
41 
42 #include "src/events/requests.h"
43 #include "src/events/events.h"
45 
46 #include "src/graphics/graphics.h"
47 #include "src/graphics/icon.h"
48 #include "src/graphics/cursor.h"
50 #include "src/graphics/queueman.h"
53 #include "src/graphics/camera.h"
54 
57 
62 
64 
66 
67 static glm::mat4 inverse(const glm::mat4 &m);
68 
69 namespace Graphics {
70 
71 PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
72 
74  _ready = false;
75 
76  _debugGL = false;
77 
78  _rendererExperimental = false;
79 
80  _needManualDeS3TC = false;
83 
84  // Default to an OpenGL 3.2 compatibility context. GL3.x will be available on most modern systems.
86  _fsaa = 0;
87 
88  _cullFaceEnabled = true;
89  _cullFaceMode = GL_BACK;
90 
92 
93  _viewAngle = 60.0f;
94  _clipNear = 1.0f;
95  _clipFar = 1000.0f;
96 
98  _guiWidth = 800;
99  _guiHeight = 600;
100 
101  _fpsCounter.reset(new FPSCounter(3));
102 
103  _frameLock.store(0);
104 
105  _cursor = 0;
106 
107  _takeScreenshot = false;
108 
109  _renderableID = 0;
110 
111  _hasAbandoned = false;
112 
113  _lastSampled = 0;
114 
116 }
117 
119  deinit();
120 }
121 
124 
125  WindowMan.init();
126 
127  _debugGL = ConfigMan.getBool("debuggl", false);
128 
129  _rendererExperimental = ConfigMan.getBool("rendernew", false);
130 
131  if (!setupSDLGL())
132  throw Common::Exception("Failed initializing the OpenGL renderer");
133 
134  // Try to change the FSAA settings to the config value
135  if (_fsaa != ConfigMan.getInt("fsaa"))
136  if (!setFSAA(ConfigMan.getInt("fsaa")))
137  // If that fails, set the config to the current level
138  ConfigMan.setInt("fsaa", _fsaa);
139 
140  // Initialize glew, for the extension entry points
141  GLenum glewErr = glewInit();
142  if (glewErr != GLEW_OK)
143  throw Common::Exception("Failed initializing glew: %s", glewGetErrorString(glewErr));
144 
145  // Check if we have all needed OpenGL extensions
147 
148  setupScene();
149 
150  ShaderMan.init();
151  SurfaceMan.init();
152  MaterialMan.init();
153  MeshMan.init();
154 
155  if (!_animationThread.createThread("Animations"))
156  throw Common::Exception("Failed to create the animation thread");
157 
158  _ready = true;
159 }
160 
163 
164  if (!_ready)
165  return;
166 
167  QueueMan.clearAllQueues();
168 
171 
172  MeshMan.deinit();
173  ShaderMan.deinit();
174  WindowMan.deinit();
175 
176  _ready = false;
177 
178  _needManualDeS3TC = false;
179  _supportMultipleTextures = false;
181 }
182 
184  return _ready;
185 }
186 
188  return _needManualDeS3TC;
189 }
190 
193 }
194 
196  return _multipleTextureCount;
197 }
198 
200  return _fsaa;
201 }
202 
204  return _fpsCounter->getFPS();
205 }
206 
207 bool GraphicsManager::setFSAA(int level) {
208  // Force calling it from the main thread
209  if (!Common::isMainThread()) {
210  Events::MainThreadFunctor<bool> functor(boost::bind(&GraphicsManager::setFSAA, this, level));
211 
212  return RequestMan.callInMainThread(functor);
213  }
214 
215  if (_fsaa == level)
216  // Nothing to do
217  return true;
218 
219  // Check if we have the support for that level
220  if (level > WindowMan.getMaxFSAA())
221  return false;
222 
223  destroyContext();
224 
225  if (WindowMan.initRender(_renderType, _debugGL, level))
226  _fsaa = level;
227 
228  // Failed changing, back up
229  else if (!WindowMan.initRender(_renderType, _debugGL, _fsaa))
230  // There's no reason how this could possibly fail, but ok...
231  throw Common::Exception("Failed reverting to the old FSAA settings");
232 
233  rebuildContext();
234 
235  return _fsaa == level;
236 }
237 
243  if (_rendererExperimental) {
245  if (WindowMan.initRender(_renderType, _debugGL, _fsaa))
246  return true;
247  else {
248  warning("Your graphics card hardware or driver does not support OpenGL 3.2. "
249  "Usage of experimental renderer is not possible");
250  return false;
251  }
252  }
253 
255  if (WindowMan.initRender(_renderType, _debugGL, _fsaa))
256  return true;
257 
258  // No OpenGL 2.1 core context. Let SDL decide what to give us.
259 
261  if (WindowMan.initRender(_renderType, _debugGL, _fsaa))
262  return true;
263 
264  return false;
265 }
266 
267 static void outputGLDebug(GLenum source, GLenum type, GLuint id, GLenum severity,
268  GLsizei UNUSED(length), const GLchar *message,
269  const void *UNUSED(userParam)) {
270 
271  static const uint32 kSourceLookup[] = {
272  GL_DEBUG_SOURCE_API_ARB , Common::kDebugGLAPI,
273  GL_DEBUG_SOURCE_SHADER_COMPILER_ARB, Common::kDebugGLWindow,
274  GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB , Common::kDebugGLShader,
275  GL_DEBUG_SOURCE_THIRD_PARTY_ARB , Common::kDebugGL3rd,
276  GL_DEBUG_SOURCE_APPLICATION_ARB , Common::kDebugGLApp,
277  GL_DEBUG_SOURCE_OTHER_ARB , Common::kDebugGLOther
278  };
279 
280  static const uint32 kTypeLookup[] = {
281  GL_DEBUG_TYPE_ERROR_ARB , Common::kDebugGLTypeError,
282  GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, Common::kDebugGLTypeDeprecated,
283  GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB , Common::kDebugGLTypeUndefined,
284  GL_DEBUG_TYPE_PERFORMANCE_ARB , Common::kDebugGLTypePortability,
285  GL_DEBUG_TYPE_PORTABILITY_ARB , Common::kDebugGLTypePerformance,
286  GL_DEBUG_TYPE_OTHER_ARB , Common::kDebugGLTypeOther
287  };
288 
289  static const uint32 kLevelLookup[] = {
290  GL_DEBUG_SEVERITY_HIGH_ARB , 1,
291  GL_DEBUG_SEVERITY_MEDIUM_ARB , 2,
292  GL_DEBUG_SEVERITY_LOW_ARB , 3,
293  GL_DEBUG_SEVERITY_NOTIFICATION, 4
294  };
295 
297  for (size_t i = 0; i < ARRAYSIZE(kSourceLookup); i += 2)
298  if (source == (GLenum) kSourceLookup[i + 0])
299  debugChannel = (Common::DebugChannel) kSourceLookup[i + 1];
300 
302  for (size_t i = 0; i < ARRAYSIZE(kTypeLookup); i += 2)
303  if (type == (GLenum) kTypeLookup[i + 0])
304  debugType = (Common::DebugGLType) kTypeLookup[i + 1];
305 
306  uint32 debugLevel = 5;
307  for (size_t i = 0; i < ARRAYSIZE(kLevelLookup); i += 2)
308  if (severity == (GLenum) kLevelLookup[i + 0])
309  debugLevel = kLevelLookup[i + 1];
310 
311  DebugMan.logDebugGL(debugChannel, debugLevel, debugType, id, message);
312 }
313 
315  if (!GLEW_EXT_texture_compression_s3tc) {
316  warning("Your graphics card does not support the needed extension "
317  "for S3TC DXT1, DXT3 and DXT5 texture decompression");
318  warning("Switching to manual S3TC DXTn decompression. "
319  "This will be slower and will take up more video memory");
320  _needManualDeS3TC = true;
321  }
322 
323  if (!_needManualDeS3TC) {
324  // Make sure we use the right glCompressedTexImage2D function
325  glCompressedTexImage2D = GLEW_GET_FUN(__glewCompressedTexImage2D) ?
326  (PFNGLCOMPRESSEDTEXIMAGE2DPROC)GLEW_GET_FUN(__glewCompressedTexImage2D) :
327  (PFNGLCOMPRESSEDTEXIMAGE2DPROC)GLEW_GET_FUN(__glewCompressedTexImage2DARB);
328 
329  if (!GLEW_ARB_texture_compression || !glCompressedTexImage2D) {
330  warning("Your graphics card doesn't support the compressed texture API");
331  warning("Switching to manual S3TC DXTn decompression. "
332  "This will be slower and will take up more video memory");
333 
334  _needManualDeS3TC = true;
335  }
336  }
337 
338 
339  if (!GLEW_ARB_multitexture) {
340  _supportMultipleTextures = false;
342  } else {
343  GLint maxTextureCoords = -1;
344  glGetIntegerv(GL_MAX_TEXTURE_COORDS, &maxTextureCoords);
345 
346  _multipleTextureCount = (maxTextureCoords <= 0) ? 1 : maxTextureCoords;
348  }
349 
351  warning("Your graphics card does no support applying multiple textures onto "
352  "one surface");
353  warning("xoreos will only use one texture. Certain surfaces may look weird");
354  }
355 
356  if (_debugGL && GLEW_ARB_debug_output) {
357  warning("Enabled OpenGL debug output");
358 
359  glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, GL_TRUE);
360 
361  /* NOTE: The type of GLDEBUGPROCARB changed with revision 17 (2013-07-08)
362  * of GL_ARB_debug_output. It involved changing the type of the last
363  * parameter, userParam, from void * to const void *. We aren't even
364  * using the parameter, so we really don't care.
365  *
366  * Conversely, the OpenGL 4.3 Core function glDebugMessageCallback()
367  * takes a GLDEBUGPROC function pointer, whose signature has again
368  * a non-const userParam. We aren't using an OpenGL 4.3 context,
369  * though.
370  *
371  * Type-punning the function pointer like this should hopefully not
372  * break anything. The C standard says that it's legal when the
373  * parameters have compatible types (otherwise, it's undefined).
374  * Since void * can be safely cast to const void *, but not the
375  * user way round, having outputGLDebug() take a const void * is
376  * probably the safest bet.
377  */
378  glDebugMessageCallbackARB((GLDEBUGPROCARB) &outputGLDebug, 0);
379  }
380 }
381 
383  glClearColor(0, 0, 0, 0);
384  glMatrixMode(GL_PROJECTION);
385  glLoadIdentity();
386  glViewport(0, 0, WindowMan.getWindowWidth(), WindowMan.getWindowHeight());
387 
388  glMatrixMode(GL_MODELVIEW);
389  glLoadIdentity();
390 
391  glShadeModel(GL_SMOOTH);
392  glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
393  glClearDepth(1.0f);
394 
395  glEnable(GL_DEPTH_TEST);
396  glDepthFunc(GL_LEQUAL);
397  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
398 
399  glEnable(GL_BLEND);
400  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
401 
402  glAlphaFunc(GL_GREATER, 0.1f);
403  glEnable(GL_ALPHA_TEST);
404 
406 
407  switch (_projectType) {
409  perspective(_viewAngle, ((float) WindowMan.getWindowWidth()) / ((float) WindowMan.getWindowHeight()), _clipNear, _clipFar);
410  break;
411 
413  ortho(0.0f, WindowMan.getWindowWidth(), 0.0f, WindowMan.getWindowHeight(), _clipNear, _clipFar);
414  break;
415 
416  default:
417  assert(false);
418  break;
419  }
420 }
421 
422 void GraphicsManager::setCullFace(bool enabled, GLenum mode) {
423  // Force calling it from the main thread
424  if (!Common::isMainThread()) {
425  Events::MainThreadFunctor<void> functor(boost::bind(&GraphicsManager::setCullFace, this, enabled, mode));
426 
427  return RequestMan.callInMainThread(functor);
428  }
429 
430  if (enabled)
431  glEnable(GL_CULL_FACE);
432  else
433  glDisable(GL_CULL_FACE);
434 
435  glCullFace(mode);
436 
437  _cullFaceEnabled = enabled;
438  _cullFaceMode = mode;
439 }
440 
442  _scalingType = scaling;
443 }
444 
445 void GraphicsManager::setGUISize(int guiWidth, int guiHeight) {
446  _guiWidth = guiWidth;
447  _guiHeight = guiHeight;
448 }
449 
450 void GraphicsManager::setPerspective(float viewAngle, float clipNear, float clipFar) {
451  // Force calling it from the main thread
452  if (!Common::isMainThread()) {
453  Events::MainThreadFunctor<void> functor(boost::bind(&GraphicsManager::setPerspective, this, viewAngle, clipNear, clipFar));
454 
455  return RequestMan.callInMainThread(functor);
456  }
457 
458  perspective(viewAngle, ((float) WindowMan.getWindowWidth()) / ((float) WindowMan.getWindowHeight()), clipNear, clipFar);
459 
461 
462  _viewAngle = viewAngle;
463  _clipNear = clipNear;
464  _clipFar = clipFar;
465 }
466 
467 void GraphicsManager::perspective(float fovy, float aspect, float zNear, float zFar) {
468  assert(fabs(fovy) > 0.001f);
469  assert(zNear > 0);
470  assert(zFar > 0);
471  assert(zFar > zNear);
472  assert((zFar - zNear) > 0.001f);
473 
474  const float f = 1.0f / (tanf(Common::deg2rad(fovy) / 2.0f));
475 
476  const float t1 = (zFar + zNear) / (zNear - zFar);
477  const float t2 = (2 * zFar * zNear) / (zNear - zFar);
478 
479  _projection[0][0] = f / aspect;
480  _projection[1][0] = 0.0f;
481  _projection[2][0] = 0.0f;
482  _projection[3][0] = 0.0f;
483 
484  _projection[0][1] = 0.0f;
485  _projection[1][1] = f;
486  _projection[2][1] = 0.0f;
487  _projection[3][1] = 0.0f;
488 
489  _projection[0][2] = 0.0f;
490  _projection[1][2] = 0.0f;
491  _projection[2][2] = t1;
492  _projection[3][2] = t2;
493 
494  _projection[0][3] = 0.0f;
495  _projection[1][3] = 0.0f;
496  _projection[2][3] = -1.0f;
497  _projection[3][3] = 0.0f;
498 
500 
503 }
504 
505 void GraphicsManager::setOrthogonal(float clipNear, float clipFar) {
506  // Force calling it from the main thread
507  if (!Common::isMainThread()) {
508  Events::MainThreadFunctor<void> functor(boost::bind(&GraphicsManager::setOrthogonal, this, clipNear, clipFar));
509 
510  return RequestMan.callInMainThread(functor);
511  }
512 
513  ortho(0.0f, WindowMan.getWindowWidth(), 0.0f, WindowMan.getWindowHeight(), clipNear, clipFar);
514 
516 
517  _clipNear = clipNear;
518  _clipFar = clipFar;
519 }
520 
521 void GraphicsManager::ortho(float left, float right, float bottom, float top, float zNear, float zFar) {
522  assert(zFar > zNear);
523  assert((zFar - zNear) > 0.001f);
524 
525  _projection[0][0] = 2.0f / (right - left);
526  _projection[1][0] = 0.0f;
527  _projection[2][0] = 0.0f;
528  _projection[3][0] = - ((right + left) / (right - left));
529 
530  _projection[0][1] = 0.0f;
531  _projection[1][1] = 2.0f / (top - bottom);
532  _projection[2][1] = 0.0f;
533  _projection[3][1] = - ((top + bottom) / (top - bottom));
534 
535  _projection[0][2] = 0.0f;
536  _projection[1][2] = 0.0f;
537  _projection[2][2] = - (2.0f / (zFar - zNear));
538  _projection[3][2] = - ((zFar + zNear) / (zFar - zNear));
539 
540  _projection[0][3] = 0.0f;
541  _projection[1][3] = 0.0f;
542  _projection[2][3] = 0.0f;
543  _projection[3][3] = 1.0f;
544 
546 
549 }
550 
551 bool GraphicsManager::project(float x, float y, float z, float &sX, float &sY, float &sZ) {
552  // This is our projection matrix
553  glm::mat4 proj(_projection);
554 
555 
556  // Generate the model matrix
557 
558  glm::mat4 model;
559 
560  float cPos[3];
561  float cOrient[3];
562 
563  memcpy(cPos , CameraMan.getPosition (), 3 * sizeof(float));
564  memcpy(cOrient, CameraMan.getOrientation(), 3 * sizeof(float));
565 
566  // Apply camera orientation
567  model = glm::rotate(model, Common::deg2rad(-cOrient[0]), glm::vec3(1.0f, 0.0f, 0.0f));
568  model = glm::rotate(model, Common::deg2rad(-cOrient[1]), glm::vec3(0.0f, 1.0f, 0.0f));
569  model = glm::rotate(model, Common::deg2rad(-cOrient[2]), glm::vec3(0.0f, 0.0f, 1.0f));
570 
571  // Apply camera position
572  model = glm::translate(model, glm::vec3(-cPos[0], -cPos[1], -cPos[2]));
573 
574 
575  glm::vec4 coords(x, y, z, 1);
576 
577  // Multiply them
578  glm::vec4 v(proj * model * coords);
579 
580  // Projection divide
581 
582  if (v.w == 0.0f)
583  return false;
584 
585  float divider = 1.0f / v.w;
586  v *= divider;
587 
588  // Viewport coordinates
589 
590  float view[4];
591 
592  view[0] = 0.0f;
593  view[1] = 0.0f;
594  view[2] = WindowMan.getWindowWidth();
595  view[3] = WindowMan.getWindowHeight();
596 
597 
598  sX = view[0] + view[2] * (v.x + 1.0f) / 2.0f;
599  sY = view[1] + view[3] * (v.y + 1.0f) / 2.0f;
600  sZ = (v.z + 1.0f) / 2.0f;
601 
602  sX -= view[2] / 2.0f;
603  sY -= view[3] / 2.0f;
604  return true;
605 }
606 
607 bool GraphicsManager::unproject(float x, float y,
608  float &x1, float &y1, float &z1,
609  float &x2, float &y2, float &z2) const {
610 
611  try {
612  // Generate the inverse of the model matrix
613 
614  glm::mat4 model;
615 
616  float cPos[3];
617  float cOrient[3];
618 
619  memcpy(cPos , CameraMan.getPosition (), 3 * sizeof(float));
620  memcpy(cOrient, CameraMan.getOrientation(), 3 * sizeof(float));
621 
622  // Apply camera position
623  model = glm::translate(model, glm::vec3(cPos[0], cPos[1], cPos[2]));
624 
625  // Apply camera orientation
626  model = glm::rotate(model, Common::deg2rad(cOrient[2]), glm::vec3(0.0f, 0.0f, 1.0f));
627  model = glm::rotate(model, Common::deg2rad(cOrient[1]), glm::vec3(0.0f, 1.0f, 0.0f));
628  model = glm::rotate(model, Common::deg2rad(cOrient[0]), glm::vec3(1.0f, 0.0f, 0.0f));
629 
630 
631  // Multiply with the inverse of our projection matrix
632  model *= _projectionInv;
633 
634 
635  // Coordinates at the near and far clipping planes
636  glm::vec4 coordsNear, coordsFar;
637 
639  /* With a perspective projection, the viewport runs from -1.0 to 0.0
640  * on the x and y axes, and the clipping planes are at 0.0 and 1.0. */
641 
642  const float view[4] = { 0.0f, 0.0f, (float) WindowMan.getWindowWidth(), (float) WindowMan.getWindowHeight() };
643  const float zNear = 0.0f;
644  const float zFar = 1.0f;
645 
646  coordsNear.x = ((2 * (x - view[0])) / (view[2])) - 1.0f;
647  coordsNear.y = ((2 * (y - view[1])) / (view[3])) - 1.0f;
648  coordsNear.z = (2 * zNear) - 1.0f;
649  coordsNear.w = 1.0f;
650 
651  coordsFar.x = ((2 * (x - view[0])) / (view[2])) - 1.0f;
652  coordsFar.y = ((2 * (y - view[1])) / (view[3])) - 1.0f;
653  coordsFar.z = (2 * zFar) - 1.0f;
654  coordsFar.w = 1.0f;
655 
656  } else if (_projectType == kProjectTypeOrthogonal) {
657  /* With an orthogonal projection, the viewport runs from 0.0 to width
658  * on the x axis and from 0.0 to height on the y axis (which already
659  * matches the coordinates we were given), and the clipping planes are
660  * at -clipNear and -clipFar. */
661 
662  coordsNear.x = x;
663  coordsNear.y = y;
664  coordsNear.z = -_clipNear;
665  coordsNear.w = 1.0f;
666 
667  coordsFar.x = x;
668  coordsFar.y = y;
669  coordsFar.z = -_clipFar;
670  coordsFar.w = 1.0f;
671  }
672 
673  // Unproject
674  glm::vec4 oNear(model * coordsNear);
675  glm::vec4 oFar (model * coordsFar );
676  if ((oNear.w == 0.0f) || (oFar.w == 0.0f))
677  return false; // TODO: check for close to 0.0f, not exactly 0.0f.
678 
679 
680  // And return the values
681 
682  oNear.w = 1.0f / oNear.w;
683 
684  x1 = oNear.x * oNear.w;
685  y1 = oNear.y * oNear.w;
686  z1 = oNear.z * oNear.w;
687 
688  oFar.w = 1.0f / oFar.w;
689 
690  x2 = oFar.x * oFar.w;
691  y2 = oFar.y * oFar.w;
692  z2 = oFar.z * oFar.w;
693 
694  } catch (...) {
696  return false;
697  }
698 
699  return true;
700 }
701 
703  // Increase the lock counter and make sure we don't overflow
704  const uint32 lock = _frameLock.fetch_add(1, boost::memory_order_acquire);
705  assert(lock != 0xFFFFFFFF);
706 
707  /* Wait for the frame to end, because the caller doesn't want to do
708  * updates in the middle of the frame.
709  *
710  * However, we should skip that if:
711  * - We're in the main thread, so we know we're not rendering a frame now
712  * - We want to quit anyway, so no further rendering is being done
713  * - The frame is already locked
714  */
715 
716  if (Common::isMainThread() || EventMan.quitRequested() || (lock > 0))
717  return;
718 
719  _frameEndSignal.store(false, boost::memory_order_release);
720  while (!_frameEndSignal.load(boost::memory_order_acquire));
721 }
722 
724  // Decrease the lock counter and make sure we don't underflow
725  const uint32 lock = _frameLock.fetch_sub(1, boost::memory_order_release);
726  assert(lock != 0);
727 }
728 
730  // World objects
732 
733  const std::list<Queueable *> &objects = QueueMan.getQueue(kQueueVisibleWorldObject);
734  for (std::list<Queueable *>::const_iterator o = objects.begin(); o != objects.end(); ++o)
735  static_cast<Renderable *>(*o)->calculateDistance();
736 
738  QueueMan.unlockQueue(kQueueVisibleWorldObject);
739 
740  // GUI front objects
742 
743  const std::list<Queueable *> &guiFront = QueueMan.getQueue(kQueueVisibleGUIFrontObject);
744  for (std::list<Queueable *>::const_iterator g = guiFront.begin(); g != guiFront.end(); ++g)
745  static_cast<Renderable *>(*g)->calculateDistance();
746 
749 
750  // GUI back objects
752 
753  const std::list<Queueable *> &guiBack = QueueMan.getQueue(kQueueVisibleGUIBackObject);
754  for (std::list<Queueable *>::const_iterator g = guiBack.begin(); g != guiBack.end(); ++g)
755  static_cast<Renderable *>(*g)->calculateDistance();
756 
759 }
760 
763 
764  return ++_renderableID;
765 }
766 
768  if (count == 0)
769  return;
770 
772 
773  _abandonTextures.reserve(_abandonTextures.size() + count);
774  while (count-- > 0)
775  _abandonTextures.push_back(*ids++);
776 
777  _hasAbandoned = true;
778 }
779 
781  if (count == 0)
782  return;
783 
785 
786  while (count-- > 0)
787  _abandonLists.push_back(ids++);
788 
789  _hasAbandoned = true;
790 }
791 
793  lockFrame();
794 
795  _cursor = cursor;
796 
797  unlockFrame();
798 }
799 
801  lockFrame();
802 
803  _takeScreenshot = true;
804 
805  unlockFrame();
806 }
807 
808 Renderable *GraphicsManager::getGUIObjectAt(float x, float y) const {
809  if (QueueMan.isQueueEmpty(kQueueVisibleGUIFrontObject))
810  return 0;
811 
812  // Map the screen coordinates to our OpenGL GUI screen coordinates
813  if (_scalingType == kScalingNone) {
814  x = x - (WindowMan.getWindowWidth() / 2.0f);
815  y = (WindowMan.getWindowHeight() - y) - (WindowMan.getWindowHeight() / 2.0f);
816  } else {
817  x = ((x * _guiWidth / WindowMan.getWindowWidth()) - (_guiWidth / 2.0f));
818  y = ((-1.0f * y * _guiHeight / WindowMan.getWindowHeight()) + (_guiHeight / 2.0f));
819  }
820 
821  Renderable *object = 0;
822 
824  const std::list<Queueable *> &gui = QueueMan.getQueue(kQueueVisibleGUIFrontObject);
825 
826  // Go through the GUI elements, from nearest to furthest
827  for (std::list<Queueable *>::const_iterator g = gui.begin(); g != gui.end(); ++g) {
828  Renderable &r = static_cast<Renderable &>(**g);
829 
830  if (!r.isClickable())
831  // Object isn't clickable, don't check
832  continue;
833 
834  // If the coordinates are "in" that object, return it
835  if (r.isIn(x, y)) {
836  object = &r;
837  break;
838  }
839  }
840 
842  return object;
843 }
844 
846  if (QueueMan.isQueueEmpty(kQueueVisibleWorldObject))
847  return 0;
848 
849  // Map the screen coordinates to OpenGL world screen coordinates
850  y = WindowMan.getWindowHeight() - y;
851 
852  float x1, y1, z1, x2, y2, z2;
853  if (!unproject(x, y, x1, y1, z1, x2, y2, z2))
854  return 0;
855 
856  Renderable *object = 0;
857 
859  const std::list<Queueable *> &objects = QueueMan.getQueue(kQueueVisibleWorldObject);
860 
861  for (std::list<Queueable *>::const_iterator o = objects.begin(); o != objects.end(); ++o) {
862  Renderable &r = static_cast<Renderable &>(**o);
863 
864  if (!r.isClickable())
865  // Object isn't clickable, don't check
866  continue;
867 
868  // If the line intersects with the object, return it
869  if (r.isIn(x1, y1, z1, x2, y2, z2)) {
870  object = &r;
871  break;
872  }
873  }
874 
875  QueueMan.unlockQueue(kQueueVisibleWorldObject);
876  return object;
877 }
878 
880  Renderable *object = 0;
881 
882  if ((object = getGUIObjectAt(x, y)))
883  return object;
884 
885  if ((object = getWorldObjectAt(x, y)))
886  return object;
887 
888  return 0;
889 }
890 
892  QueueMan.lockQueue(kQueueNewShader);
893  const std::list<Queueable *> &shadq = QueueMan.getQueue(kQueueNewShader);
894  if (shadq.empty()) {
895  QueueMan.unlockQueue(kQueueNewShader);
896  } else {
897  for (std::list<Queueable *>::const_iterator t = shadq.begin(); t != shadq.end(); ++t)
898  static_cast<GLContainer *>(*t)->rebuild();
899 
900  QueueMan.clearQueue(kQueueNewShader);
901  QueueMan.unlockQueue(kQueueNewShader);
902  }
903 
904  QueueMan.lockQueue(kQueueNewTexture);
905  const std::list<Queueable *> &text = QueueMan.getQueue(kQueueNewTexture);
906  if (text.empty()) {
907  QueueMan.unlockQueue(kQueueNewTexture);
908  return;
909  }
910 
911  for (std::list<Queueable *>::const_iterator t = text.begin(); t != text.end(); ++t)
912  static_cast<GLContainer *>(*t)->rebuild();
913 
914  QueueMan.clearQueue(kQueueNewTexture);
915  QueueMan.unlockQueue(kQueueNewTexture);
916 }
917 
919  WindowMan.beginScene();
920 
921  if (_fsaa > 0)
922  glEnable(GL_MULTISAMPLE_ARB);
923 
924  // Clear
925  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
926 
927  glEnable(GL_TEXTURE_2D);
928 }
929 
931  if (QueueMan.isQueueEmpty(kQueueVisibleVideo))
932  return false;
933 
934  glMatrixMode(GL_PROJECTION);
935  glLoadIdentity();
936  glScalef(2.0f / WindowMan.getWindowWidth(), 2.0f / WindowMan.getWindowHeight(), 0.0f);
937 
938  glMatrixMode(GL_MODELVIEW);
939  glLoadIdentity();
940 
941  QueueMan.lockQueue(kQueueVisibleVideo);
942  const std::list<Queueable *> &videos = QueueMan.getQueue(kQueueVisibleVideo);
943 
944  for (std::list<Queueable *>::const_iterator v = videos.begin(); v != videos.end(); ++v) {
945  glPushMatrix();
946  static_cast<Renderable *>(*v)->render(kRenderPassAll);
947  glPopMatrix();
948  }
949 
950  QueueMan.unlockQueue(kQueueVisibleVideo);
951  return true;
952 }
953 
955  if (QueueMan.isQueueEmpty(kQueueVisibleWorldObject))
956  return false;
957 
958  float cPos[3];
959  float cOrient[3];
960 
961  memcpy(cPos , CameraMan.getPosition (), 3 * sizeof(float));
962  memcpy(cOrient, CameraMan.getOrientation(), 3 * sizeof(float));
963 
964  glMatrixMode(GL_PROJECTION);
965  glLoadIdentity();
966 
967  glMultMatrixf(glm::value_ptr(_projection));
968 
969  glMatrixMode(GL_MODELVIEW);
970  glLoadIdentity();
971 
972  // Apply camera orientation
973  glRotatef(-cOrient[0], 1.0f, 0.0f, 0.0f);
974  glRotatef(-cOrient[1], 0.0f, 1.0f, 0.0f);
975  glRotatef(-cOrient[2], 0.0f, 0.0f, 1.0f);
976 
977  // Apply camera position
978  glTranslatef(-cPos[0], -cPos[1], -cPos[2]);
979 
980  _modelview = glm::mat4();
981  _modelview = glm::rotate(_modelview, Common::deg2rad(-cOrient[0]), glm::vec3(1.0f, 0.0f, 0.0f));
982  _modelview = glm::rotate(_modelview, Common::deg2rad(-cOrient[1]), glm::vec3(0.0f, 1.0f, 0.0f));
983  _modelview = glm::rotate(_modelview, Common::deg2rad(-cOrient[2]), glm::vec3(0.0f, 0.0f, 1.0f));
984  _modelview = glm::translate(_modelview, glm::vec3(-cPos[0], -cPos[1], -cPos[2]));
985 
987  const std::list<Queueable *> &objects = QueueMan.getQueue(kQueueVisibleWorldObject);
988 
990 
992 
993  // Draw opaque objects
994  for (std::list<Queueable *>::const_reverse_iterator o = objects.rbegin();
995  o != objects.rend(); ++o) {
996 
997  glPushMatrix();
998  static_cast<Renderable *>(*o)->render(kRenderPassOpaque);
999  glPopMatrix();
1000  }
1001 
1002  // Draw transparent objects
1003  for (std::list<Queueable *>::const_reverse_iterator o = objects.rbegin();
1004  o != objects.rend(); ++o) {
1005 
1006  glPushMatrix();
1007  static_cast<Renderable *>(*o)->render(kRenderPassTransparent);
1008  glPopMatrix();
1009  }
1010 
1011  QueueMan.unlockQueue(kQueueVisibleWorldObject);
1012  return true;
1013 }
1014 
1017 }
1018 
1021 }
1022 
1025 }
1026 
1027 bool GraphicsManager::renderGUI(ScalingType scalingType, QueueType guiQueue, bool disableDepthMask) {
1028  if (QueueMan.isQueueEmpty(guiQueue))
1029  return false;
1030 
1031  glDisable(GL_DEPTH_TEST);
1032  if (disableDepthMask)
1033  glDepthMask(GL_FALSE);
1034 
1035  glMatrixMode(GL_PROJECTION);
1036  glLoadIdentity();
1037 
1038  int windowWidth = WindowMan.getWindowWidth();
1039  int windowHeight = WindowMan.getWindowHeight();
1040  int rasterWidth = (scalingType == kScalingWindowSize || _guiWidth > windowWidth) ? _guiWidth : windowWidth;
1041  int rasterHeight = (scalingType == kScalingWindowSize || _guiHeight > windowHeight) ? _guiHeight : windowHeight;
1042  glScalef(2.0f / rasterWidth, 2.0f / rasterHeight, 0.0f);
1043 
1044  glMatrixMode(GL_MODELVIEW);
1045  glLoadIdentity();
1046 
1047  QueueMan.lockQueue(guiQueue);
1048  const std::list<Queueable *> &gui = QueueMan.getQueue(guiQueue);
1049 
1050  buildNewTextures();
1051 
1052  for (std::list<Queueable *>::const_reverse_iterator g = gui.rbegin();
1053  g != gui.rend(); ++g) {
1054 
1055  glPushMatrix();
1056  static_cast<Renderable *>(*g)->render(kRenderPassAll);
1057  glPopMatrix();
1058  }
1059 
1060  QueueMan.unlockQueue(guiQueue);
1061 
1062  if (disableDepthMask)
1063  glDepthMask(GL_TRUE);
1064  glEnable(GL_DEPTH_TEST);
1065  return true;
1066 }
1067 
1069  if (!_cursor)
1070  return false;
1071 
1072  buildNewTextures();
1073 
1074  glDisable(GL_DEPTH_TEST);
1075  glMatrixMode(GL_PROJECTION);
1076  glLoadIdentity();
1077  glScalef(2.0f / WindowMan.getWindowWidth(), 2.0f / WindowMan.getWindowHeight(), 0.0f);
1078  glTranslatef(- (WindowMan.getWindowWidth() / 2.0f), WindowMan.getWindowHeight() / 2.0f, 0.0f);
1079 
1080  glMatrixMode(GL_TEXTURE);
1081  glLoadIdentity();
1082 
1083  glMatrixMode(GL_MODELVIEW);
1084  glLoadIdentity();
1085 
1086  _cursor->render();
1087  glEnable(GL_DEPTH_TEST);
1088  return true;
1089 }
1090 
1092  if (QueueMan.isQueueEmpty(kQueueVisibleWorldObject))
1093  return false;
1094 
1097 
1098  float cPos[3];
1099  float cOrient[3];
1100 
1101  memcpy(cPos , CameraMan.getPosition (), 3 * sizeof(float));
1102  memcpy(cOrient, CameraMan.getOrientation(), 3 * sizeof(float));
1103 
1104  _modelview = glm::mat4();
1105  _modelview = glm::rotate(_modelview, Common::deg2rad(-cOrient[0]), glm::vec3(1.0f, 0.0f, 0.0f));
1106  _modelview = glm::rotate(_modelview, Common::deg2rad(-cOrient[1]), glm::vec3(0.0f, 1.0f, 0.0f));
1107  _modelview = glm::rotate(_modelview, Common::deg2rad(-cOrient[2]), glm::vec3(0.0f, 0.0f, 1.0f));
1108  _modelview = glm::translate(_modelview, glm::vec3(-cPos[0], -cPos[1], -cPos[2]));
1109 
1111  const std::list<Queueable *> &objects = QueueMan.getQueue(kQueueVisibleWorldObject);
1112 
1113  buildNewTextures();
1114 
1116 
1117  glm::mat4 ident;
1118  RenderMan.clear();
1119  for (std::list<Queueable *>::const_reverse_iterator o = objects.rbegin();
1120  o != objects.rend(); ++o) {
1121  static_cast<Renderable *>(*o)->queueRender(ident);
1122  }
1123  RenderMan.sort();
1124  RenderMan.render();
1125 
1126  QueueMan.unlockQueue(kQueueVisibleWorldObject);
1127  return true;
1128 }
1129 
1132 }
1133 
1136 }
1137 
1140 }
1141 
1142 bool GraphicsManager::renderGUIShader(ScalingType scalingType, QueueType guiQueue, bool disableDepthMask) {
1143  if (QueueMan.isQueueEmpty(guiQueue))
1144  return false;
1145 
1146  glDisable(GL_DEPTH_TEST);
1147  if (disableDepthMask)
1148  glDepthMask(GL_FALSE);
1149 
1150  int windowWidth = WindowMan.getWindowWidth();
1151  int windowHeight = WindowMan.getWindowHeight();
1152  int rasterWidth = (scalingType == kScalingWindowSize || _guiWidth > windowWidth) ? _guiWidth : windowWidth;
1153  int rasterHeight = (scalingType == kScalingWindowSize || _guiHeight > windowHeight) ? _guiHeight : windowHeight;
1154  _projection = glm::scale(glm::mat4(), glm::vec3(2.0f / rasterWidth, 2.0f / rasterHeight, 0.0f));
1155 
1156  QueueMan.lockQueue(guiQueue);
1157  const std::list<Queueable *> &gui = QueueMan.getQueue(guiQueue);
1158  _modelview = glm::mat4();
1159 
1160  buildNewTextures();
1161 
1162  glm::mat4 ident;
1163  for (std::list<Queueable *>::const_reverse_iterator g = gui.rbegin();
1164  g != gui.rend(); ++g) {
1165  static_cast<Renderable *>(*g)->renderImmediate(ident);
1166  }
1167 
1168  QueueMan.unlockQueue(guiQueue);
1169 
1170  if (disableDepthMask)
1171  glDepthMask(GL_TRUE);
1172  glEnable(GL_DEPTH_TEST);
1173  return true;
1174 }
1175 
1177  if (!_cursor)
1178  return false;
1179 
1180  buildNewTextures();
1181 
1182  glDisable(GL_DEPTH_TEST);
1183  glMatrixMode(GL_PROJECTION);
1184  glLoadIdentity();
1185  glScalef(2.0f / WindowMan.getWindowWidth(), 2.0f / WindowMan.getWindowHeight(), 0.0f);
1186  glTranslatef(- (WindowMan.getWindowWidth() / 2.0f), WindowMan.getWindowHeight() / 2.0f, 0.0f);
1187 
1188  glMatrixMode(GL_TEXTURE);
1189  glLoadIdentity();
1190 
1191  glMatrixMode(GL_MODELVIEW);
1192  glLoadIdentity();
1193 
1194  _cursor->render();
1195  glEnable(GL_DEPTH_TEST);
1196  return true;
1197 }
1198 
1200  WindowMan.endScene();
1201 
1202  if (_takeScreenshot) {
1204  _takeScreenshot = false;
1205  }
1206 
1207  _fpsCounter->finishedFrame();
1208 
1209  if (_fsaa > 0)
1210  glDisable(GL_MULTISAMPLE_ARB);
1211 }
1212 
1215 
1216  cleanupAbandoned();
1217 
1218  if (EventMan.quitRequested() || (_frameLock.load(boost::memory_order_acquire) > 0)) {
1219  _frameEndSignal.store(true, boost::memory_order_release);
1220 
1221  return;
1222  }
1223 
1224  beginScene();
1225 
1226  if (playVideo()) {
1227  endScene();
1228  return;
1229  }
1230 
1231  if (_rendererExperimental) {
1237  } else {
1238  renderGUIBack();
1239  renderWorld();
1240  renderGUIFront();
1241  renderGUIConsole();
1242  renderCursor();
1243  }
1244 
1245  endScene();
1246 
1247  _frameEndSignal.store(true, boost::memory_order_release);
1248 }
1249 
1250 const glm::mat4 &GraphicsManager::getProjectionMatrix() const {
1251  return _projection;
1252 }
1253 
1255  return _projection;
1256 }
1257 
1259  return _projectionInv;
1260 }
1261 
1262 const glm::mat4 &GraphicsManager::getModelviewMatrix() const {
1263  return _modelview;
1264 }
1265 
1267  return _modelview;
1268 }
1269 
1271  return _modelviewInv;
1272 }
1273 
1276 }
1277 
1280 }
1281 
1284 }
1285 
1288 }
1289 
1292 }
1293 
1295  QueueMan.lockQueue(kQueueGLContainer);
1296 
1297  const std::list<Queueable *> &cont = QueueMan.getQueue(kQueueGLContainer);
1298  for (std::list<Queueable *>::const_iterator c = cont.begin(); c != cont.end(); ++c)
1299  static_cast<GLContainer *>(*c)->rebuild();
1300 
1301  QueueMan.unlockQueue(kQueueGLContainer);
1302 }
1303 
1305  QueueMan.lockQueue(kQueueGLContainer);
1306 
1307  const std::list<Queueable *> &cont = QueueMan.getQueue(kQueueGLContainer);
1308  for (std::list<Queueable *>::const_iterator c = cont.begin(); c != cont.end(); ++c)
1309  static_cast<GLContainer *>(*c)->destroy();
1310 
1311  QueueMan.unlockQueue(kQueueGLContainer);
1312 }
1313 
1315  // Destroying all GL containers, since we need to
1316  // reload/rebuild them anyway when the context is recreated
1318 }
1319 
1321  // Reintroduce glew to the surface
1322  GLenum glewErr = glewInit();
1323  if (glewErr != GLEW_OK)
1324  throw Common::Exception("Failed initializing glew: %s", glewGetErrorString(glewErr));
1325 
1326  // Reintroduce OpenGL to the surface
1327  setupScene();
1328 
1329  // And reload/rebuild all GL containers
1331 
1332  // Wait for everything to settle
1333  RequestMan.sync();
1334 }
1335 
1337  if (!_hasAbandoned)
1338  return;
1339 
1341 
1342  if (!_abandonTextures.empty())
1343  glDeleteTextures(_abandonTextures.size(), &_abandonTextures[0]);
1344 
1345  for (std::list<ListID>::iterator l = _abandonLists.begin(); l != _abandonLists.end(); ++l)
1346  glDeleteLists(*l, 1);
1347 
1348  _abandonTextures.clear();
1349  _abandonLists.clear();
1350 
1351  _hasAbandoned = false;
1352 }
1353 
1354 void GraphicsManager::notifyResized(int UNUSED(oldWidth), int UNUSED(oldHeight),
1355  int UNUSED(newWidth), int UNUSED(newHeight)) {
1356 
1357  destroyContext();
1358  rebuildContext();
1359 }
1360 
1361 } // End of namespace Graphics
1362 
1363 static glm::mat4 inverse(const glm::mat4 &m) {
1364  float A0 = (m[0][0] * m[1][1]) - (m[0][1] * m[1][0]);
1365  float A1 = (m[0][0] * m[1][2]) - (m[0][2] * m[1][0]);
1366  float A2 = (m[0][0] * m[1][3]) - (m[0][3] * m[1][0]);
1367  float A3 = (m[0][1] * m[1][2]) - (m[0][2] * m[1][1]);
1368  float A4 = (m[0][1] * m[1][3]) - (m[0][3] * m[1][1]);
1369  float A5 = (m[0][2] * m[1][3]) - (m[0][3] * m[1][2]);
1370  float B0 = (m[2][0] * m[3][1]) - (m[2][1] * m[3][0]);
1371  float B1 = (m[2][0] * m[3][2]) - (m[2][2] * m[3][0]);
1372  float B2 = (m[2][0] * m[3][3]) - (m[2][3] * m[3][0]);
1373  float B3 = (m[2][1] * m[3][2]) - (m[2][2] * m[3][1]);
1374  float B4 = (m[2][1] * m[3][3]) - (m[2][3] * m[3][1]);
1375  float B5 = (m[2][2] * m[3][3]) - (m[2][3] * m[3][2]);
1376 
1377  float det = A0*B5 - A1*B4 + A2*B3 + A3*B2 - A4*B1 + A5*B0;
1378 
1379  if (fabs(det) <= 0.00001f)
1380  return glm::mat4();
1381 
1382  det = 1.0f / det;
1383  glm::mat4 t;
1384 
1385  t[0][0] = (m[1][1] * B5 - m[1][2] * B4 + m[1][3] * B3) * det;
1386  t[1][0] = (m[1][2] * B2 - m[1][3] * B1 - m[1][0] * B5) * det;
1387  t[2][0] = (m[1][0] * B4 - m[1][1] * B2 + m[1][3] * B0) * det;
1388  t[3][0] = (m[1][1] * B1 - m[1][0] * B3 - m[1][2] * B0) * det;
1389  t[0][1] = (m[0][2] * B4 - m[0][3] * B3 - m[0][1] * B5) * det;
1390  t[1][1] = (m[0][0] * B5 - m[0][2] * B2 + m[0][3] * B1) * det;
1391  t[2][1] = (m[0][1] * B2 - m[0][3] * B0 - m[0][0] * B4) * det;
1392  t[3][1] = (m[0][0] * B3 - m[0][1] * B1 + m[0][2] * B0) * det;
1393  t[0][2] = (m[3][1] * A5 - m[3][2] * A4 + m[3][3] * A3) * det;
1394  t[1][2] = (m[3][2] * A2 - m[3][3] * A1 - m[3][0] * A5) * det;
1395  t[2][2] = (m[3][0] * A4 - m[3][1] * A2 + m[3][3] * A0) * det;
1396  t[3][2] = (m[3][1] * A1 - m[3][0] * A3 - m[3][2] * A0) * det;
1397  t[0][3] = (m[2][2] * A4 - m[2][3] * A3 - m[2][1] * A5) * det;
1398  t[1][3] = (m[2][0] * A5 - m[2][2] * A2 + m[2][3] * A1) * det;
1399  t[2][3] = (m[2][1] * A2 - m[2][3] * A0 - m[2][0] * A4) * det;
1400  t[3][3] = (m[2][0] * A3 - m[2][1] * A1 + m[2][2] * A0) * det;
1401 
1402  return t;
1403 }
void lockFrame()
Increase the frame lock counter, disabling all frame rendering.
Definition: graphics.cpp:702
bool isGL3() const
Are we currently running an OpenGL 3.x context?
Definition: graphics.cpp:1290
A newly created texture.
Definition: types.h:73
bool _supportMultipleTextures
Do we have support for multiple textures?
Definition: graphics.h:200
Common::Mutex _abandonMutex
A mutex protecting abandoned structures.
Definition: graphics.h:248
static void outputGLDebug(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
Definition: graphics.cpp:267
Generic image decoder interface.
bool takeScreenshot()
Saves a screenshot to a file.
Definition: screenshot.cpp:110
Inter-thread request events.
Make the render window display our icon.
Cursor * _cursor
The current cursor.
Definition: graphics.h:236
size_t getMultipleTextureCount() const
Return the number of texture units for multiple textures.
Definition: graphics.cpp:195
Only render transparent parts.
Definition: types.h:99
The global graphics manager.
Behavior that has been marked for deprecation.
Definition: debugman.h:71
An object containing shader information.
Definition: types.h:85
"GGLAPI", OpenGL debug message generated by the GL.
Definition: debugman.h:48
uint32 getFPS() const
How many frames per second to we render at the moments?
Definition: graphics.cpp:203
ProjectType _projectType
Definition: graphics.h:210
Common::ScopedPtr< FPSCounter > _fpsCounter
Counts the current frames per seconds value.
Definition: graphics.h:220
The graphics manager.
Definition: graphics.h:59
An object containing OpenGL structures.
Definition: types.h:84
void init()
Initialize the graphics subsystem.
Definition: graphics.cpp:122
"GGLWindow", OpenGL debug message generated by the windowing system.
Definition: debugman.h:49
Template specialization for a MainThreadFunctor returning void.
Definition: types.h:323
bool destroyThread()
Definition: thread.cpp:64
The global config manager.
#define SurfaceMan
Shortcut for accessing the shader manager.
Definition: surfaceman.h:74
A visible Debug Console object, in front of the Front GUI.
Definition: types.h:81
bool isMainThread()
Returns true if called from the main thread, false otherwise.
Definition: threads.cpp:54
#define A3
Definition: bink.cpp:1527
Mathematical helpers.
Camera management.
uint32 _lastSampled
Timestamp used to advance animations.
Definition: graphics.h:222
A visible GUI object, in front of the world objects.
Definition: types.h:79
Renderable * getObjectAt(float x, float y)
Get the object at this screen position.
Definition: graphics.cpp:879
A cursor.
bool _ready
Was the graphics subsystem successfully initialized?
Definition: graphics.h:192
bool supportMultipleTextures() const
Do we have support for multiple textures?
Definition: graphics.cpp:191
const glm::mat4 & getModelviewInverseMatrix() const
Return the inverse modelview matrix (camera view).
Definition: graphics.cpp:1270
bool setupSDLGL()
Setup SDL + OpenGL renderer.
Definition: graphics.cpp:242
#define ARRAYSIZE(x)
Macro which determines the number of entries in a fixed size array.
Definition: util.h:131
Common::Mutex _renderableIDMutex
The mutex to govern renderable ID creation.
Definition: graphics.h:241
bool renderGUIShader(ScalingType scalingType, QueueType guiQueue, bool disableDepthMask)
Definition: graphics.cpp:1142
Screenshot writing.
GLuint TextureID
Definition: types.h:45
glm::mat4 _projectionInv
The inverse of our projection matrix.
Definition: graphics.h:229
void resumeAnimations()
Resume animation thread.
Definition: graphics.cpp:1278
#define QueueMan
Shortcut for accessing the graphics queue manager.
Definition: queueman.h:71
#define A2
Definition: bink.cpp:1526
Exception that provides a stack of explanations.
Definition: error.h:36
glm::mat4 _perspective
3D perspective projection matrix.
Definition: graphics.h:224
Counting FPS.
A container of OpenGL elements.
void exceptionDispatcherWarning(const char *s,...)
Exception dispatcher that prints the exception as a warning, and adds another reason on top...
Definition: error.cpp:158
A class counting frames per second.
Definition: fpscounter.h:34
uint32 _renderableID
The last ID given to a renderable.
Definition: graphics.h:240
An abstract cursor.
Definition: cursor.h:31
The notification manager, handling all notifications.
glm::mat4 _orthoInv
The inverse of our othographical matrix.
Definition: graphics.h:227
WindowManager::RenderType _renderType
Definition: graphics.h:203
void unregisterModel(Model *model)
Remove a model from the processing pool.
Basic exceptions to throw.
virtual void renderImmediate(const glm::mat4 &parentTransform)
For shader based systems, don&#39;t sort anything, render this right_now.
Definition: renderable.h:59
Threading system helpers.
virtual void queueRender(const glm::mat4 &parentTransform)
Queue the object for later rendering.
Definition: renderable.h:62
void notifyResized(int oldWidth, int oldHeight, int newWidth, int newHeight)
Definition: graphics.cpp:1354
glm::mat4 _perspectiveInv
The inverse of our perspective matrix.
Definition: graphics.h:225
Render all parts.
Definition: types.h:100
bool createThread(const UString &name="")
Definition: thread.cpp:44
The debug manager, managing debug channels.
GLuint ListID
Definition: types.h:46
The global shader manager.
#define ConfigMan
Shortcut for accessing the config manager.
Definition: configman.h:176
#define UNUSED(x)
Definition: system.h:170
Utility templates and functions.
QueueType
Definition: types.h:71
Basic xoreos version information.
#define DECLARE_SINGLETON(T)
Note that you need to use this macro from the global namespace.
Definition: singleton.h:122
ScalingType _scalingType
Definition: graphics.h:216
void registerAnimatedModel(Aurora::Model *model)
Register a model with the animation thread.
Definition: graphics.cpp:1282
The global events manager.
bool unproject(float x, float y, float &x1, float &y1, float &z1, float &x2, float &y2, float &z2) const
Map the given screen coordinates onto a line in world space.
Definition: graphics.cpp:607
void setGUISize(int guiWidth, int guiHeight)
Configure the original size of the GUI.
Definition: graphics.cpp:445
"GGLApp", OpenGL debug message generated by the application.
Definition: debugman.h:52
DebugGLType
Types of OpenGL debug messages.
Definition: debugman.h:69
bool needManualDeS3TC() const
Do we need to do manual S3TC DXTn decompression?
Definition: graphics.cpp:187
A visible object in 3D space.
Definition: types.h:75
Events that generated an error.
Definition: debugman.h:70
bool _takeScreenshot
Should screenshot be taken?
Definition: graphics.h:238
The global shader material manager.
The global shader surface manager.
The global mesh manager.
std::list< ListID > _abandonLists
Abandoned lists.
Definition: graphics.h:246
void recalculateObjectDistances()
Recalculate all object distances to the camera and resort the objects.
Definition: graphics.cpp:729
#define MaterialMan
Shortcut for accessing the shader material manager.
Definition: materialman.h:74
void registerModel(Model *model)
Add a model to the processing pool.
StackException Exception
Definition: error.h:59
bool project(float x, float y, float z, float &sX, float &sY, float &sZ)
Map the given world coordinates onto screen coordinates.
Definition: graphics.cpp:551
virtual void render()=0
Render the cursor.
void perspective(float fovy, float aspect, float zNear, float zFar)
Set up a projection matrix.
Definition: graphics.cpp:467
The graphics queue manager.
void unregisterAnimatedModel(Aurora::Model *model)
Unregister a model from the animation thread.
Definition: graphics.cpp:1286
A currently playing video.
Definition: types.h:83
void warning(const char *s,...)
Definition: util.cpp:33
virtual bool isIn(float x, float y) const
Is that point within the object?
Definition: renderable.cpp:127
void takeScreenshot()
Take a screenshot.
Definition: graphics.cpp:800
void flush()
Apply changes to position and geometry of all models in the processing pool.
int _fsaa
Current FSAA settings.
Definition: graphics.h:205
glm::mat4 _projection
Our projection matrix.
Definition: graphics.h:228
Behavior that is undefined according to the specification.
Definition: debugman.h:72
bool renderGUI(ScalingType scalingType, QueueType guiQueue, bool disableDepthMask)
Definition: graphics.cpp:1027
Convenience class that locks a mutex on creation and unlocks it on destruction.
Definition: mutex.h:71
#define DebugMan
Shortcut for accessing the debug manager.
Definition: debugman.h:195
#define EventMan
Shortcut for accessing the events manager.
Definition: events.h:210
uint32 createRenderableID()
Create a new unique renderable ID.
Definition: graphics.cpp:761
void ortho(float left, float right, float bottom, float top, float zNear, float zFar)
Set up an orthogonal projection matrix.
Definition: graphics.cpp:521
glm::mat4 _modelview
Our base modelview matrix (i.e camera view).
Definition: graphics.h:230
Render queue manager.
#define MeshMan
Shortcut for accessing the shader manager.
Definition: meshman.h:74
An object that can be displayed by the graphics manager.
Definition: renderable.h:42
bool setFSAA(int level)
Set the FSAA settings.
Definition: graphics.cpp:207
#define WindowMan
Shortcut for accessing the window manager.
Definition: windowman.h:137
#define A1
Definition: bink.cpp:1525
DebugChannel
All debug channels.
Definition: debugman.h:41
void unlockFrame()
Decrease the frame lock counter, potentially re-enabling frame rendering.
Definition: graphics.cpp:723
void setCursor(Cursor *cursor=0)
Set the current cursor.
Definition: graphics.cpp:792
void enforceMainThread()
Throws an Exception if called from a non-main thread.
Definition: threads.cpp:60
boost::atomic< bool > _frameEndSignal
Definition: graphics.h:234
Renderable * getWorldObjectAt(float x, float y) const
Definition: graphics.cpp:845
const glm::mat4 & getProjectionInverseMatrix() const
Return the inverse screen projection view matrix.
Definition: graphics.cpp:1258
"GGLOther", OpenGL debug message generated by other sources.
Definition: debugman.h:53
#define ShaderMan
Shortcut for accessing the shader manager.
Definition: shader.h:293
uint32_t uint32
Definition: types.h:204
bool _rendererExperimental
Should we use the experimental shader based renderer?
Definition: graphics.h:196
static glm::mat4 inverse(const glm::mat4 &m)
Definition: graphics.cpp:1363
const glm::mat4 & getModelviewMatrix() const
Return the current modelview matrix (camera view).
Definition: graphics.cpp:1262
Types of events that do not fit any of the ones listed above.
Definition: debugman.h:75
Renderable * getGUIObjectAt(float x, float y) const
Definition: graphics.cpp:808
bool ready() const
Was the graphics subsystem successfully initialized?
Definition: graphics.cpp:183
void deinit()
Deinitialize the graphics subsystem.
Definition: graphics.cpp:161
#define RequestMan
Shortcut for accessing the request manager.
Definition: requests.h:127
#define CameraMan
Shortcut for accessing the camera manager.
Definition: camera.h:83
void abandon(TextureID *ids, uint32 count)
Abandon these textures.
Definition: graphics.cpp:767
Use of extensions or shaders in a way that is highly vendor-specific.
Definition: debugman.h:74
void setPerspective(float viewAngle, float clipNear, float clipFar)
Change the perspective projection matrix.
Definition: graphics.cpp:450
glm::mat4 _ortho
Orthographical projection matrix.
Definition: graphics.h:226
int getCurrentFSAA() const
Return the current FSAA level.
Definition: graphics.cpp:199
const glm::mat4 & getProjectionMatrix() const
Return the current screen projection view matrix.
Definition: graphics.cpp:1250
void pauseAnimations()
Pause animation thread.
Definition: graphics.cpp:1274
void setGUIScale(ScalingType scaling)
Configure scaling type for the GUI.
Definition: graphics.cpp:441
boost::atomic< uint32 > _frameLock
Definition: graphics.h:233
bool _needManualDeS3TC
Do we need to do manual S3TC DXTn decompression?
Definition: graphics.h:199
"GGL3rd", OpenGL debug message generated by third party middleware.
Definition: debugman.h:51
A visible GUI object, behind the world objects.
Definition: types.h:80
static float deg2rad(float deg)
Definition: maths.h:97
An object that can be displayed by the graphics manager.
A functor for a function that needs to be called in the main thread.
Definition: types.h:298
bool _debugGL
Should we create an OpenGL debug context?
Definition: graphics.h:194
void renderScene()
Render one complete frame of the scene.
Definition: graphics.cpp:1213
void setOrthogonal(float clipNear, float clipFar)
Change the projection matrix to be orthogonal.
Definition: graphics.cpp:505
#define A4
Definition: bink.cpp:1528
"GGLShader", OpenGL debug message generated by the shader compiler.
Definition: debugman.h:50
bool _hasAbandoned
Do we have abandoned textures/lists?
Definition: graphics.h:243
size_t _multipleTextureCount
The number of texture units for multiple textures.
Definition: graphics.h:201
void setCullFace(bool enabled, GLenum mode=GL_BACK)
Enable/Disable face culling.
Definition: graphics.cpp:422
Only render opaque parts.
Definition: types.h:98
bool isClickable() const
Is the object clickable?
Definition: renderable.cpp:90
PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D
Definition: graphics.cpp:71
glm::mat4 _modelviewInv
The inverse of our modelview matrix.
Definition: graphics.h:231
virtual void render(RenderPass pass)=0
Render the object.
std::vector< TextureID > _abandonTextures
Abandoned textures.
Definition: graphics.h:245
Aurora::AnimationThread _animationThread
Definition: graphics.h:250
Implementation-dependent performance warnings.
Definition: debugman.h:73
#define RenderMan
Shortcut for accessing the render manager.
Definition: renderman.h:84