1
2 #ifdef B3_USE_GLFW
3 #include "GLFWOpenGLWindow.h"
4
5 #include <glad/gl.h>
6 #include <GLFW/glfw3.h>
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include "LinearMath/btScalar.h"
11
12 struct GLFWOpenGLWindowInternalData
13 {
14 bool m_requestedExit;
15 bool m_hasCursorPos;
16 bool m_altPressed;
17 bool m_shiftPressed;
18 bool m_ctrlPressed;
19 float m_cursorXPos;
20 float m_cursorYPos;
21 b3MouseMoveCallback m_mouseMoveCallback;
22 b3MouseButtonCallback m_mouseButtonCallback;
23 b3ResizeCallback m_resizeCallback;
24 b3WheelCallback m_wheelCallback;
25 b3KeyboardCallback m_keyboardCallback;
26 b3RenderCallback m_renderCallback;
27 int m_width;
28 int m_height;
29 float m_retinaScaleFactor;
30
31 GLFWwindow* m_glfwWindow;
32
GLFWOpenGLWindowInternalDataGLFWOpenGLWindowInternalData33 GLFWOpenGLWindowInternalData()
34 : m_requestedExit(false),
35 m_hasCursorPos(false),
36 m_altPressed(false),
37 m_shiftPressed(false),
38 m_ctrlPressed(false),
39 m_cursorXPos(0),
40 m_cursorYPos(0),
41 m_mouseMoveCallback(0),
42 m_mouseButtonCallback(0),
43 m_resizeCallback(0),
44 m_wheelCallback(0),
45 m_keyboardCallback(0),
46 m_renderCallback(0),
47 m_width(0),
48 m_height(0),
49 m_retinaScaleFactor(1),
50 m_glfwWindow(0)
51 {
52 }
53 };
54
GLFWErrorCallback(int error,const char * description)55 static void GLFWErrorCallback(int error, const char* description)
56 {
57 fprintf(stderr, "Error: %s\n", description);
58 }
59
GLFWMouseButtonCallback(GLFWwindow * window,int button,int glfwState,int)60 static void GLFWMouseButtonCallback(GLFWwindow* window, int button, int glfwState, int)
61 {
62 GLFWOpenGLWindow* wnd = (GLFWOpenGLWindow*)glfwGetWindowUserPointer(window);
63 if (wnd && wnd->getMouseButtonCallback())
64 {
65 int state = (glfwState == GLFW_PRESS) ? 1 : 0;
66 wnd->mouseButtonCallbackInternal(button, state);
67 }
68 }
69
GLFWScrollCallback(GLFWwindow * window,double deltaX,double deltaY)70 static void GLFWScrollCallback(GLFWwindow* window, double deltaX, double deltaY)
71 {
72 GLFWOpenGLWindow* wnd = (GLFWOpenGLWindow*)glfwGetWindowUserPointer(window);
73 if (wnd && wnd->getWheelCallback())
74 {
75 wnd->getWheelCallback()(deltaX * 100, deltaY * 100);
76 }
77 }
78
GLFWCursorPosCallback(GLFWwindow * window,double xPos,double yPos)79 static void GLFWCursorPosCallback(GLFWwindow* window, double xPos, double yPos)
80 {
81 GLFWOpenGLWindow* wnd = (GLFWOpenGLWindow*)glfwGetWindowUserPointer(window);
82 if (wnd && wnd->getMouseMoveCallback())
83 {
84 wnd->mouseCursorCallbackInternal(xPos, yPos);
85 }
86 }
87
GLFWKeyCallback(GLFWwindow * window,int key,int scancode,int action,int mods)88 static void GLFWKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
89 {
90 GLFWOpenGLWindow* wnd = (GLFWOpenGLWindow*)glfwGetWindowUserPointer(window);
91 if (wnd)
92 {
93 wnd->keyboardCallbackInternal(key, action);
94 }
95 if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
96 {
97 glfwSetWindowShouldClose(window, GLFW_TRUE);
98 }
99 }
100
GLFWSizeCallback(GLFWwindow * window,int width,int height)101 static void GLFWSizeCallback(GLFWwindow* window, int width, int height)
102 {
103 GLFWOpenGLWindow* wnd = (GLFWOpenGLWindow*)glfwGetWindowUserPointer(window);
104 {
105 wnd->resizeInternal(width, height);
106 }
107 }
108
GLFWOpenGLWindow()109 GLFWOpenGLWindow::GLFWOpenGLWindow()
110 {
111 m_data = new GLFWOpenGLWindowInternalData();
112 }
113
~GLFWOpenGLWindow()114 GLFWOpenGLWindow::~GLFWOpenGLWindow()
115 {
116 if (m_data->m_glfwWindow)
117 {
118 closeWindow();
119 }
120 delete m_data;
121 }
122
getBulletKeyFromGLFWKeycode(int glfwKeyCode)123 int getBulletKeyFromGLFWKeycode(int glfwKeyCode)
124 {
125 int keycode = -1;
126 if (glfwKeyCode >= 'A' && glfwKeyCode <= 'Z')
127 {
128 return glfwKeyCode + 32; //todo: fix the ascii A vs a input
129 }
130 if (glfwKeyCode >= '0' && glfwKeyCode <= '9')
131 {
132 return glfwKeyCode;
133 }
134
135 switch (glfwKeyCode)
136 {
137 case GLFW_KEY_ENTER:
138 {
139 keycode = B3G_RETURN;
140 break;
141 };
142 case GLFW_KEY_ESCAPE:
143 {
144 keycode = B3G_ESCAPE;
145 break;
146 };
147 case GLFW_KEY_F1:
148 {
149 keycode = B3G_F1;
150 break;
151 }
152 case GLFW_KEY_F2:
153 {
154 keycode = B3G_F2;
155 break;
156 }
157 case GLFW_KEY_F3:
158 {
159 keycode = B3G_F3;
160 break;
161 }
162 case GLFW_KEY_F4:
163 {
164 keycode = B3G_F4;
165 break;
166 }
167 case GLFW_KEY_F5:
168 {
169 keycode = B3G_F5;
170 break;
171 }
172 case GLFW_KEY_F6:
173 {
174 keycode = B3G_F6;
175 break;
176 }
177 case GLFW_KEY_F7:
178 {
179 keycode = B3G_F7;
180 break;
181 }
182 case GLFW_KEY_F8:
183 {
184 keycode = B3G_F8;
185 break;
186 }
187 case GLFW_KEY_F9:
188 {
189 keycode = B3G_F9;
190 break;
191 }
192 case GLFW_KEY_F10:
193 {
194 keycode = B3G_F10;
195 break;
196 }
197
198 //case GLFW_KEY_SPACE: {keycode= ' '; break;}
199
200 case GLFW_KEY_PAGE_DOWN:
201 {
202 keycode = B3G_PAGE_DOWN;
203 break;
204 }
205 case GLFW_KEY_PAGE_UP:
206 {
207 keycode = B3G_PAGE_UP;
208 break;
209 }
210
211 case GLFW_KEY_INSERT:
212 {
213 keycode = B3G_INSERT;
214 break;
215 }
216 case GLFW_KEY_BACKSPACE:
217 {
218 keycode = B3G_BACKSPACE;
219 break;
220 }
221 case GLFW_KEY_DELETE:
222 {
223 keycode = B3G_DELETE;
224 break;
225 }
226
227 case GLFW_KEY_END:
228 {
229 keycode = B3G_END;
230 break;
231 }
232 case GLFW_KEY_HOME:
233 {
234 keycode = B3G_HOME;
235 break;
236 }
237 case GLFW_KEY_LEFT:
238 {
239 keycode = B3G_LEFT_ARROW;
240 break;
241 }
242 case GLFW_KEY_UP:
243 {
244 keycode = B3G_UP_ARROW;
245 break;
246 }
247 case GLFW_KEY_RIGHT:
248 {
249 keycode = B3G_RIGHT_ARROW;
250 break;
251 }
252 case GLFW_KEY_DOWN:
253 {
254 keycode = B3G_DOWN_ARROW;
255 break;
256 }
257 case GLFW_KEY_RIGHT_SHIFT:
258 {
259 keycode = B3G_SHIFT;
260 break;
261 }
262 case GLFW_KEY_LEFT_SHIFT:
263 {
264 keycode = B3G_SHIFT;
265 break;
266 }
267 case GLFW_KEY_MENU:
268 {
269 keycode = B3G_ALT;
270 break;
271 }
272 case GLFW_KEY_RIGHT_CONTROL:
273 {
274 keycode = B3G_CONTROL;
275 break;
276 }
277 case GLFW_KEY_LEFT_CONTROL:
278 {
279 keycode = B3G_CONTROL;
280 break;
281 }
282 default:
283 {
284 //keycode = MapVirtualKey( virtualKeyCode, MAPGLFW_KEY_GLFW_KEY_TO_CHAR ) & 0x0000FFFF;
285 }
286 };
287
288 return keycode;
289 }
290
keyboardCallbackInternal(int key,int state)291 void GLFWOpenGLWindow::keyboardCallbackInternal(int key, int state)
292 {
293 if (getKeyboardCallback())
294 {
295 //convert keyboard codes from glfw to bullet
296 int btcode = getBulletKeyFromGLFWKeycode(key);
297 int btstate = (state == GLFW_RELEASE) ? 0 : 1;
298
299 switch (btcode)
300 {
301 case B3G_SHIFT:
302 {
303 m_data->m_shiftPressed = state != 0;
304 break;
305 }
306 case B3G_ALT:
307 {
308 m_data->m_altPressed = state != 0;
309 break;
310 }
311 case B3G_CONTROL:
312 {
313 m_data->m_ctrlPressed = state != 0;
314 break;
315 }
316 default:
317 {
318 }
319 }
320
321 getKeyboardCallback()(btcode, btstate);
322 }
323 }
324
mouseButtonCallbackInternal(int button,int state)325 void GLFWOpenGLWindow::mouseButtonCallbackInternal(int button, int state)
326 {
327 if (getMouseButtonCallback() && m_data->m_hasCursorPos)
328 {
329 getMouseButtonCallback()(button, state, m_data->m_cursorXPos, m_data->m_cursorYPos);
330 }
331 }
332
mouseCursorCallbackInternal(double xPos,double yPos)333 void GLFWOpenGLWindow::mouseCursorCallbackInternal(double xPos, double yPos)
334 {
335 if (getMouseMoveCallback())
336 {
337 m_data->m_hasCursorPos = true;
338 m_data->m_cursorXPos = xPos;
339 m_data->m_cursorYPos = yPos;
340 getMouseMoveCallback()(xPos, yPos);
341 }
342 }
343
resizeInternal(int width,int height)344 void GLFWOpenGLWindow::resizeInternal(int width, int height)
345 {
346 glfwGetFramebufferSize(m_data->m_glfwWindow, &m_data->m_width, &m_data->m_height);
347 glViewport(0, 0, m_data->m_width, m_data->m_height);
348
349 if (getResizeCallback())
350 {
351 getResizeCallback()(m_data->m_width / m_data->m_retinaScaleFactor, m_data->m_height / m_data->m_retinaScaleFactor);
352 }
353 }
354
createDefaultWindow(int width,int height,const char * title)355 void GLFWOpenGLWindow::createDefaultWindow(int width, int height, const char* title)
356 {
357 b3gWindowConstructionInfo ci;
358 ci.m_width = width;
359 ci.m_height = height;
360 ci.m_title = title;
361
362 createWindow(ci);
363 }
364
createWindow(const b3gWindowConstructionInfo & ci)365 void GLFWOpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci)
366 {
367 btAssert(m_data->m_glfwWindow == 0);
368 if (m_data->m_glfwWindow == 0)
369 {
370 glfwSetErrorCallback(GLFWErrorCallback);
371
372 if (!glfwInit())
373 exit(EXIT_FAILURE);
374
375 if (ci.m_openglVersion == 2)
376 {
377 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
378 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
379 }
380 else
381 {
382 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
383 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
384 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
385 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
386 }
387
388 m_data->m_glfwWindow = glfwCreateWindow(ci.m_width, ci.m_height, ci.m_title, NULL, NULL);
389
390 if (!m_data->m_glfwWindow)
391 {
392 glfwTerminate();
393 exit(EXIT_FAILURE);
394 }
395
396 glfwSetKeyCallback(m_data->m_glfwWindow, GLFWKeyCallback);
397 glfwSetMouseButtonCallback(m_data->m_glfwWindow, GLFWMouseButtonCallback);
398
399 glfwSetCursorPosCallback(m_data->m_glfwWindow, GLFWCursorPosCallback);
400 glfwSetScrollCallback(m_data->m_glfwWindow, GLFWScrollCallback);
401
402 glfwSetWindowSizeCallback(m_data->m_glfwWindow, GLFWSizeCallback);
403 glfwSetWindowUserPointer(m_data->m_glfwWindow, this);
404
405 glfwMakeContextCurrent(m_data->m_glfwWindow);
406 gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
407 glfwSwapInterval(0); //1);
408 glfwGetFramebufferSize(m_data->m_glfwWindow, &m_data->m_width, &m_data->m_height);
409 int windowWidth, windowHeight;
410 glfwGetWindowSize(m_data->m_glfwWindow, &windowWidth, &windowHeight);
411 m_data->m_retinaScaleFactor = float(m_data->m_width) / float(windowWidth);
412 glViewport(0, 0, m_data->m_width, m_data->m_height);
413 }
414 }
415
closeWindow()416 void GLFWOpenGLWindow::closeWindow()
417 {
418 if (m_data->m_glfwWindow)
419 {
420 glfwDestroyWindow(m_data->m_glfwWindow);
421
422 glfwTerminate();
423 m_data->m_glfwWindow = 0;
424 }
425 }
426
runMainLoop()427 void GLFWOpenGLWindow::runMainLoop()
428 {
429 }
430
getTimeInSeconds()431 float GLFWOpenGLWindow::getTimeInSeconds()
432 {
433 return 0.f;
434 }
435
requestedExit() const436 bool GLFWOpenGLWindow::requestedExit() const
437 {
438 bool shouldClose = m_data->m_requestedExit;
439
440 if (m_data->m_glfwWindow)
441 {
442 shouldClose = shouldClose || glfwWindowShouldClose(m_data->m_glfwWindow);
443 }
444 return shouldClose;
445 }
446
setRequestExit()447 void GLFWOpenGLWindow::setRequestExit()
448 {
449 if (m_data->m_glfwWindow)
450 {
451 glfwSetWindowShouldClose(m_data->m_glfwWindow, GLFW_TRUE);
452 }
453 m_data->m_requestedExit = true;
454 }
455
startRendering()456 void GLFWOpenGLWindow::startRendering()
457 {
458 if (m_data->m_glfwWindow)
459 {
460 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
461 }
462 }
463
endRendering()464 void GLFWOpenGLWindow::endRendering()
465 {
466 glfwPollEvents();
467 glfwSwapBuffers(m_data->m_glfwWindow);
468 }
469
isModifierKeyPressed(int key)470 bool GLFWOpenGLWindow::isModifierKeyPressed(int key)
471 {
472 bool result = false;
473
474 switch (key)
475 {
476 case B3G_SHIFT:
477 {
478 result = m_data->m_shiftPressed;
479 break;
480 }
481 case B3G_ALT:
482 {
483 result = m_data->m_altPressed;
484 break;
485 }
486 case B3G_CONTROL:
487 {
488 result = m_data->m_ctrlPressed;
489 break;
490 }
491 default:
492 {
493 }
494 }
495 return result;
496 }
497
setMouseMoveCallback(b3MouseMoveCallback mouseCallback)498 void GLFWOpenGLWindow::setMouseMoveCallback(b3MouseMoveCallback mouseCallback)
499 {
500 m_data->m_mouseMoveCallback = mouseCallback;
501 }
502
getMouseMoveCallback()503 b3MouseMoveCallback GLFWOpenGLWindow::getMouseMoveCallback()
504 {
505 return m_data->m_mouseMoveCallback;
506 }
507
setMouseButtonCallback(b3MouseButtonCallback mouseCallback)508 void GLFWOpenGLWindow::setMouseButtonCallback(b3MouseButtonCallback mouseCallback)
509 {
510 m_data->m_mouseButtonCallback = mouseCallback;
511 }
512
getMouseButtonCallback()513 b3MouseButtonCallback GLFWOpenGLWindow::getMouseButtonCallback()
514 {
515 return m_data->m_mouseButtonCallback;
516 }
517
setResizeCallback(b3ResizeCallback resizeCallback)518 void GLFWOpenGLWindow::setResizeCallback(b3ResizeCallback resizeCallback)
519 {
520 m_data->m_resizeCallback = resizeCallback;
521 getResizeCallback()(m_data->m_width / getRetinaScale(), m_data->m_height / getRetinaScale());
522 }
523
getResizeCallback()524 b3ResizeCallback GLFWOpenGLWindow::getResizeCallback()
525 {
526 return m_data->m_resizeCallback;
527 }
528
setWheelCallback(b3WheelCallback wheelCallback)529 void GLFWOpenGLWindow::setWheelCallback(b3WheelCallback wheelCallback)
530 {
531 m_data->m_wheelCallback = wheelCallback;
532 }
533
getWheelCallback()534 b3WheelCallback GLFWOpenGLWindow::getWheelCallback()
535 {
536 return m_data->m_wheelCallback;
537 }
538
setKeyboardCallback(b3KeyboardCallback keyboardCallback)539 void GLFWOpenGLWindow::setKeyboardCallback(b3KeyboardCallback keyboardCallback)
540 {
541 m_data->m_keyboardCallback = keyboardCallback;
542 }
543
getKeyboardCallback()544 b3KeyboardCallback GLFWOpenGLWindow::getKeyboardCallback()
545 {
546 return m_data->m_keyboardCallback;
547 }
548
setRenderCallback(b3RenderCallback renderCallback)549 void GLFWOpenGLWindow::setRenderCallback(b3RenderCallback renderCallback)
550 {
551 m_data->m_renderCallback = renderCallback;
552 }
553
setWindowTitle(const char * title)554 void GLFWOpenGLWindow::setWindowTitle(const char* title)
555 {
556 if (m_data->m_glfwWindow)
557 {
558 glfwSetWindowTitle(m_data->m_glfwWindow, title);
559 }
560 }
561
getRetinaScale() const562 float GLFWOpenGLWindow::getRetinaScale() const
563 {
564 return m_data->m_retinaScaleFactor;
565 }
setAllowRetina(bool allow)566 void GLFWOpenGLWindow::setAllowRetina(bool allow)
567 {
568 }
569
getWidth() const570 int GLFWOpenGLWindow::getWidth() const
571 {
572 if (m_data->m_glfwWindow)
573 {
574 glfwGetFramebufferSize(m_data->m_glfwWindow, &m_data->m_width, &m_data->m_height);
575 }
576 int width = m_data->m_width / m_data->m_retinaScaleFactor;
577 return width;
578 }
getHeight() const579 int GLFWOpenGLWindow::getHeight() const
580 {
581 if (m_data->m_glfwWindow)
582 {
583 glfwGetFramebufferSize(m_data->m_glfwWindow, &m_data->m_width, &m_data->m_height);
584 }
585 return m_data->m_height / m_data->m_retinaScaleFactor;
586 }
587
fileOpenDialog(char * fileName,int maxFileNameLength)588 int GLFWOpenGLWindow::fileOpenDialog(char* fileName, int maxFileNameLength)
589 {
590 return 0;
591 }
592
593 #endif //B3_USE_GLFW
594