Blue Brain BioExplorer
BaseWindow.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2017, EPFL/Blue Brain Project
3  *
4  * The Blue Brain BioExplorer is a tool for scientists to extract and analyse
5  * scientific data from visualization
6  *
7  * This file is part of Blue Brain BioExplorer <https://github.com/BlueBrain/BioExplorer>
8  *
9  * This program is free software: you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License as published by the Free Software
11  * Foundation, either version 3 of the License, or (at your option) any later
12  * version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
23 #include "BaseWindow.h"
24 
25 #include <platform/core/Core.h>
35 
36 #include <assert.h>
37 
38 #ifdef __APPLE__
39 #include "GLUT/glut.h"
40 #include <unistd.h>
41 #else
42 #include "GL/glut.h"
43 #include <GL/freeglut_ext.h>
44 #endif
45 
46 namespace
47 {
48 const int GLUT_WHEEL_SCROLL_UP = 3;
49 const int GLUT_WHEEL_SCROLL_DOWN = 4;
50 } // namespace
51 
52 namespace core
53 {
54 uint64_t currentFrame = 0;
55 uint64_t maxFrame = 0;
56 
57 void runGLUT()
58 {
59  glutMainLoop();
60 }
61 
62 void initGLUT(int* ac, const char** av)
63 {
64  glutInit(ac, (char**)av);
65  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
66 }
67 
68 // ------------------------------------------------------------------
69 // glut event handlers
70 // ------------------------------------------------------------------
71 void glut3dReshape(int x, int y)
72 {
73  if (BaseWindow::_activeWindow)
74  BaseWindow::_activeWindow->reshape(Vector2i(x, y));
75 }
76 
77 void glut3dDisplay(void)
78 {
79  if (BaseWindow::_activeWindow)
80  {
81  BaseWindow::_activeWindow->display();
82  }
83 }
84 
85 void glut3dKeyboard(unsigned char key, int x, int y)
86 {
87  if (BaseWindow::_activeWindow)
88  BaseWindow::_activeWindow->keypress(key, Vector2i(x, y));
89 }
90 void glut3dSpecial(int key, int x, int y)
91 {
92  if (BaseWindow::_activeWindow)
93  BaseWindow::_activeWindow->specialkey(key, Vector2i(x, y));
94 }
95 
96 void glut3dIdle(void)
97 {
98  if (BaseWindow::_activeWindow)
99  BaseWindow::_activeWindow->idle();
100 }
101 void glut3dMotionFunc(int x, int y)
102 {
103  if (BaseWindow::_activeWindow)
104  BaseWindow::_activeWindow->motion(Vector2i(x, y));
105 }
106 
107 void glut3dMouseFunc(int whichButton, int released, int x, int y)
108 {
109  if (BaseWindow::_activeWindow)
110  BaseWindow::_activeWindow->mouseButton(whichButton, released, Vector2i(x, y));
111 }
112 
113 void glut3dPassiveMouseFunc(int x, int y)
114 {
115  if (BaseWindow::_activeWindow)
116  BaseWindow::_activeWindow->passiveMotion(Vector2i(x, y));
117 }
118 
119 // ------------------------------------------------------------------
120 // Base window
121 // ------------------------------------------------------------------
123 BaseWindow* BaseWindow::_activeWindow = nullptr;
124 
126  : _core(core)
127  , _lastMousePos(-1, -1)
128  , _currMousePos(-1, -1)
129  , _lastButtonState(0)
130  , _currButtonState(0)
131  , _currModifiers(0)
132  , _frameBufferMode(frameBufferMode)
133  , _windowID(-1)
134  , _windowSize(-1, -1)
135  , _displayHelp(false)
136  , _fullScreen(false)
137 {
138  const auto motionSpeed = _core.getCameraManipulator().getMotionSpeed();
139  CORE_INFO("Camera :" << _core.getEngine().getCamera());
140  CORE_INFO("Motion speed :" << motionSpeed);
141 
143  if (rp.getAccumulationType() == AccumulationType::ai_denoised)
145 
146  _rendererTypes = _core.getEngine().getRendererTypes();
147 }
148 
150 
151 void BaseWindow::mouseButton(const int button, const bool released, const Vector2i& pos)
152 {
153  if (pos != _currMousePos)
154  motion(pos);
156 
157  if (released)
158  _currButtonState = _currButtonState & ~(1 << button);
159  else
160  _currButtonState = _currButtonState | (1 << button);
161  _currModifiers = glutGetModifiers();
162 
163  auto& manipulator = _core.getCameraManipulator();
164 
165  if (_currModifiers & GLUT_ACTIVE_SHIFT && released)
166  {
167  const auto& result =
168  _core.getEngine().getRenderer().pick({pos.x / float(_windowSize.x), 1.f - pos.y / float(_windowSize.y)});
170  if (result.hit)
171  {
172  _core.getEngine().getCamera().setTarget(result.pos);
173  // updates position based on new target and current rotation
174  manipulator.rotate(result.pos, 0, 0, AbstractManipulator::AxisMode::localY);
175  }
176  }
177 
178  if (button == GLUT_WHEEL_SCROLL_UP || button == GLUT_WHEEL_SCROLL_DOWN)
179  {
180  // Wheel events are reported twice like a button click (press + release)
181  if (released)
182  return;
183  const auto delta = (button == GLUT_WHEEL_SCROLL_UP) ? 1 : -1;
184  manipulator.wheel(pos, delta);
185  }
186 }
187 
188 void BaseWindow::motion(const Vector2i& pos)
189 {
190  _currMousePos = pos;
192  {
193  // some button got pressed; reset 'old' pos to new pos.
196  }
197 
198  auto& manipulator = _core.getCameraManipulator();
199 
200  if ((_currButtonState == (1 << GLUT_RIGHT_BUTTON)) ||
201  ((_currButtonState == (1 << GLUT_LEFT_BUTTON)) && (_currModifiers & GLUT_ACTIVE_ALT)))
202  {
203  manipulator.dragRight(_currMousePos, _lastMousePos);
204  }
205  else if ((_currButtonState == (1 << GLUT_MIDDLE_BUTTON)) ||
206  ((_currButtonState == (1 << GLUT_LEFT_BUTTON)) && (_currModifiers & GLUT_ACTIVE_CTRL)))
207  {
208  manipulator.dragMiddle(_currMousePos, _lastMousePos);
209  }
210  else if (_currButtonState == (1 << GLUT_LEFT_BUTTON))
211  {
212  manipulator.dragLeft(_currMousePos, _lastMousePos);
213  }
214 
216 }
217 
219 {
220  _mouse = pos;
221 }
222 
224 {
225  usleep(1000);
226 }
227 
228 void BaseWindow::reshape(const Vector2i& newSize)
229 {
230  _windowSize = newSize;
231 
232  auto& applicationParameters = _core.getParametersManager();
233  applicationParameters.getApplicationParameters().setWindowSize(_windowSize);
234 }
235 
237 {
238  _activeWindow = this;
239  glutSetWindow(_windowID);
240 }
241 
243 {
244  glutPostRedisplay();
245 }
246 
248 {
250  if (windowSize != _windowSize)
251  glutReshapeWindow(windowSize.x, windowSize.y);
252 
253  _timer.start();
254 
255  const auto& camera = _core.getEngine().getCamera();
256  _renderInput.windowSize = windowSize;
257  _renderInput.position = camera.getPosition();
258  _renderInput.orientation = camera.getOrientation();
259  _renderInput.target = camera.getTarget();
260 
261  const auto& renderer = _core.getEngine().getRenderer();
262  const auto maxAccumFrames = renderer.getMaxAccumFrames();
263 
264  const auto& fb = _core.getEngine().getFrameBuffer();
265  if (fb.numAccumFrames() < maxAccumFrames)
267  else
268  _core.commit();
269 
270  GLenum format = GL_RGBA;
272  {
274  format = GL_BGRA;
275  break;
277  format = GL_RGB;
278  break;
279  default:
280  format = GL_RGBA;
281  }
282 
283  GLenum type = GL_FLOAT;
284  GLvoid* buffer = nullptr;
285  switch (_frameBufferMode)
286  {
288  type = GL_UNSIGNED_BYTE;
289  buffer = _renderOutput.colorBuffer.data();
290  break;
292  {
293  type = GL_FLOAT;
294  // format = GL_BGRA;
295  format = GL_RGBA;
296  buffer = _renderOutput.floatBuffer.data();
297  break;
298  }
300  format = GL_LUMINANCE;
301  buffer = _renderOutput.floatBuffer.data();
302  break;
303  default:
304  glClearColor(0.f, 0.f, 0.f, 1.f);
305  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
306  }
307 
308  if (buffer)
309  glDrawPixels(_windowSize.x, _windowSize.y, format, type, buffer);
310 
311  const auto time = std::chrono::steady_clock::now();
312  const uint64_t millisecondsElapsed = std::chrono::duration_cast<std::chrono::milliseconds>(time - _chrono).count();
313  if (millisecondsElapsed < _hintDelay)
314  _renderBitmapString(0.f, -0.9f, _hintMessage);
315  else
316  _hintMessage = "";
317 
318  if (_displayHelp)
319  {
320  auto& keyHandler = _core.getKeyboardHandler();
321  std::string help;
322  for (const auto& value : keyHandler.help())
323  help += value + "\n";
324  _renderBitmapString(0.f, 0.8f, help);
325  }
326 
327  _timer.stop();
328 
329  glutSwapBuffers();
330 
331  clearPixels();
332 
333  forceRedraw();
334 }
335 
337 {
338  glClearColor(0.f, 0.f, 0.f, 1.f);
339  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
340 }
341 
342 void BaseWindow::drawPixels(const int* framebuffer)
343 {
344  glDrawPixels(_windowSize.x, _windowSize.y, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
345  glutSwapBuffers();
346 }
347 
348 void BaseWindow::drawPixels(const Vector3f* framebuffer)
349 {
350  glDrawPixels(_windowSize.x, _windowSize.y, GL_RGBA, GL_FLOAT, framebuffer);
351  glutSwapBuffers();
352 }
353 
354 void BaseWindow::_setTitle(const char* title)
355 {
356  assert(_windowID >= 0);
357  glutSetWindow(_windowID);
358  glutSetWindowTitle(title);
359 }
360 
361 void BaseWindow::create(const char* title, const size_t width, const size_t height)
362 {
363  glutInitWindowSize(width, height);
364  _windowID = glutCreateWindow(title);
365  _activeWindow = this;
366  glutDisplayFunc(glut3dDisplay);
367  glutReshapeFunc(glut3dReshape);
368  glutKeyboardFunc(glut3dKeyboard);
369  glutSpecialFunc(glut3dSpecial);
370  glutMotionFunc(glut3dMotionFunc);
371  glutMouseFunc(glut3dMouseFunc);
372  glutPassiveMotionFunc(glut3dPassiveMouseFunc);
373  glutIdleFunc(glut3dIdle);
374 
376 }
377 
378 void BaseWindow::keypress(const char key, const Vector2f&)
379 {
380  switch (key)
381  {
382  case 'h':
384  break;
385  case '$':
386  _setHint("My mind won't fit on a server somewhere I could never afford");
387  break;
388  case '*':
389  _setHint("You can't download the sun. You'll never download me");
390  break;
391  case 27:
392  case 'Q':
393 #ifdef __APPLE__
394  exit(0);
395 #else
396  glutLeaveMainLoop();
397 #endif
398  break;
399  default:
400  auto& kh = _core.getKeyboardHandler();
401  kh.handleKeyboardShortcut(key);
402  if (_hintMessage.empty())
403  _setHint(kh.getKeyboardShortcutDescription(key));
404  }
405 
406  _core.getEngine().commit();
407 }
408 
409 void BaseWindow::specialkey(const int key, const Vector2f&)
410 {
411  switch (key)
412  {
413  case GLUT_KEY_LEFT:
415  break;
416  case GLUT_KEY_RIGHT:
418  break;
419  case GLUT_KEY_UP:
421  break;
422  case GLUT_KEY_DOWN:
424  break;
425  case GLUT_KEY_F11:
426  if (_fullScreen)
427  glutPositionWindow(_windowPosition.x, _windowPosition.y);
428  else
429  {
430  _windowPosition.x = glutGet((GLenum)GLUT_WINDOW_X);
431  _windowPosition.y = glutGet((GLenum)GLUT_WINDOW_Y);
432  glutFullScreen();
433  }
435  break;
436  }
437 }
438 
440 {
441  auto& keyHandler = _core.getKeyboardHandler();
442  keyHandler.registerKeyboardShortcut('z', "Switch between depth and color buffers",
443  std::bind(&BaseWindow::_toggleFrameBuffer, this));
444  keyHandler.registerKeyboardShortcut('n', "Next renderer type", std::bind(&BaseWindow::_toggleRendererType, this));
445  keyHandler.registerKeyboardShortcut('l', "Toggle head light", std::bind(&BaseWindow::_toggleHeadLight, this));
446 }
447 
448 #ifdef __APPLE__
449 void BaseWindow::_renderBitmapString(const float, const float, const std::string&) {}
450 #else
451 void BaseWindow::_renderBitmapString(const float x, const float y, const std::string& text)
452 {
453  const unsigned char* msg = reinterpret_cast<const unsigned char*>(text.c_str());
454  const auto font = GLUT_BITMAP_HELVETICA_18;
455  const float normalizeTextLength =
456  static_cast<float>(glutBitmapLength(font, msg)) / static_cast<float>(_windowSize.x);
457  const float normalizeTextHeight = static_cast<float>(glutBitmapHeight(font)) / static_cast<float>(_windowSize.y);
458  glRasterPos2f(x - normalizeTextLength, y - normalizeTextHeight);
459  glutBitmapString(font, msg);
460  glRasterPos2f(-1.f, -1.f);
461 }
462 #endif
463 
464 void BaseWindow::_toggleFrameBuffer()
465 {
466  size_t mode = static_cast<size_t>(_frameBufferMode);
467  mode = (mode + 1) % 2;
468  auto& engine = _core.getEngine();
469  const auto& ap = engine.getParametersManager().getApplicationParameters();
470  const auto& engineName = ap.getEngine();
471  if (engineName == ENGINE_OSPRAY && mode == static_cast<size_t>(AccumulationType::ai_denoised))
472  mode = (mode + 1) % 2;
473  _frameBufferMode = static_cast<FrameBufferMode>(mode);
474 
475  // Accumulation type
476  auto& frameBuffer = engine.getFrameBuffer();
478  {
479  const auto& rp = engine.getParametersManager().getRenderingParameters();
480  if (rp.getToneMapperExposure() > 0.f)
481  _setHint("Post processing: AI Denoiser + Tone mapper");
482  else
483  _setHint("Post processing: AI Denoiser");
484  frameBuffer.setAccumulationType(AccumulationType::ai_denoised);
485  }
486  else
487  {
488  _setHint("Post processing: None");
489  frameBuffer.setAccumulationType(AccumulationType::linear);
490  }
491 }
492 
493 void BaseWindow::_toggleRendererType()
494 {
495  ++_currentRendererTypeIndex;
496  _currentRendererTypeIndex = _currentRendererTypeIndex % _rendererTypes.size();
497  const auto rendererType = _rendererTypes[_currentRendererTypeIndex];
498  auto& engine = _core.getEngine();
499  auto& renderer = engine.getRenderer();
500  renderer.setCurrentType(rendererType);
501  _setHint("Renderer: [" + rendererType + "]");
502 }
503 
504 void BaseWindow::_toggleHeadLight()
505 {
506  auto& renderer = _core.getEngine().getRenderer();
507  renderer.setHeadLight(!renderer.getHeadLight());
508  std::string hint = "Head light: [";
509  hint += (renderer.getHeadLight() ? "ON" : "OFF");
510  hint += "]";
511  _setHint(hint);
512 }
513 
514 void BaseWindow::_setHint(const std::string& message, const uint64_t milliseconds)
515 {
516  _hintMessage = message;
517  _hintDelay = milliseconds;
518  _chrono = std::chrono::steady_clock::now();
519 }
520 
521 } // namespace core
virtual void dragRight(const Vector2i &to, const Vector2i &from)=0
void setWindowSize(const Vector2ui &size)
const Vector2ui getWindowSize() const
u_int64_t _currModifiers
Definition: BaseWindow.h:123
u_int64_t _currButtonState
Definition: BaseWindow.h:122
friend void glut3dPassiveMouseFunc(int x, int y)
Definition: BaseWindow.cpp:113
virtual void display()
Definition: BaseWindow.cpp:247
friend void glut3dMouseFunc(int whichButton, int released, int x, int y)
Definition: BaseWindow.cpp:107
void _renderBitmapString(float x, float y, const std::string &text)
Definition: BaseWindow.cpp:451
Vector2i _currMousePos
Definition: BaseWindow.h:119
virtual void reshape(const Vector2i &newSize)
Definition: BaseWindow.cpp:228
virtual ~BaseWindow()
Definition: BaseWindow.cpp:149
BaseWindow(Core &core, FrameBufferMode frameBufferMode=FrameBufferMode::COLOR_I8)
Definition: BaseWindow.cpp:125
virtual void keypress(char key, const Vector2f &where)
Definition: BaseWindow.cpp:378
FrameBufferMode _frameBufferMode
Definition: BaseWindow.h:125
void _setTitle(const char *title)
Definition: BaseWindow.cpp:354
friend void glut3dReshape(int x, int y)
Definition: BaseWindow.cpp:71
Vector2ui _windowSize
Definition: BaseWindow.h:128
std::string _hintMessage
Definition: BaseWindow.h:141
std::chrono::time_point< std::chrono::steady_clock > _chrono
Definition: BaseWindow.h:143
Vector2i _mouse
Definition: BaseWindow.h:120
friend void glut3dIdle(void)
Definition: BaseWindow.cpp:96
virtual void motion(const Vector2i &pos)
Definition: BaseWindow.cpp:188
RenderOutput _renderOutput
Definition: BaseWindow.h:139
void create(const char *title, size_t width, size_t height)
Definition: BaseWindow.cpp:361
virtual void activate()
Definition: BaseWindow.cpp:236
u_int64_t _lastButtonState
Definition: BaseWindow.h:121
Vector2ui _windowPosition
Definition: BaseWindow.h:136
virtual void passiveMotion(const Vector2i &pos)
Definition: BaseWindow.cpp:218
void drawPixels(const int *framebuffer)
Definition: BaseWindow.cpp:342
friend void glut3dSpecial(int key, int x, int y)
Definition: BaseWindow.cpp:90
uint64_t _hintDelay
Definition: BaseWindow.h:142
virtual void mouseButton(int button, bool released, const Vector2i &pos)
Definition: BaseWindow.cpp:151
virtual void specialkey(int key, const Vector2f &where)
Definition: BaseWindow.cpp:409
friend void glut3dMotionFunc(int x, int y)
Definition: BaseWindow.cpp:101
friend void glut3dKeyboard(unsigned char key, int x, int y)
Definition: BaseWindow.cpp:85
void _setHint(const std::string &message, const uint64_t milliseconds=3000)
Definition: BaseWindow.cpp:514
virtual void idle()
Definition: BaseWindow.cpp:223
virtual void _registerKeyboardShortcuts()
Definition: BaseWindow.cpp:439
Vector2i _lastMousePos
Definition: BaseWindow.h:117
RenderInput _renderInput
Definition: BaseWindow.h:138
friend void glut3dDisplay(void)
Definition: BaseWindow.cpp:77
virtual void forceRedraw()
Definition: BaseWindow.cpp:242
PLATFORM_API void setTarget(const Vector3d &target)
Sets the camera target.
Definition: Camera.h:101
PLATFORM_API Engine & getEngine()
Definition: Core.cpp:510
PLATFORM_API void commitAndRender(const RenderInput &renderInput, RenderOutput &renderOutput)
Definition: Core.cpp:479
PLATFORM_API AbstractManipulator & getCameraManipulator()
Definition: Core.cpp:524
PLATFORM_API ParametersManager & getParametersManager()
Definition: Core.cpp:514
PLATFORM_API KeyboardHandler & getKeyboardHandler()
Definition: Core.cpp:519
PLATFORM_API bool commit()
Definition: Core.cpp:498
PLATFORM_API FrameBuffer & getFrameBuffer()
Returns the frame buffer.
Definition: Engine.h:154
PLATFORM_API const auto & getParametersManager() const
Returns the parameter manager.
Definition: Engine.h:210
PLATFORM_API Renderer & getRenderer()
Returns the renderer.
Definition: Engine.cpp:72
virtual PLATFORM_API void commit()
Commits changes to the engine. This includes scene modifications, camera modifications and renderer m...
Definition: Engine.cpp:41
PLATFORM_API const strings & getRendererTypes() const
Returns all renderer types.
Definition: Engine.h:264
PLATFORM_API const Camera & getCamera() const
Returns the camera.
Definition: Engine.h:161
virtual PLATFORM_API void clear()
Clear the framebuffer.
Definition: FrameBuffer.h:90
void handle(const SpecialKey key)
Handles a special key.
void handleKeyboardShortcut(const unsigned char key)
Handles a keyboard shortcut.
void registerKeyboardShortcut(const unsigned char key, const std::string &description, std::function< void()> functor)
Registers a keyboard shortcut.
PLATFORM_API ApplicationParameters & getApplicationParameters()
PLATFORM_API RenderingParameters & getRenderingParameters()
void setCurrentType(const std::string &type)
PLATFORM_API size_t getMaxAccumFrames() const
Definition: Renderer.h:117
virtual PickResult pick(const Vector2f &)
Pick method This method is used to pick a point on the scene and returns PickResult struct with hit b...
Definition: Renderer.h:89
PLATFORM_API void setHeadLight(const bool value)
Definition: Renderer.h:108
void start()
Definition: Timer.cpp:34
void stop()
Definition: Timer.cpp:44
void glut3dDisplay(void)
Definition: BaseWindow.cpp:77
void glut3dIdle(void)
Definition: BaseWindow.cpp:96
void initGLUT(int *ac, const char **av)
dedicated namespace for 3D glut viewer widget
Definition: BaseWindow.cpp:62
glm::vec3 Vector3f
Definition: MathTypes.h:137
void glut3dKeyboard(unsigned char key, int x, int y)
Definition: BaseWindow.cpp:85
glm::vec2 Vector2f
Definition: MathTypes.h:136
glm::vec< 2, int32_t > Vector2i
Definition: MathTypes.h:130
uint64_t maxFrame
Definition: BaseWindow.cpp:55
void glut3dMotionFunc(int x, int y)
Definition: BaseWindow.cpp:101
void glut3dReshape(int x, int y)
Definition: BaseWindow.cpp:71
void glut3dPassiveMouseFunc(int x, int y)
Definition: BaseWindow.cpp:113
void glut3dSpecial(int key, int x, int y)
Definition: BaseWindow.cpp:90
uint64_t currentFrame
Definition: BaseWindow.cpp:54
void runGLUT()
Definition: BaseWindow.cpp:57
void glut3dMouseFunc(int whichButton, int released, int x, int y)
Definition: BaseWindow.cpp:107
FrameBufferMode
Definition: BaseWindow.h:45
glm::vec< 2, uint32_t > Vector2ui
Definition: MathTypes.h:133
#define CORE_INFO(__msg)
Definition: Logs.h:33
Quaterniond orientation
Definition: Types.h:317
Vector3d target
Definition: Types.h:316
Vector3d position
Definition: Types.h:315
Vector2i windowSize
Definition: Types.h:313
floats floatBuffer
Definition: Types.h:324
uint8_ts colorBuffer
Definition: Types.h:323
FrameBufferFormat colorBufferFormat
Definition: Types.h:325