1 #include "OpenGLExampleBrowser.h"
2 #include "LinearMath/btQuickprof.h"
3 #include "../OpenGLWindow/OpenGLInclude.h"
4 #include "../OpenGLWindow/SimpleOpenGL2App.h"
5 #ifndef NO_OPENGL3
6 #include "../OpenGLWindow/SimpleOpenGL3App.h"
7 #endif
8 #include "../CommonInterfaces/CommonRenderInterface.h"
9 #ifdef __APPLE__
10 #include "../OpenGLWindow/MacOpenGLWindow.h"
11 #else
12 #ifdef _WIN32
13 #include "../OpenGLWindow/Win32OpenGLWindow.h"
14 #else
15 //let's cross the fingers it is Linux/X11
16 #ifdef BT_USE_EGL
17 #include "../OpenGLWindow/EGLOpenGLWindow.h"
18 #else
19 #include "../OpenGLWindow/X11OpenGLWindow.h"
20 #endif //BT_USE_EGL
21 #endif //_WIN32
22 #endif //__APPLE__
23 #include "../ThirdPartyLibs/Gwen/Renderers/OpenGL_DebugFont.h"
24 #include "LinearMath/btThreads.h"
25 #include "Bullet3Common/b3Vector3.h"
26 #include "assert.h"
27 #include <stdio.h>
28 #include "GwenGUISupport/gwenInternalData.h"
29 #include "GwenGUISupport/gwenUserInterface.h"
30 #include "../Utils/b3Clock.h"
31 #include "../Utils/ChromeTraceUtil.h"
32 #include "GwenGUISupport/GwenParameterInterface.h"
33 #ifndef BT_NO_PROFILE
34 #include "GwenGUISupport/GwenProfileWindow.h"
35 #endif
36 #include "GwenGUISupport/GwenTextureWindow.h"
37 #include "GwenGUISupport/GraphingTexture.h"
38 #include "../CommonInterfaces/Common2dCanvasInterface.h"
39 #include "../CommonInterfaces/CommonExampleInterface.h"
40 #include "Bullet3Common/b3CommandLineArgs.h"
41 #include "../OpenGLWindow/SimpleCamera.h"
42 #include "../OpenGLWindow/SimpleOpenGL2Renderer.h"
43 #include "ExampleEntries.h"
44 #include "OpenGLGuiHelper.h"
45 #include "Bullet3Common/b3FileUtils.h"
46
47 #include "LinearMath/btIDebugDraw.h"
48 //quick test for file import, @todo(erwincoumans) make it more general and add other file formats
49 #include "../Importers/ImportURDFDemo/ImportURDFSetup.h"
50 #include "../Importers/ImportBullet/SerializeSetup.h"
51 #include "Bullet3Common/b3HashMap.h"
52
53 struct GL3TexLoader : public MyTextureLoader
54 {
55 b3HashMap<b3HashString, GLint> m_hashMap;
56
LoadTextureGL3TexLoader57 virtual void LoadTexture(Gwen::Texture* pTexture)
58 {
59 Gwen::String namestr = pTexture->name.Get();
60 const char* n = namestr.c_str();
61 GLint* texIdPtr = m_hashMap[n];
62 if (texIdPtr)
63 {
64 pTexture->m_intData = *texIdPtr;
65 }
66 }
FreeTextureGL3TexLoader67 virtual void FreeTexture(Gwen::Texture* pTexture)
68 {
69 }
70 };
71
72 struct OpenGLExampleBrowserInternalData
73 {
74 Gwen::Renderer::Base* m_gwenRenderer;
75 CommonGraphicsApp* m_app;
76 #ifndef BT_NO_PROFILE
77 MyProfileWindow* m_profWindow;
78 #endif //BT_NO_PROFILE
79 btAlignedObjectArray<Gwen::Controls::TreeNode*> m_nodes;
80 GwenUserInterface* m_gui;
81 GL3TexLoader* m_myTexLoader;
82 struct MyMenuItemHander* m_handler2;
83 btAlignedObjectArray<MyMenuItemHander*> m_handlers;
84
OpenGLExampleBrowserInternalDataOpenGLExampleBrowserInternalData85 OpenGLExampleBrowserInternalData()
86 : m_gwenRenderer(0),
87 m_app(0),
88 // m_profWindow(0),
89 m_gui(0),
90 m_myTexLoader(0),
91 m_handler2(0)
92 {
93 }
94 };
95
96 static CommonGraphicsApp* s_app = 0;
97
98 static CommonWindowInterface* s_window = 0;
99 static CommonParameterInterface* s_parameterInterface = 0;
100 static CommonRenderInterface* s_instancingRenderer = 0;
101 static OpenGLGuiHelper* s_guiHelper = 0;
102 #ifndef BT_NO_PROFILE
103 static MyProfileWindow* s_profWindow = 0;
104 #endif //BT_NO_PROFILE
105 static SharedMemoryInterface* sSharedMem = 0;
106
107 #define DEMO_SELECTION_COMBOBOX 13
108 const char* startFileName = "0_Bullet3Demo.txt";
109 char staticPngFileName[1024];
110 //static GwenUserInterface* gui = 0;
111 static GwenUserInterface* gui2 = 0;
112 static int sCurrentDemoIndex = -1;
113 static int sCurrentHightlighted = 0;
114 static CommonExampleInterface* sCurrentDemo = 0;
115 static b3AlignedObjectArray<const char*> allNames;
116 static float gFixedTimeStep = 0;
117 bool gAllowRetina = true;
118 bool gDisableDemoSelection = false;
119 int gRenderDevice = -1;
120 int gWindowBackend = 0;
121 static class ExampleEntries* gAllExamples = 0;
122 bool sUseOpenGL2 = false;
123 #ifndef USE_OPENGL3
124 extern bool useShadowMap;
125 #endif
126
127 bool visualWireframe = false;
128 static bool renderVisualGeometry = true;
129 static bool renderGrid = true;
130 static bool gEnableRenderLoop = true;
131
132 bool renderGui = true;
133 static bool enable_experimental_opencl = false;
134
135 static bool gEnableDefaultKeyboardShortcuts = true;
136 static bool gEnableDefaultMousePicking = true;
137
138 int gDebugDrawFlags = 0;
139 static bool pauseSimulation = false;
140 static bool singleStepSimulation = false;
141 int midiBaseIndex = 176;
142 extern bool gDisableDeactivation;
143
144 int gSharedMemoryKey = -1;
145
146 ///some quick test variable for the OpenCL examples
147
148 int gPreferredOpenCLDeviceIndex = -1;
149 int gPreferredOpenCLPlatformIndex = -1;
150 int gGpuArraySizeX = 45;
151 int gGpuArraySizeY = 55;
152 int gGpuArraySizeZ = 45;
153
154 //#include <float.h>
155 //unsigned int fp_control_state = _controlfp(_EM_INEXACT, _MCW_EM);
156
deleteDemo()157 void deleteDemo()
158 {
159 if (sCurrentDemo)
160 {
161 sCurrentDemo->exitPhysics();
162 s_instancingRenderer->removeAllInstances();
163 delete sCurrentDemo;
164 sCurrentDemo = 0;
165 delete s_guiHelper;
166 s_guiHelper = 0;
167
168 // CProfileManager::CleanupMemory();
169 }
170 }
171
172 const char* gPngFileName = 0;
173 int gPngSkipFrames = 0;
174
175 b3KeyboardCallback prevKeyboardCallback = 0;
176
MyKeyboardCallback(int key,int state)177 void MyKeyboardCallback(int key, int state)
178 {
179 //b3Printf("key=%d, state=%d", key, state);
180 bool handled = false;
181 if (renderGui)
182 {
183 if (gui2 && !handled)
184 {
185 handled = gui2->keyboardCallback(key, state);
186 }
187 }
188
189 if (!handled && sCurrentDemo)
190 {
191 handled = sCurrentDemo->keyboardCallback(key, state);
192 }
193
194 //checkout: is it desired to ignore keys, if the demo already handles them?
195 //if (handled)
196 // return;
197
198 if (gEnableDefaultKeyboardShortcuts)
199 {
200 if (key == 'a' && state)
201 {
202 gDebugDrawFlags ^= btIDebugDraw::DBG_DrawAabb;
203 }
204 if (key == 'c' && state)
205 {
206 gDebugDrawFlags ^= btIDebugDraw::DBG_DrawContactPoints;
207 }
208 if (key == 'd' && state)
209 {
210 gDebugDrawFlags ^= btIDebugDraw::DBG_NoDeactivation;
211 gDisableDeactivation = ((gDebugDrawFlags & btIDebugDraw::DBG_NoDeactivation) != 0);
212 }
213 if (key == 'j' && state)
214 {
215 gDebugDrawFlags ^= btIDebugDraw::DBG_DrawFrames;
216 }
217
218 if (key == 'k' && state)
219 {
220 gDebugDrawFlags ^= btIDebugDraw::DBG_DrawConstraints;
221 }
222
223 if (key == 'l' && state)
224 {
225 gDebugDrawFlags ^= btIDebugDraw::DBG_DrawConstraintLimits;
226 }
227 if (key == 'w' && state)
228 {
229 visualWireframe = !visualWireframe;
230 gDebugDrawFlags ^= btIDebugDraw::DBG_DrawWireframe;
231 }
232
233 if (key == 'v' && state)
234 {
235 renderVisualGeometry = !renderVisualGeometry;
236 }
237 if (key == 'g' && state)
238 {
239 renderGrid = !renderGrid;
240 renderGui = !renderGui;
241 }
242
243 if (key == 'i' && state)
244 {
245 pauseSimulation = !pauseSimulation;
246 }
247 if (key == 'o' && state)
248 {
249 singleStepSimulation = true;
250 }
251
252 if (key == 'p')
253 {
254 if (state)
255 {
256 b3ChromeUtilsStartTimings();
257 }
258 else
259 {
260 #ifdef _WIN32
261 b3ChromeUtilsStopTimingsAndWriteJsonFile("timings");
262 #else
263 b3ChromeUtilsStopTimingsAndWriteJsonFile("/tmp/timings");
264 #endif
265 }
266 }
267
268 #ifndef NO_OPENGL3
269 if (key == 's' && state)
270 {
271 useShadowMap = !useShadowMap;
272 }
273 #endif
274 if (key == B3G_F1)
275 {
276 static int count = 0;
277 if (state)
278 {
279 b3Printf("F1 pressed %d", count++);
280
281 if (gPngFileName)
282 {
283 b3Printf("disable image dump");
284
285 gPngFileName = 0;
286 }
287 else
288 {
289 gPngFileName = gAllExamples->getExampleName(sCurrentDemoIndex);
290 b3Printf("enable image dump %s", gPngFileName);
291 }
292 }
293 else
294 {
295 b3Printf("F1 released %d", count++);
296 }
297 }
298 }
299 if (key == B3G_ESCAPE && s_window)
300 {
301 s_window->setRequestExit();
302 }
303
304 if (prevKeyboardCallback)
305 prevKeyboardCallback(key, state);
306 }
307
308 b3MouseMoveCallback prevMouseMoveCallback = 0;
MyMouseMoveCallback(float x,float y)309 static void MyMouseMoveCallback(float x, float y)
310 {
311 bool handled = false;
312 if (sCurrentDemo)
313 handled = sCurrentDemo->mouseMoveCallback(x, y);
314 if (renderGui)
315 {
316 if (!handled && gui2)
317 handled = gui2->mouseMoveCallback(x, y);
318 }
319 if (!handled)
320 {
321 if (prevMouseMoveCallback)
322 prevMouseMoveCallback(x, y);
323 }
324 }
325
326 b3MouseButtonCallback prevMouseButtonCallback = 0;
327
MyMouseButtonCallback(int button,int state,float x,float y)328 static void MyMouseButtonCallback(int button, int state, float x, float y)
329 {
330 bool handled = false;
331 //try picking first
332 if (sCurrentDemo)
333 handled = sCurrentDemo->mouseButtonCallback(button, state, x, y);
334
335 if (renderGui)
336 {
337 if (!handled && gui2)
338 handled = gui2->mouseButtonCallback(button, state, x, y);
339 }
340 if (!handled)
341 {
342 if (prevMouseButtonCallback)
343 prevMouseButtonCallback(button, state, x, y);
344 }
345 // b3DefaultMouseButtonCallback(button,state,x,y);
346 }
347
348 #include <string.h>
349 struct FileImporterByExtension
350 {
351 std::string m_extension;
352 CommonExampleInterface::CreateFunc* m_createFunc;
353 };
354
355 static btAlignedObjectArray<FileImporterByExtension> gFileImporterByExtension;
356
registerFileImporter(const char * extension,CommonExampleInterface::CreateFunc * createFunc)357 void OpenGLExampleBrowser::registerFileImporter(const char* extension, CommonExampleInterface::CreateFunc* createFunc)
358 {
359 FileImporterByExtension fi;
360 fi.m_extension = extension;
361 fi.m_createFunc = createFunc;
362 gFileImporterByExtension.push_back(fi);
363 }
364 #include "../SharedMemory/SharedMemoryPublic.h"
365
OpenGLExampleBrowserVisualizerFlagCallback(int flag,bool enable)366 void OpenGLExampleBrowserVisualizerFlagCallback(int flag, bool enable)
367 {
368 if (flag == COV_ENABLE_Y_AXIS_UP)
369 {
370 //either Y = up or Z
371 int upAxis = enable ? 1 : 2;
372 s_app->setUpAxis(upAxis);
373 }
374
375 if (flag == COV_ENABLE_RENDERING)
376 {
377 gEnableRenderLoop = (enable != 0);
378 }
379
380 if (flag == COV_ENABLE_SINGLE_STEP_RENDERING)
381 {
382 if (enable)
383 {
384 gEnableRenderLoop = false;
385 singleStepSimulation = true;
386 }
387 else
388 {
389 gEnableRenderLoop = true;
390 singleStepSimulation = false;
391 }
392 }
393
394 if (flag == COV_ENABLE_SHADOWS)
395 {
396 useShadowMap = enable;
397 }
398 if (flag == COV_ENABLE_GUI)
399 {
400 renderGui = enable;
401 renderGrid = enable;
402 }
403
404 if (flag == COV_ENABLE_KEYBOARD_SHORTCUTS)
405 {
406 gEnableDefaultKeyboardShortcuts = enable;
407 }
408 if (flag == COV_ENABLE_MOUSE_PICKING)
409 {
410 gEnableDefaultMousePicking = enable;
411 }
412
413 if (flag == COV_ENABLE_WIREFRAME)
414 {
415 visualWireframe = enable;
416 if (visualWireframe)
417 {
418 gDebugDrawFlags |= btIDebugDraw::DBG_DrawWireframe;
419 }
420 else
421 {
422 gDebugDrawFlags &= ~btIDebugDraw::DBG_DrawWireframe;
423 }
424 }
425 }
426
openFileDemo(const char * filename)427 void openFileDemo(const char* filename)
428 {
429 deleteDemo();
430
431 s_guiHelper = new OpenGLGuiHelper(s_app, sUseOpenGL2);
432 s_guiHelper->setVisualizerFlagCallback(OpenGLExampleBrowserVisualizerFlagCallback);
433
434 s_parameterInterface->removeAllParameters();
435
436 CommonExampleOptions options(s_guiHelper, 1);
437 options.m_fileName = filename;
438 char fullPath[1024];
439 sprintf(fullPath, "%s", filename);
440 b3FileUtils::toLower(fullPath);
441
442 for (int i = 0; i < gFileImporterByExtension.size(); i++)
443 {
444 if (strstr(fullPath, gFileImporterByExtension[i].m_extension.c_str()))
445 {
446 sCurrentDemo = gFileImporterByExtension[i].m_createFunc(options);
447 }
448 }
449
450 if (sCurrentDemo)
451 {
452 sCurrentDemo->initPhysics();
453 sCurrentDemo->resetCamera();
454 }
455 }
456
selectDemo(int demoIndex)457 void selectDemo(int demoIndex)
458 {
459 bool resetCamera = (sCurrentDemoIndex != demoIndex);
460 sCurrentDemoIndex = demoIndex;
461 sCurrentHightlighted = demoIndex;
462 int numDemos = gAllExamples->getNumRegisteredExamples();
463
464 if (demoIndex > numDemos)
465 {
466 demoIndex = 0;
467 }
468 deleteDemo();
469
470 CommonExampleInterface::CreateFunc* func = gAllExamples->getExampleCreateFunc(demoIndex);
471 if (func)
472 {
473 if (s_parameterInterface)
474 {
475 s_parameterInterface->removeAllParameters();
476 }
477 int option = gAllExamples->getExampleOption(demoIndex);
478 s_guiHelper = new OpenGLGuiHelper(s_app, sUseOpenGL2);
479 s_guiHelper->setVisualizerFlagCallback(OpenGLExampleBrowserVisualizerFlagCallback);
480
481 CommonExampleOptions options(s_guiHelper, option);
482 options.m_sharedMem = sSharedMem;
483 sCurrentDemo = (*func)(options);
484 if (sCurrentDemo)
485 {
486 if (gui2)
487 {
488 gui2->setStatusBarMessage("Status: OK", false);
489 }
490 b3Printf("Selected demo: %s", gAllExamples->getExampleName(demoIndex));
491 if (gui2)
492 {
493 gui2->setExampleDescription(gAllExamples->getExampleDescription(demoIndex));
494 }
495
496 sCurrentDemo->initPhysics();
497 if (resetCamera)
498 {
499 sCurrentDemo->resetCamera();
500 }
501 }
502 }
503 }
504
505 #include <stdio.h>
506
saveCurrentSettings(int currentEntry,const char * startFileName)507 static void saveCurrentSettings(int currentEntry, const char* startFileName)
508 {
509 FILE* f = fopen(startFileName, "w");
510 if (f)
511 {
512 fprintf(f, "--start_demo_name=%s\n", gAllExamples->getExampleName(sCurrentDemoIndex));
513 fprintf(f, "--mouse_move_multiplier=%f\n", s_app->getMouseMoveMultiplier());
514 fprintf(f, "--mouse_wheel_multiplier=%f\n", s_app->getMouseWheelMultiplier());
515 float red, green, blue;
516 s_app->getBackgroundColor(&red, &green, &blue);
517 fprintf(f, "--background_color_red= %f\n", red);
518 fprintf(f, "--background_color_green= %f\n", green);
519 fprintf(f, "--background_color_blue= %f\n", blue);
520 fprintf(f, "--fixed_timestep= %f\n", gFixedTimeStep);
521 if (!gAllowRetina)
522 {
523 fprintf(f, "--disable_retina");
524 }
525
526 if (enable_experimental_opencl)
527 {
528 fprintf(f, "--enable_experimental_opencl\n");
529 }
530 // if (sUseOpenGL2 )
531 // {
532 // fprintf(f,"--opengl2\n");
533 // }
534
535 fclose(f);
536 }
537 };
538
loadCurrentSettings(const char * startFileName,b3CommandLineArgs & args)539 static void loadCurrentSettings(const char* startFileName, b3CommandLineArgs& args)
540 {
541 //int currentEntry= 0;
542 FILE* f = fopen(startFileName, "r");
543 if (f)
544 {
545 char oneline[1024];
546 char* argv[] = {0, &oneline[0]};
547
548 while (fgets(oneline, 1024, f) != NULL)
549 {
550 char* pos;
551 if ((pos = strchr(oneline, '\n')) != NULL)
552 *pos = '\0';
553 args.addArgs(2, argv);
554 }
555 fclose(f);
556 }
557 };
558
MyComboBoxCallback(int comboId,const char * item)559 void MyComboBoxCallback(int comboId, const char* item)
560 {
561 //printf("comboId = %d, item = %s\n",comboId, item);
562 if (comboId == DEMO_SELECTION_COMBOBOX)
563 {
564 //find selected item
565 for (int i = 0; i < allNames.size(); i++)
566 {
567 if (strcmp(item, allNames[i]) == 0)
568 {
569 selectDemo(i);
570 saveCurrentSettings(sCurrentDemoIndex, startFileName);
571 break;
572 }
573 }
574 }
575 }
576
577 //in case of multi-threading, don't submit messages while the GUI is rendering (causing crashes)
578 static bool gBlockGuiMessages = false;
579
MyGuiPrintf(const char * msg)580 void MyGuiPrintf(const char* msg)
581 {
582 printf("b3Printf: %s\n", msg);
583 if (!gDisableDemoSelection && !gBlockGuiMessages)
584 {
585 gui2->textOutput(msg);
586 gui2->forceUpdateScrollBars();
587 }
588 }
589
MyStatusBarPrintf(const char * msg)590 void MyStatusBarPrintf(const char* msg)
591 {
592 printf("b3Printf: %s\n", msg);
593 if (!gDisableDemoSelection && !gBlockGuiMessages)
594 {
595 bool isLeft = true;
596 gui2->setStatusBarMessage(msg, isLeft);
597 }
598 }
599
MyStatusBarError(const char * msg)600 void MyStatusBarError(const char* msg)
601 {
602 printf("Warning: %s\n", msg);
603 if (!gDisableDemoSelection && !gBlockGuiMessages)
604 {
605 bool isLeft = false;
606 gui2->setStatusBarMessage(msg, isLeft);
607 gui2->textOutput(msg);
608 gui2->forceUpdateScrollBars();
609 }
610 btAssert(0);
611 }
612
613 struct MyMenuItemHander : public Gwen::Event::Handler
614 {
615 int m_buttonId;
616
MyMenuItemHanderMyMenuItemHander617 MyMenuItemHander(int buttonId)
618 : m_buttonId(buttonId)
619 {
620 }
621
onButtonAMyMenuItemHander622 void onButtonA(Gwen::Controls::Base* pControl)
623 {
624 //const Gwen::String& name = pControl->GetName();
625 Gwen::Controls::TreeNode* node = (Gwen::Controls::TreeNode*)pControl;
626 // Gwen::Controls::Label* l = node->GetButton();
627
628 Gwen::UnicodeString la = node->GetButton()->GetText(); // node->GetButton()->GetName();// GetText();
629 Gwen::String laa = Gwen::Utility::UnicodeToString(la);
630 // const char* ha = laa.c_str();
631
632 //printf("selected %s\n", ha);
633 //int dep = but->IsDepressed();
634 //int tog = but->GetToggleState();
635 // if (m_data->m_toggleButtonCallback)
636 // (*m_data->m_toggleButtonCallback)(m_buttonId, tog);
637 }
onButtonBMyMenuItemHander638 void onButtonB(Gwen::Controls::Base* pControl)
639 {
640 Gwen::Controls::Label* label = (Gwen::Controls::Label*)pControl;
641 Gwen::UnicodeString la = label->GetText(); // node->GetButton()->GetName();// GetText();
642 Gwen::String laa = Gwen::Utility::UnicodeToString(la);
643 //const char* ha = laa.c_str();
644
645 if (!gDisableDemoSelection)
646 {
647 selectDemo(sCurrentHightlighted);
648 saveCurrentSettings(sCurrentDemoIndex, startFileName);
649 }
650 }
onButtonCMyMenuItemHander651 void onButtonC(Gwen::Controls::Base* pControl)
652 {
653 /*Gwen::Controls::Label* label = (Gwen::Controls::Label*) pControl;
654 Gwen::UnicodeString la = label->GetText();// node->GetButton()->GetName();// GetText();
655 Gwen::String laa = Gwen::Utility::UnicodeToString(la);
656 const char* ha = laa.c_str();
657
658
659 printf("onButtonC ! %s\n", ha);
660 */
661 }
onButtonDMyMenuItemHander662 void onButtonD(Gwen::Controls::Base* pControl)
663 {
664 /* Gwen::Controls::Label* label = (Gwen::Controls::Label*) pControl;
665 Gwen::UnicodeString la = label->GetText();// node->GetButton()->GetName();// GetText();
666 Gwen::String laa = Gwen::Utility::UnicodeToString(la);
667 const char* ha = laa.c_str();
668 */
669
670 // printf("onKeyReturn ! \n");
671 if (!gDisableDemoSelection)
672 {
673 selectDemo(sCurrentHightlighted);
674 saveCurrentSettings(sCurrentDemoIndex, startFileName);
675 }
676 }
677
onButtonEMyMenuItemHander678 void onButtonE(Gwen::Controls::Base* pControl)
679 {
680 // printf("select %d\n",m_buttonId);
681 sCurrentHightlighted = m_buttonId;
682 gui2->setExampleDescription(gAllExamples->getExampleDescription(sCurrentHightlighted));
683 }
684
onButtonFMyMenuItemHander685 void onButtonF(Gwen::Controls::Base* pControl)
686 {
687 //printf("selection changed!\n");
688 }
689
onButtonGMyMenuItemHander690 void onButtonG(Gwen::Controls::Base* pControl)
691 {
692 //printf("onButtonG !\n");
693 }
694 };
695
quitCallback()696 void quitCallback()
697 {
698 s_window->setRequestExit();
699 }
700
fileOpenCallback()701 void fileOpenCallback()
702 {
703 char filename[1024];
704 int len = s_window->fileOpenDialog(filename, 1024);
705 if (len)
706 {
707 //todo(erwincoumans) check if it is actually URDF
708 //printf("file open:%s\n", filename);
709 openFileDemo(filename);
710 }
711 }
712
713 #define MAX_GRAPH_WINDOWS 5
714
715 struct QuickCanvas : public Common2dCanvasInterface
716 {
717 GL3TexLoader* m_myTexLoader;
718
719 MyGraphWindow* m_gw[MAX_GRAPH_WINDOWS];
720 GraphingTexture* m_gt[MAX_GRAPH_WINDOWS];
721 int m_curNumGraphWindows;
722
QuickCanvasQuickCanvas723 QuickCanvas(GL3TexLoader* myTexLoader)
724 : m_myTexLoader(myTexLoader),
725 m_curNumGraphWindows(0)
726 {
727 for (int i = 0; i < MAX_GRAPH_WINDOWS; i++)
728 {
729 m_gw[i] = 0;
730 m_gt[i] = 0;
731 }
732 }
~QuickCanvasQuickCanvas733 virtual ~QuickCanvas() {}
createCanvasQuickCanvas734 virtual int createCanvas(const char* canvasName, int width, int height, int xPos, int yPos)
735 {
736 if (m_curNumGraphWindows < MAX_GRAPH_WINDOWS)
737 {
738 //find a slot
739 int slot = m_curNumGraphWindows;
740 btAssert(slot < MAX_GRAPH_WINDOWS);
741 if (slot >= MAX_GRAPH_WINDOWS)
742 return 0; //don't crash
743
744 m_curNumGraphWindows++;
745
746 MyGraphInput input(gui2->getInternalData());
747 input.m_width = width;
748 input.m_height = height;
749 input.m_xPos = xPos;
750 input.m_yPos = yPos;
751 input.m_name = canvasName;
752 input.m_texName = canvasName;
753 m_gt[slot] = new GraphingTexture;
754 m_gt[slot]->create(width, height);
755 int texId = m_gt[slot]->getTextureId();
756 m_myTexLoader->m_hashMap.insert(canvasName, texId);
757 m_gw[slot] = setupTextureWindow(input);
758
759 return slot;
760 }
761 return -1;
762 }
destroyCanvasQuickCanvas763 virtual void destroyCanvas(int canvasId)
764 {
765 btAssert(canvasId >= 0);
766 delete m_gt[canvasId];
767 m_gt[canvasId] = 0;
768 destroyTextureWindow(m_gw[canvasId]);
769 m_gw[canvasId] = 0;
770 m_curNumGraphWindows--;
771 }
setPixelQuickCanvas772 virtual void setPixel(int canvasId, int x, int y, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
773 {
774 btAssert(canvasId >= 0);
775 btAssert(canvasId < m_curNumGraphWindows);
776 m_gt[canvasId]->setPixel(x, y, red, green, blue, alpha);
777 }
778
getPixelQuickCanvas779 virtual void getPixel(int canvasId, int x, int y, unsigned char& red, unsigned char& green, unsigned char& blue, unsigned char& alpha)
780 {
781 btAssert(canvasId >= 0);
782 btAssert(canvasId < m_curNumGraphWindows);
783 m_gt[canvasId]->getPixel(x, y, red, green, blue, alpha);
784 }
785
refreshImageDataQuickCanvas786 virtual void refreshImageData(int canvasId)
787 {
788 m_gt[canvasId]->uploadImageData();
789 }
790 };
791
OpenGLExampleBrowser(class ExampleEntries * examples)792 OpenGLExampleBrowser::OpenGLExampleBrowser(class ExampleEntries* examples)
793 {
794 m_internalData = new OpenGLExampleBrowserInternalData;
795
796 gAllExamples = examples;
797 }
798
~OpenGLExampleBrowser()799 OpenGLExampleBrowser::~OpenGLExampleBrowser()
800 {
801 deleteDemo();
802 for (int i = 0; i < m_internalData->m_nodes.size(); i++)
803 {
804 delete m_internalData->m_nodes[i];
805 }
806 delete m_internalData->m_handler2;
807 for (int i = 0; i < m_internalData->m_handlers.size(); i++)
808 {
809 delete m_internalData->m_handlers[i];
810 }
811 m_internalData->m_handlers.clear();
812 m_internalData->m_nodes.clear();
813 delete s_parameterInterface;
814 s_parameterInterface = 0;
815 delete s_app->m_2dCanvasInterface;
816 s_app->m_2dCanvasInterface = 0;
817
818 #ifndef BT_NO_PROFILE
819 destroyProfileWindow(m_internalData->m_profWindow);
820 #endif
821
822 m_internalData->m_gui->exit();
823
824 delete m_internalData->m_gui;
825 delete m_internalData->m_gwenRenderer;
826 delete m_internalData->m_myTexLoader;
827
828 delete m_internalData->m_app;
829 s_app = 0;
830
831 delete m_internalData;
832
833 gFileImporterByExtension.clear();
834 gAllExamples = 0;
835 }
836
837 #include "EmptyExample.h"
838
init(int argc,char * argv[])839 bool OpenGLExampleBrowser::init(int argc, char* argv[])
840 {
841 b3CommandLineArgs args(argc, argv);
842
843 loadCurrentSettings(startFileName, args);
844 if (args.CheckCmdLineFlag("nogui"))
845 {
846 renderGrid = false;
847 renderGui = false;
848 }
849 if (args.CheckCmdLineFlag("tracing"))
850 {
851 b3ChromeUtilsStartTimings();
852 }
853 args.GetCmdLineArgument("fixed_timestep", gFixedTimeStep);
854 args.GetCmdLineArgument("png_skip_frames", gPngSkipFrames);
855 ///The OpenCL rigid body pipeline is experimental and
856 ///most OpenCL drivers and OpenCL compilers have issues with our kernels.
857 ///If you have a high-end desktop GPU such as AMD 7970 or better, or NVIDIA GTX 680 with up-to-date drivers
858 ///you could give it a try
859 ///Note that several old OpenCL physics examples still have to be ported over to this new Example Browser
860 if (args.CheckCmdLineFlag("enable_experimental_opencl"))
861 {
862 enable_experimental_opencl = true;
863 gAllExamples->initOpenCLExampleEntries();
864 }
865
866 if (args.CheckCmdLineFlag("disable_retina"))
867 {
868 gAllowRetina = false;
869 }
870
871 int width = 1024;
872 int height = 768;
873
874 if (args.CheckCmdLineFlag("width"))
875 {
876 args.GetCmdLineArgument("width", width);
877 }
878 if (args.CheckCmdLineFlag("height"))
879 {
880 args.GetCmdLineArgument("height", height);
881 }
882
883 #ifndef NO_OPENGL3
884 SimpleOpenGL3App* simpleApp = 0;
885 sUseOpenGL2 = args.CheckCmdLineFlag("opengl2");
886 args.GetCmdLineArgument("render_device", gRenderDevice);
887 args.GetCmdLineArgument("window_backend", gWindowBackend);
888 #else
889 sUseOpenGL2 = true;
890 #endif
891 const char* appTitle = "Bullet Physics ExampleBrowser";
892 #if defined(_DEBUG) || defined(DEBUG)
893 const char* optMode = "Debug build (slow)";
894 #else
895 const char* optMode = "Release build";
896 #endif
897
898 #ifdef B3_USE_GLFW
899 const char* glContext = "[glfw]";
900 #else
901 const char* glContext = "[btgl]";
902 #endif
903
904 if (sUseOpenGL2)
905 {
906 char title[1024];
907 sprintf(title, "%s using limited OpenGL2 fallback %s %s", appTitle, glContext, optMode);
908 s_app = new SimpleOpenGL2App(title, width, height);
909 s_app->m_renderer = new SimpleOpenGL2Renderer(width, height);
910 }
911
912 #ifndef NO_OPENGL3
913 else
914 {
915 char title[1024];
916 sprintf(title, "%s using OpenGL3+ %s %s", appTitle, glContext, optMode);
917 simpleApp = new SimpleOpenGL3App(title, width, height, gAllowRetina, gWindowBackend, gRenderDevice);
918 s_app = simpleApp;
919 }
920 #endif
921 m_internalData->m_app = s_app;
922 char* gVideoFileName = 0;
923 args.GetCmdLineArgument("mp4", gVideoFileName);
924 int gVideoFps = 0;
925 args.GetCmdLineArgument("mp4fps", gVideoFps);
926 if (gVideoFps)
927 {
928 simpleApp->setMp4Fps(gVideoFps);
929 }
930
931 #ifndef NO_OPENGL3
932 if (gVideoFileName)
933 simpleApp->dumpFramesToVideo(gVideoFileName);
934 #endif
935
936 s_instancingRenderer = s_app->m_renderer;
937 s_window = s_app->m_window;
938
939 width = s_window->getWidth();
940 height = s_window->getHeight();
941
942 prevMouseMoveCallback = s_window->getMouseMoveCallback();
943 s_window->setMouseMoveCallback(MyMouseMoveCallback);
944
945 prevMouseButtonCallback = s_window->getMouseButtonCallback();
946 s_window->setMouseButtonCallback(MyMouseButtonCallback);
947 prevKeyboardCallback = s_window->getKeyboardCallback();
948 s_window->setKeyboardCallback(MyKeyboardCallback);
949
950 s_app->m_renderer->getActiveCamera()->setCameraDistance(13);
951 s_app->m_renderer->getActiveCamera()->setCameraPitch(0);
952 s_app->m_renderer->getActiveCamera()->setCameraTargetPosition(0, 0, 0);
953
954 float mouseMoveMult = s_app->getMouseMoveMultiplier();
955 if (args.GetCmdLineArgument("mouse_move_multiplier", mouseMoveMult))
956 {
957 s_app->setMouseMoveMultiplier(mouseMoveMult);
958 }
959
960 float mouseWheelMult = s_app->getMouseWheelMultiplier();
961 if (args.GetCmdLineArgument("mouse_wheel_multiplier", mouseWheelMult))
962 {
963 s_app->setMouseWheelMultiplier(mouseWheelMult);
964 }
965
966 args.GetCmdLineArgument("shared_memory_key", gSharedMemoryKey);
967
968 float red, green, blue;
969 s_app->getBackgroundColor(&red, &green, &blue);
970 args.GetCmdLineArgument("background_color_red", red);
971 args.GetCmdLineArgument("background_color_green", green);
972 args.GetCmdLineArgument("background_color_blue", blue);
973 s_app->setBackgroundColor(red, green, blue);
974
975 b3SetCustomWarningMessageFunc(MyGuiPrintf);
976 b3SetCustomPrintfFunc(MyGuiPrintf);
977 b3SetCustomErrorMessageFunc(MyStatusBarError);
978
979 assert(glGetError() == GL_NO_ERROR);
980
981 {
982 GL3TexLoader* myTexLoader = new GL3TexLoader;
983 m_internalData->m_myTexLoader = myTexLoader;
984
985 if (sUseOpenGL2)
986 {
987 m_internalData->m_gwenRenderer = new Gwen::Renderer::OpenGL_DebugFont(s_window->getRetinaScale());
988 }
989 #ifndef NO_OPENGL3
990 else
991 {
992 sth_stash* fontstash = simpleApp->getFontStash();
993 m_internalData->m_gwenRenderer = new GwenOpenGL3CoreRenderer(simpleApp->m_primRenderer, fontstash, width, height, s_window->getRetinaScale(), myTexLoader);
994 }
995 #endif
996
997 gui2 = new GwenUserInterface;
998
999 m_internalData->m_gui = gui2;
1000
1001 m_internalData->m_myTexLoader = myTexLoader;
1002
1003 gui2->init(width, height, m_internalData->m_gwenRenderer, s_window->getRetinaScale());
1004 }
1005 //gui = 0;// new GwenUserInterface;
1006
1007 GL3TexLoader* myTexLoader = m_internalData->m_myTexLoader;
1008 // = myTexLoader;
1009
1010 //
1011
1012 if (gui2)
1013 {
1014 // gui->getInternalData()->m_explorerPage
1015 Gwen::Controls::TreeControl* tree = gui2->getInternalData()->m_explorerTreeCtrl;
1016
1017 //gui->getInternalData()->pRenderer->setTextureLoader(myTexLoader);
1018
1019 #ifndef BT_NO_PROFILE
1020 s_profWindow = setupProfileWindow(gui2->getInternalData());
1021 m_internalData->m_profWindow = s_profWindow;
1022 profileWindowSetVisible(s_profWindow, false);
1023 #endif //BT_NO_PROFILE
1024 gui2->setFocus();
1025
1026 s_parameterInterface = s_app->m_parameterInterface = new GwenParameterInterface(gui2->getInternalData());
1027 s_app->m_2dCanvasInterface = new QuickCanvas(myTexLoader);
1028
1029 ///add some demos to the gAllExamples
1030
1031 int numDemos = gAllExamples->getNumRegisteredExamples();
1032
1033 //char nodeText[1024];
1034 //int curDemo = 0;
1035 int selectedDemo = 0;
1036 Gwen::Controls::TreeNode* curNode = tree;
1037 m_internalData->m_handler2 = new MyMenuItemHander(-1);
1038
1039 char* demoNameFromCommandOption = 0;
1040 args.GetCmdLineArgument("start_demo_name", demoNameFromCommandOption);
1041 if (demoNameFromCommandOption)
1042 {
1043 selectedDemo = -1;
1044 }
1045
1046 tree->onReturnKeyDown.Add(m_internalData->m_handler2, &MyMenuItemHander::onButtonD);
1047 int firstAvailableDemoIndex = -1;
1048 Gwen::Controls::TreeNode* firstNode = 0;
1049
1050 for (int d = 0; d < numDemos; d++)
1051 {
1052 // sprintf(nodeText, "Node %d", i);
1053 Gwen::UnicodeString nodeUText = Gwen::Utility::StringToUnicode(gAllExamples->getExampleName(d));
1054 if (gAllExamples->getExampleCreateFunc(d)) //was test for gAllExamples[d].m_menuLevel==1
1055 {
1056 Gwen::Controls::TreeNode* pNode = curNode->AddNode(nodeUText);
1057
1058 if (firstAvailableDemoIndex < 0)
1059 {
1060 firstAvailableDemoIndex = d;
1061 firstNode = pNode;
1062 }
1063
1064 if (d == selectedDemo)
1065 {
1066 firstAvailableDemoIndex = d;
1067 firstNode = pNode;
1068 //pNode->SetSelected(true);
1069 //tree->ExpandAll();
1070 // tree->ForceUpdateScrollBars();
1071 //tree->OnKeyLeft(true);
1072 // tree->OnKeyRight(true);
1073
1074 //tree->ExpandAll();
1075
1076 // selectDemo(d);
1077 }
1078
1079 if (demoNameFromCommandOption)
1080 {
1081 const char* demoName = gAllExamples->getExampleName(d);
1082 int res = strcmp(demoName, demoNameFromCommandOption);
1083 if (res == 0)
1084 {
1085 firstAvailableDemoIndex = d;
1086 firstNode = pNode;
1087 }
1088 }
1089
1090 #if 1
1091 MyMenuItemHander* handler = new MyMenuItemHander(d);
1092 m_internalData->m_handlers.push_back(handler);
1093
1094 pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonA);
1095 pNode->GetButton()->onDoubleClick.Add(handler, &MyMenuItemHander::onButtonB);
1096 pNode->GetButton()->onDown.Add(handler, &MyMenuItemHander::onButtonC);
1097 pNode->onSelect.Add(handler, &MyMenuItemHander::onButtonE);
1098 pNode->onReturnKeyDown.Add(handler, &MyMenuItemHander::onButtonG);
1099 pNode->onSelectChange.Add(handler, &MyMenuItemHander::onButtonF);
1100
1101 #endif
1102 // pNode->onKeyReturn.Add(handler, &MyMenuItemHander::onButtonD);
1103 // pNode->GetButton()->onKeyboardReturn.Add(handler, &MyMenuItemHander::onButtonD);
1104 // pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonD);
1105 // pNode->onKeyboardPressed.Add(handler, &MyMenuItemHander::onButtonD);
1106 // pNode->OnKeyPress
1107 }
1108 else
1109 {
1110 curNode = tree->AddNode(nodeUText);
1111 m_internalData->m_nodes.push_back(curNode);
1112 }
1113 }
1114
1115 if (sCurrentDemo == 0)
1116 {
1117 if (firstAvailableDemoIndex >= 0)
1118 {
1119 firstNode->SetSelected(true);
1120 while (firstNode != tree)
1121 {
1122 firstNode->ExpandAll();
1123 firstNode = (Gwen::Controls::TreeNode*)firstNode->GetParent();
1124 }
1125
1126 selectDemo(firstAvailableDemoIndex);
1127 }
1128 }
1129 free(demoNameFromCommandOption);
1130 demoNameFromCommandOption = 0;
1131
1132 btAssert(sCurrentDemo != 0);
1133 if (sCurrentDemo == 0)
1134 {
1135 printf("Error, no demo/example\n");
1136 exit(0);
1137 }
1138
1139 gui2->registerFileOpenCallback(fileOpenCallback);
1140 gui2->registerQuitCallback(quitCallback);
1141 }
1142
1143 return true;
1144 }
1145
getCurrentExample()1146 CommonExampleInterface* OpenGLExampleBrowser::getCurrentExample()
1147 {
1148 btAssert(sCurrentDemo);
1149 return sCurrentDemo;
1150 }
1151
requestedExit()1152 bool OpenGLExampleBrowser::requestedExit()
1153 {
1154 return s_window->requestedExit();
1155 }
1156
updateGraphics()1157 void OpenGLExampleBrowser::updateGraphics()
1158 {
1159 if (sCurrentDemo)
1160 {
1161 if (!pauseSimulation || singleStepSimulation)
1162 {
1163 //B3_PROFILE("sCurrentDemo->updateGraphics");
1164 sCurrentDemo->updateGraphics();
1165 }
1166 }
1167 }
1168
update(float deltaTime)1169 void OpenGLExampleBrowser::update(float deltaTime)
1170 {
1171
1172 b3ChromeUtilsEnableProfiling();
1173
1174 if (!gEnableRenderLoop && !singleStepSimulation)
1175 {
1176 B3_PROFILE("updateGraphics");
1177 sCurrentDemo->updateGraphics();
1178 return;
1179 }
1180
1181 B3_PROFILE("OpenGLExampleBrowser::update");
1182 //assert(glGetError() == GL_NO_ERROR);
1183 {
1184 B3_PROFILE("s_instancingRenderer");
1185 s_instancingRenderer->init();
1186 }
1187 DrawGridData dg;
1188 dg.upAxis = s_app->getUpAxis();
1189
1190 {
1191 BT_PROFILE("Update Camera and Light");
1192
1193 s_instancingRenderer->updateCamera(dg.upAxis);
1194 }
1195
1196 static int frameCount = 0;
1197 frameCount++;
1198
1199 if (0)
1200 {
1201 BT_PROFILE("Draw frame counter");
1202 char bla[1024];
1203 sprintf(bla, "Frame %d", frameCount);
1204 s_app->drawText(bla, 10, 10);
1205 }
1206
1207 if (gPngFileName)
1208 {
1209 static int skip = 0;
1210 skip--;
1211 if (skip < 0)
1212 {
1213 skip = gPngSkipFrames;
1214 //printf("gPngFileName=%s\n",gPngFileName);
1215 static int s_frameCount = 0;
1216
1217 sprintf(staticPngFileName, "%s%d.png", gPngFileName, s_frameCount++);
1218 //b3Printf("Made screenshot %s",staticPngFileName);
1219 s_app->dumpNextFrameToPng(staticPngFileName);
1220 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1221 }
1222 }
1223
1224 if (sCurrentDemo)
1225 {
1226 if (!pauseSimulation || singleStepSimulation)
1227 {
1228 //printf("---------------------------------------------------\n");
1229 //printf("Framecount = %d\n",frameCount);
1230 B3_PROFILE("sCurrentDemo->stepSimulation");
1231
1232 if (gFixedTimeStep > 0)
1233 {
1234
1235 sCurrentDemo->stepSimulation(gFixedTimeStep);
1236 }
1237 else
1238 {
1239 sCurrentDemo->stepSimulation(deltaTime); //1./60.f);
1240 }
1241 }
1242
1243 if (renderGrid)
1244 {
1245 BT_PROFILE("Draw Grid");
1246 //glPolygonOffset(3.0, 3);
1247 //glEnable(GL_POLYGON_OFFSET_FILL);
1248 s_app->drawGrid(dg);
1249 }
1250 if (renderVisualGeometry && ((gDebugDrawFlags & btIDebugDraw::DBG_DrawWireframe) == 0))
1251 {
1252 if (visualWireframe)
1253 {
1254 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1255 }
1256 BT_PROFILE("Render Scene");
1257 sCurrentDemo->renderScene();
1258 }
1259 else
1260 {
1261 B3_PROFILE("physicsDebugDraw");
1262 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1263 sCurrentDemo->physicsDebugDraw(gDebugDrawFlags);
1264 }
1265 }
1266
1267 {
1268 if (gui2 && s_guiHelper && s_guiHelper->getRenderInterface() && s_guiHelper->getRenderInterface()->getActiveCamera())
1269 {
1270 B3_PROFILE("setStatusBarMessage");
1271 char msg[1024];
1272 float camDist = s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraDistance();
1273 float pitch = s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraPitch();
1274 float yaw = s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraYaw();
1275 float camTarget[3];
1276 float camPos[3];
1277 s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraPosition(camPos);
1278 s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraTargetPosition(camTarget);
1279 sprintf(msg, "camTargetPos=%2.2f,%2.2f,%2.2f, dist=%2.2f, pitch=%2.2f, yaw=%2.2f", camTarget[0], camTarget[1], camTarget[2], camDist, pitch, yaw);
1280 gui2->setStatusBarMessage(msg, true);
1281 }
1282 }
1283
1284 static int toggle = 1;
1285 if (renderGui)
1286 {
1287 B3_PROFILE("renderGui");
1288 #ifndef BT_NO_PROFILE
1289
1290 if (!pauseSimulation || singleStepSimulation)
1291 {
1292 if (isProfileWindowVisible(s_profWindow))
1293 {
1294 processProfileData(s_profWindow, false);
1295 }
1296 }
1297 #endif //#ifndef BT_NO_PROFILE
1298
1299 {
1300 B3_PROFILE("updateOpenGL");
1301 if (sUseOpenGL2)
1302 {
1303 saveOpenGLState(s_instancingRenderer->getScreenWidth() * s_window->getRetinaScale(), s_instancingRenderer->getScreenHeight() * s_window->getRetinaScale());
1304 }
1305
1306 if (m_internalData->m_gui)
1307 {
1308 gBlockGuiMessages = true;
1309 m_internalData->m_gui->draw(s_instancingRenderer->getScreenWidth(), s_instancingRenderer->getScreenHeight());
1310
1311 gBlockGuiMessages = false;
1312 }
1313
1314 if (sUseOpenGL2)
1315 {
1316 restoreOpenGLState();
1317 }
1318 }
1319 }
1320
1321 singleStepSimulation = false;
1322
1323 toggle = 1 - toggle;
1324 {
1325 BT_PROFILE("Sync Parameters");
1326 if (s_parameterInterface)
1327 {
1328 s_parameterInterface->syncParameters();
1329 }
1330 }
1331 {
1332 BT_PROFILE("Swap Buffers");
1333 s_app->swapBuffer();
1334 }
1335
1336 if (gui2)
1337 {
1338 B3_PROFILE("forceUpdateScrollBars");
1339 gui2->forceUpdateScrollBars();
1340 }
1341 }
1342
setSharedMemoryInterface(class SharedMemoryInterface * sharedMem)1343 void OpenGLExampleBrowser::setSharedMemoryInterface(class SharedMemoryInterface* sharedMem)
1344 {
1345 gDisableDemoSelection = true;
1346 sSharedMem = sharedMem;
1347 }
1348