Files
bullet3/examples/ExampleBrowser/OpenGLExampleBrowser.cpp
Chuyuan Fu 7aba1f9e8a Use two SI solvers as blocks in block solver.
In the btBlockSolver we are experimenting with, we have SI for both multibody and rigid body. I'm currently replacing rigid body SI solver with two smaller SI solvers. The two examples provided by RigidBodyBoxes.h should have the same behavior.
2019-03-25 14:41:58 -07:00

1328 lines
32 KiB
C++

#include "OpenGLExampleBrowser.h"
#include "LinearMath/btQuickprof.h"
#include "../OpenGLWindow/OpenGLInclude.h"
#include "../OpenGLWindow/SimpleOpenGL2App.h"
#ifndef NO_OPENGL3
#include "../OpenGLWindow/SimpleOpenGL3App.h"
#endif
#include "../CommonInterfaces/CommonRenderInterface.h"
#ifdef __APPLE__
#include "../OpenGLWindow/MacOpenGLWindow.h"
#else
#ifdef _WIN32
#include "../OpenGLWindow/Win32OpenGLWindow.h"
#else
//let's cross the fingers it is Linux/X11
#ifdef BT_USE_EGL
#include "../OpenGLWindow/EGLOpenGLWindow.h"
#else
#include "../OpenGLWindow/X11OpenGLWindow.h"
#endif //BT_USE_EGL
#endif //_WIN32
#endif //__APPLE__
#include "../ThirdPartyLibs/Gwen/Renderers/OpenGL_DebugFont.h"
#include "LinearMath/btThreads.h"
#include "Bullet3Common/b3Vector3.h"
#include "assert.h"
#include <stdio.h>
#include "GwenGUISupport/gwenInternalData.h"
#include "GwenGUISupport/gwenUserInterface.h"
#include "../Utils/b3Clock.h"
#include "../Utils/ChromeTraceUtil.h"
#include "GwenGUISupport/GwenParameterInterface.h"
#ifndef BT_NO_PROFILE
#include "GwenGUISupport/GwenProfileWindow.h"
#endif
#include "GwenGUISupport/GwenTextureWindow.h"
#include "GwenGUISupport/GraphingTexture.h"
#include "../CommonInterfaces/Common2dCanvasInterface.h"
#include "../CommonInterfaces/CommonExampleInterface.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "../OpenGLWindow/SimpleCamera.h"
#include "../OpenGLWindow/SimpleOpenGL2Renderer.h"
#include "ExampleEntries.h"
#include "OpenGLGuiHelper.h"
#include "Bullet3Common/b3FileUtils.h"
#include "LinearMath/btIDebugDraw.h"
//quick test for file import, @todo(erwincoumans) make it more general and add other file formats
#include "../Importers/ImportURDFDemo/ImportURDFSetup.h"
#include "../Importers/ImportBullet/SerializeSetup.h"
#include "Bullet3Common/b3HashMap.h"
struct GL3TexLoader : public MyTextureLoader
{
b3HashMap<b3HashString, GLint> m_hashMap;
virtual void LoadTexture(Gwen::Texture* pTexture)
{
Gwen::String namestr = pTexture->name.Get();
const char* n = namestr.c_str();
GLint* texIdPtr = m_hashMap[n];
if (texIdPtr)
{
pTexture->m_intData = *texIdPtr;
}
}
virtual void FreeTexture(Gwen::Texture* pTexture)
{
}
};
struct OpenGLExampleBrowserInternalData
{
Gwen::Renderer::Base* m_gwenRenderer;
CommonGraphicsApp* m_app;
#ifndef BT_NO_PROFILE
MyProfileWindow* m_profWindow;
#endif //BT_NO_PROFILE
btAlignedObjectArray<Gwen::Controls::TreeNode*> m_nodes;
GwenUserInterface* m_gui;
GL3TexLoader* m_myTexLoader;
struct MyMenuItemHander* m_handler2;
btAlignedObjectArray<MyMenuItemHander*> m_handlers;
OpenGLExampleBrowserInternalData()
: m_gwenRenderer(0),
m_app(0),
// m_profWindow(0),
m_gui(0),
m_myTexLoader(0),
m_handler2(0)
{
}
};
static CommonGraphicsApp* s_app = 0;
static CommonWindowInterface* s_window = 0;
static CommonParameterInterface* s_parameterInterface = 0;
static CommonRenderInterface* s_instancingRenderer = 0;
static OpenGLGuiHelper* s_guiHelper = 0;
#ifndef BT_NO_PROFILE
static MyProfileWindow* s_profWindow = 0;
#endif //BT_NO_PROFILE
static SharedMemoryInterface* sSharedMem = 0;
#define DEMO_SELECTION_COMBOBOX 13
const char* startFileName = "0_Bullet3Demo.txt";
char staticPngFileName[1024];
//static GwenUserInterface* gui = 0;
static GwenUserInterface* gui2 = 0;
static int sCurrentDemoIndex = -1;
static int sCurrentHightlighted = 0;
static CommonExampleInterface* sCurrentDemo = 0;
static b3AlignedObjectArray<const char*> allNames;
static float gFixedTimeStep = 0;
bool gAllowRetina = true;
bool gDisableDemoSelection = false;
int gRenderDevice = -1;
int gWindowBackend = 0;
static class ExampleEntries* gAllExamples = 0;
bool sUseOpenGL2 = false;
#ifndef USE_OPENGL3
extern bool useShadowMap;
#endif
bool visualWireframe = false;
static bool renderVisualGeometry = true;
static bool renderGrid = true;
static bool gEnableRenderLoop = true;
bool renderGui = true;
static bool enable_experimental_opencl = false;
static bool gEnableDefaultKeyboardShortcuts = true;
static bool gEnableDefaultMousePicking = true;
int gDebugDrawFlags = 0;
static bool pauseSimulation = false;
static bool singleStepSimulation = false;
int midiBaseIndex = 176;
extern bool gDisableDeactivation;
int gSharedMemoryKey = -1;
///some quick test variable for the OpenCL examples
int gPreferredOpenCLDeviceIndex = -1;
int gPreferredOpenCLPlatformIndex = -1;
int gGpuArraySizeX = 45;
int gGpuArraySizeY = 55;
int gGpuArraySizeZ = 45;
//#include <float.h>
//unsigned int fp_control_state = _controlfp(_EM_INEXACT, _MCW_EM);
void deleteDemo()
{
if (sCurrentDemo)
{
sCurrentDemo->exitPhysics();
s_instancingRenderer->removeAllInstances();
delete sCurrentDemo;
sCurrentDemo = 0;
delete s_guiHelper;
s_guiHelper = 0;
// CProfileManager::CleanupMemory();
}
}
const char* gPngFileName = 0;
int gPngSkipFrames = 0;
b3KeyboardCallback prevKeyboardCallback = 0;
void MyKeyboardCallback(int key, int state)
{
//b3Printf("key=%d, state=%d", key, state);
bool handled = false;
if (renderGui)
{
if (gui2 && !handled)
{
handled = gui2->keyboardCallback(key, state);
}
}
if (!handled && sCurrentDemo)
{
handled = sCurrentDemo->keyboardCallback(key, state);
}
//checkout: is it desired to ignore keys, if the demo already handles them?
//if (handled)
// return;
if (gEnableDefaultKeyboardShortcuts)
{
if (key == 'a' && state)
{
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawAabb;
}
if (key == 'c' && state)
{
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawContactPoints;
}
if (key == 'd' && state)
{
gDebugDrawFlags ^= btIDebugDraw::DBG_NoDeactivation;
gDisableDeactivation = ((gDebugDrawFlags & btIDebugDraw::DBG_NoDeactivation) != 0);
}
if (key == 'j' && state)
{
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawFrames;
}
if (key == 'k' && state)
{
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawConstraints;
}
if (key == 'l' && state)
{
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawConstraintLimits;
}
if (key == 'w' && state)
{
visualWireframe = !visualWireframe;
gDebugDrawFlags ^= btIDebugDraw::DBG_DrawWireframe;
}
if (key == 'v' && state)
{
renderVisualGeometry = !renderVisualGeometry;
}
if (key == 'g' && state)
{
renderGrid = !renderGrid;
renderGui = !renderGui;
}
if (key == 'i' && state)
{
pauseSimulation = !pauseSimulation;
}
if (key == 'o' && state)
{
singleStepSimulation = true;
}
if (key == 'p')
{
if (state)
{
b3ChromeUtilsStartTimings();
}
else
{
b3ChromeUtilsStopTimingsAndWriteJsonFile("timings");
}
}
#ifndef NO_OPENGL3
if (key == 's' && state)
{
useShadowMap = !useShadowMap;
}
#endif
if (key == B3G_F1)
{
static int count = 0;
if (state)
{
b3Printf("F1 pressed %d", count++);
if (gPngFileName)
{
b3Printf("disable image dump");
gPngFileName = 0;
}
else
{
gPngFileName = gAllExamples->getExampleName(sCurrentDemoIndex);
b3Printf("enable image dump %s", gPngFileName);
}
}
else
{
b3Printf("F1 released %d", count++);
}
}
}
if (key == B3G_ESCAPE && s_window)
{
s_window->setRequestExit();
}
if (prevKeyboardCallback)
prevKeyboardCallback(key, state);
}
b3MouseMoveCallback prevMouseMoveCallback = 0;
static void MyMouseMoveCallback(float x, float y)
{
bool handled = false;
if (sCurrentDemo)
handled = sCurrentDemo->mouseMoveCallback(x, y);
if (renderGui)
{
if (!handled && gui2)
handled = gui2->mouseMoveCallback(x, y);
}
if (!handled)
{
if (prevMouseMoveCallback)
prevMouseMoveCallback(x, y);
}
}
b3MouseButtonCallback prevMouseButtonCallback = 0;
static void MyMouseButtonCallback(int button, int state, float x, float y)
{
bool handled = false;
//try picking first
if (sCurrentDemo)
handled = sCurrentDemo->mouseButtonCallback(button, state, x, y);
if (renderGui)
{
if (!handled && gui2)
handled = gui2->mouseButtonCallback(button, state, x, y);
}
if (!handled)
{
if (prevMouseButtonCallback)
prevMouseButtonCallback(button, state, x, y);
}
// b3DefaultMouseButtonCallback(button,state,x,y);
}
#include <string.h>
struct FileImporterByExtension
{
std::string m_extension;
CommonExampleInterface::CreateFunc* m_createFunc;
};
static btAlignedObjectArray<FileImporterByExtension> gFileImporterByExtension;
void OpenGLExampleBrowser::registerFileImporter(const char* extension, CommonExampleInterface::CreateFunc* createFunc)
{
FileImporterByExtension fi;
fi.m_extension = extension;
fi.m_createFunc = createFunc;
gFileImporterByExtension.push_back(fi);
}
#include "../SharedMemory/SharedMemoryPublic.h"
void OpenGLExampleBrowserVisualizerFlagCallback(int flag, bool enable)
{
if (flag == COV_ENABLE_Y_AXIS_UP)
{
//either Y = up or Z
int upAxis = enable ? 1 : 2;
s_app->setUpAxis(upAxis);
}
if (flag == COV_ENABLE_RENDERING)
{
gEnableRenderLoop = (enable != 0);
}
if (flag == COV_ENABLE_SINGLE_STEP_RENDERING)
{
if (enable)
{
gEnableRenderLoop = false;
singleStepSimulation = true;
}
else
{
gEnableRenderLoop = true;
singleStepSimulation = false;
}
}
if (flag == COV_ENABLE_SHADOWS)
{
useShadowMap = enable;
}
if (flag == COV_ENABLE_GUI)
{
renderGui = enable;
renderGrid = enable;
}
if (flag == COV_ENABLE_KEYBOARD_SHORTCUTS)
{
gEnableDefaultKeyboardShortcuts = enable;
}
if (flag == COV_ENABLE_MOUSE_PICKING)
{
gEnableDefaultMousePicking = enable;
}
if (flag == COV_ENABLE_WIREFRAME)
{
visualWireframe = enable;
if (visualWireframe)
{
gDebugDrawFlags |= btIDebugDraw::DBG_DrawWireframe;
}
else
{
gDebugDrawFlags &= ~btIDebugDraw::DBG_DrawWireframe;
}
}
}
void openFileDemo(const char* filename)
{
deleteDemo();
s_guiHelper = new OpenGLGuiHelper(s_app, sUseOpenGL2);
s_guiHelper->setVisualizerFlagCallback(OpenGLExampleBrowserVisualizerFlagCallback);
s_parameterInterface->removeAllParameters();
CommonExampleOptions options(s_guiHelper, 1);
options.m_fileName = filename;
char fullPath[1024];
sprintf(fullPath, "%s", filename);
b3FileUtils::toLower(fullPath);
for (int i = 0; i < gFileImporterByExtension.size(); i++)
{
if (strstr(fullPath, gFileImporterByExtension[i].m_extension.c_str()))
{
sCurrentDemo = gFileImporterByExtension[i].m_createFunc(options);
}
}
if (sCurrentDemo)
{
sCurrentDemo->initPhysics();
sCurrentDemo->resetCamera();
}
}
void selectDemo(int demoIndex)
{
bool resetCamera = (sCurrentDemoIndex != demoIndex);
sCurrentDemoIndex = demoIndex;
sCurrentHightlighted = demoIndex;
int numDemos = gAllExamples->getNumRegisteredExamples();
if (demoIndex > numDemos)
{
demoIndex = 0;
}
deleteDemo();
CommonExampleInterface::CreateFunc* func = gAllExamples->getExampleCreateFunc(demoIndex);
if (func)
{
if (s_parameterInterface)
{
s_parameterInterface->removeAllParameters();
}
int option = gAllExamples->getExampleOption(demoIndex);
s_guiHelper = new OpenGLGuiHelper(s_app, sUseOpenGL2);
s_guiHelper->setVisualizerFlagCallback(OpenGLExampleBrowserVisualizerFlagCallback);
CommonExampleOptions options(s_guiHelper, option);
options.m_sharedMem = sSharedMem;
sCurrentDemo = (*func)(options);
if (sCurrentDemo)
{
if (gui2)
{
gui2->setStatusBarMessage("Status: OK", false);
}
b3Printf("Selected demo: %s", gAllExamples->getExampleName(demoIndex));
if (gui2)
{
gui2->setExampleDescription(gAllExamples->getExampleDescription(demoIndex));
}
sCurrentDemo->initPhysics();
if (resetCamera)
{
sCurrentDemo->resetCamera();
}
}
}
}
#include <stdio.h>
static void saveCurrentSettings(int currentEntry, const char* startFileName)
{
FILE* f = fopen(startFileName, "w");
if (f)
{
fprintf(f, "--start_demo_name=%s\n", gAllExamples->getExampleName(sCurrentDemoIndex));
fprintf(f, "--mouse_move_multiplier=%f\n", s_app->getMouseMoveMultiplier());
fprintf(f, "--mouse_wheel_multiplier=%f\n", s_app->getMouseWheelMultiplier());
float red, green, blue;
s_app->getBackgroundColor(&red, &green, &blue);
fprintf(f, "--background_color_red= %f\n", red);
fprintf(f, "--background_color_green= %f\n", green);
fprintf(f, "--background_color_blue= %f\n", blue);
fprintf(f, "--fixed_timestep= %f\n", gFixedTimeStep);
if (!gAllowRetina)
{
fprintf(f, "--disable_retina");
}
if (enable_experimental_opencl)
{
fprintf(f, "--enable_experimental_opencl\n");
}
// if (sUseOpenGL2 )
// {
// fprintf(f,"--opengl2\n");
// }
fclose(f);
}
};
static void loadCurrentSettings(const char* startFileName, b3CommandLineArgs& args)
{
//int currentEntry= 0;
FILE* f = fopen(startFileName, "r");
if (f)
{
char oneline[1024];
char* argv[] = {0, &oneline[0]};
while (fgets(oneline, 1024, f) != NULL)
{
char* pos;
if ((pos = strchr(oneline, '\n')) != NULL)
*pos = '\0';
args.addArgs(2, argv);
}
fclose(f);
}
};
void MyComboBoxCallback(int comboId, const char* item)
{
//printf("comboId = %d, item = %s\n",comboId, item);
if (comboId == DEMO_SELECTION_COMBOBOX)
{
//find selected item
for (int i = 0; i < allNames.size(); i++)
{
if (strcmp(item, allNames[i]) == 0)
{
selectDemo(i);
saveCurrentSettings(sCurrentDemoIndex, startFileName);
break;
}
}
}
}
//in case of multi-threading, don't submit messages while the GUI is rendering (causing crashes)
static bool gBlockGuiMessages = false;
void MyGuiPrintf(const char* msg)
{
printf("b3Printf: %s\n", msg);
if (!gDisableDemoSelection && !gBlockGuiMessages)
{
gui2->textOutput(msg);
gui2->forceUpdateScrollBars();
}
}
void MyStatusBarPrintf(const char* msg)
{
printf("b3Printf: %s\n", msg);
if (!gDisableDemoSelection && !gBlockGuiMessages)
{
bool isLeft = true;
gui2->setStatusBarMessage(msg, isLeft);
}
}
void MyStatusBarError(const char* msg)
{
printf("Warning: %s\n", msg);
if (!gDisableDemoSelection && !gBlockGuiMessages)
{
bool isLeft = false;
gui2->setStatusBarMessage(msg, isLeft);
gui2->textOutput(msg);
gui2->forceUpdateScrollBars();
}
btAssert(0);
}
struct MyMenuItemHander : public Gwen::Event::Handler
{
int m_buttonId;
MyMenuItemHander(int buttonId)
: m_buttonId(buttonId)
{
}
void onButtonA(Gwen::Controls::Base* pControl)
{
//const Gwen::String& name = pControl->GetName();
Gwen::Controls::TreeNode* node = (Gwen::Controls::TreeNode*)pControl;
// Gwen::Controls::Label* l = node->GetButton();
Gwen::UnicodeString la = node->GetButton()->GetText(); // node->GetButton()->GetName();// GetText();
Gwen::String laa = Gwen::Utility::UnicodeToString(la);
// const char* ha = laa.c_str();
//printf("selected %s\n", ha);
//int dep = but->IsDepressed();
//int tog = but->GetToggleState();
// if (m_data->m_toggleButtonCallback)
// (*m_data->m_toggleButtonCallback)(m_buttonId, tog);
}
void onButtonB(Gwen::Controls::Base* pControl)
{
Gwen::Controls::Label* label = (Gwen::Controls::Label*)pControl;
Gwen::UnicodeString la = label->GetText(); // node->GetButton()->GetName();// GetText();
Gwen::String laa = Gwen::Utility::UnicodeToString(la);
//const char* ha = laa.c_str();
if (!gDisableDemoSelection)
{
selectDemo(sCurrentHightlighted);
saveCurrentSettings(sCurrentDemoIndex, startFileName);
}
}
void onButtonC(Gwen::Controls::Base* pControl)
{
/*Gwen::Controls::Label* label = (Gwen::Controls::Label*) pControl;
Gwen::UnicodeString la = label->GetText();// node->GetButton()->GetName();// GetText();
Gwen::String laa = Gwen::Utility::UnicodeToString(la);
const char* ha = laa.c_str();
printf("onButtonC ! %s\n", ha);
*/
}
void onButtonD(Gwen::Controls::Base* pControl)
{
/* Gwen::Controls::Label* label = (Gwen::Controls::Label*) pControl;
Gwen::UnicodeString la = label->GetText();// node->GetButton()->GetName();// GetText();
Gwen::String laa = Gwen::Utility::UnicodeToString(la);
const char* ha = laa.c_str();
*/
// printf("onKeyReturn ! \n");
if (!gDisableDemoSelection)
{
selectDemo(sCurrentHightlighted);
saveCurrentSettings(sCurrentDemoIndex, startFileName);
}
}
void onButtonE(Gwen::Controls::Base* pControl)
{
// printf("select %d\n",m_buttonId);
sCurrentHightlighted = m_buttonId;
gui2->setExampleDescription(gAllExamples->getExampleDescription(sCurrentHightlighted));
}
void onButtonF(Gwen::Controls::Base* pControl)
{
//printf("selection changed!\n");
}
void onButtonG(Gwen::Controls::Base* pControl)
{
//printf("onButtonG !\n");
}
};
void quitCallback()
{
s_window->setRequestExit();
}
void fileOpenCallback()
{
char filename[1024];
int len = s_window->fileOpenDialog(filename, 1024);
if (len)
{
//todo(erwincoumans) check if it is actually URDF
//printf("file open:%s\n", filename);
openFileDemo(filename);
}
}
#define MAX_GRAPH_WINDOWS 5
struct QuickCanvas : public Common2dCanvasInterface
{
GL3TexLoader* m_myTexLoader;
MyGraphWindow* m_gw[MAX_GRAPH_WINDOWS];
GraphingTexture* m_gt[MAX_GRAPH_WINDOWS];
int m_curNumGraphWindows;
QuickCanvas(GL3TexLoader* myTexLoader)
: m_myTexLoader(myTexLoader),
m_curNumGraphWindows(0)
{
for (int i = 0; i < MAX_GRAPH_WINDOWS; i++)
{
m_gw[i] = 0;
m_gt[i] = 0;
}
}
virtual ~QuickCanvas() {}
virtual int createCanvas(const char* canvasName, int width, int height, int xPos, int yPos)
{
if (m_curNumGraphWindows < MAX_GRAPH_WINDOWS)
{
//find a slot
int slot = m_curNumGraphWindows;
btAssert(slot < MAX_GRAPH_WINDOWS);
if (slot >= MAX_GRAPH_WINDOWS)
return 0; //don't crash
m_curNumGraphWindows++;
MyGraphInput input(gui2->getInternalData());
input.m_width = width;
input.m_height = height;
input.m_xPos = xPos;
input.m_yPos = yPos;
input.m_name = canvasName;
input.m_texName = canvasName;
m_gt[slot] = new GraphingTexture;
m_gt[slot]->create(width, height);
int texId = m_gt[slot]->getTextureId();
m_myTexLoader->m_hashMap.insert(canvasName, texId);
m_gw[slot] = setupTextureWindow(input);
return slot;
}
return -1;
}
virtual void destroyCanvas(int canvasId)
{
btAssert(canvasId >= 0);
delete m_gt[canvasId];
m_gt[canvasId] = 0;
destroyTextureWindow(m_gw[canvasId]);
m_gw[canvasId] = 0;
m_curNumGraphWindows--;
}
virtual void setPixel(int canvasId, int x, int y, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
{
btAssert(canvasId >= 0);
btAssert(canvasId < m_curNumGraphWindows);
m_gt[canvasId]->setPixel(x, y, red, green, blue, alpha);
}
virtual void getPixel(int canvasId, int x, int y, unsigned char& red, unsigned char& green, unsigned char& blue, unsigned char& alpha)
{
btAssert(canvasId >= 0);
btAssert(canvasId < m_curNumGraphWindows);
m_gt[canvasId]->getPixel(x, y, red, green, blue, alpha);
}
virtual void refreshImageData(int canvasId)
{
m_gt[canvasId]->uploadImageData();
}
};
OpenGLExampleBrowser::OpenGLExampleBrowser(class ExampleEntries* examples)
{
m_internalData = new OpenGLExampleBrowserInternalData;
gAllExamples = examples;
}
OpenGLExampleBrowser::~OpenGLExampleBrowser()
{
deleteDemo();
for (int i = 0; i < m_internalData->m_nodes.size(); i++)
{
delete m_internalData->m_nodes[i];
}
delete m_internalData->m_handler2;
for (int i = 0; i < m_internalData->m_handlers.size(); i++)
{
delete m_internalData->m_handlers[i];
}
m_internalData->m_handlers.clear();
m_internalData->m_nodes.clear();
delete s_parameterInterface;
s_parameterInterface = 0;
delete s_app->m_2dCanvasInterface;
s_app->m_2dCanvasInterface = 0;
#ifndef BT_NO_PROFILE
destroyProfileWindow(m_internalData->m_profWindow);
#endif
m_internalData->m_gui->exit();
delete m_internalData->m_gui;
delete m_internalData->m_gwenRenderer;
delete m_internalData->m_myTexLoader;
delete m_internalData->m_app;
s_app = 0;
delete m_internalData;
gFileImporterByExtension.clear();
gAllExamples = 0;
}
#include "EmptyExample.h"
bool OpenGLExampleBrowser::init(int argc, char* argv[])
{
b3CommandLineArgs args(argc, argv);
loadCurrentSettings(startFileName, args);
if (args.CheckCmdLineFlag("nogui"))
{
renderGrid = false;
renderGui = false;
}
if (args.CheckCmdLineFlag("tracing"))
{
b3ChromeUtilsStartTimings();
}
args.GetCmdLineArgument("fixed_timestep", gFixedTimeStep);
args.GetCmdLineArgument("png_skip_frames", gPngSkipFrames);
///The OpenCL rigid body pipeline is experimental and
///most OpenCL drivers and OpenCL compilers have issues with our kernels.
///If you have a high-end desktop GPU such as AMD 7970 or better, or NVIDIA GTX 680 with up-to-date drivers
///you could give it a try
///Note that several old OpenCL physics examples still have to be ported over to this new Example Browser
if (args.CheckCmdLineFlag("enable_experimental_opencl"))
{
enable_experimental_opencl = true;
gAllExamples->initOpenCLExampleEntries();
}
if (args.CheckCmdLineFlag("disable_retina"))
{
gAllowRetina = false;
}
int width = 1024;
int height = 768;
if (args.CheckCmdLineFlag("width"))
{
args.GetCmdLineArgument("width", width);
}
if (args.CheckCmdLineFlag("height"))
{
args.GetCmdLineArgument("height", height);
}
#ifndef NO_OPENGL3
SimpleOpenGL3App* simpleApp = 0;
sUseOpenGL2 = args.CheckCmdLineFlag("opengl2");
args.GetCmdLineArgument("render_device", gRenderDevice);
args.GetCmdLineArgument("window_backend", gWindowBackend);
#else
sUseOpenGL2 = true;
#endif
const char* appTitle = "Bullet Physics ExampleBrowser";
#if defined(_DEBUG) || defined(DEBUG)
const char* optMode = "Debug build (slow)";
#else
const char* optMode = "Release build";
#endif
#ifdef B3_USE_GLFW
const char* glContext = "[glfw]";
#else
const char* glContext = "[btgl]";
#endif
if (sUseOpenGL2)
{
char title[1024];
sprintf(title, "%s using limited OpenGL2 fallback %s %s", appTitle, glContext, optMode);
s_app = new SimpleOpenGL2App(title, width, height);
s_app->m_renderer = new SimpleOpenGL2Renderer(width, height);
}
#ifndef NO_OPENGL3
else
{
char title[1024];
sprintf(title, "%s using OpenGL3+ %s %s", appTitle, glContext, optMode);
simpleApp = new SimpleOpenGL3App(title, width, height, gAllowRetina, gWindowBackend, gRenderDevice);
s_app = simpleApp;
}
#endif
m_internalData->m_app = s_app;
char* gVideoFileName = 0;
args.GetCmdLineArgument("mp4", gVideoFileName);
#ifndef NO_OPENGL3
if (gVideoFileName)
simpleApp->dumpFramesToVideo(gVideoFileName);
#endif
s_instancingRenderer = s_app->m_renderer;
s_window = s_app->m_window;
width = s_window->getWidth();
height = s_window->getHeight();
prevMouseMoveCallback = s_window->getMouseMoveCallback();
s_window->setMouseMoveCallback(MyMouseMoveCallback);
prevMouseButtonCallback = s_window->getMouseButtonCallback();
s_window->setMouseButtonCallback(MyMouseButtonCallback);
prevKeyboardCallback = s_window->getKeyboardCallback();
s_window->setKeyboardCallback(MyKeyboardCallback);
s_app->m_renderer->getActiveCamera()->setCameraDistance(13);
s_app->m_renderer->getActiveCamera()->setCameraPitch(0);
s_app->m_renderer->getActiveCamera()->setCameraTargetPosition(0, 0, 0);
float mouseMoveMult = s_app->getMouseMoveMultiplier();
if (args.GetCmdLineArgument("mouse_move_multiplier", mouseMoveMult))
{
s_app->setMouseMoveMultiplier(mouseMoveMult);
}
float mouseWheelMult = s_app->getMouseWheelMultiplier();
if (args.GetCmdLineArgument("mouse_wheel_multiplier", mouseWheelMult))
{
s_app->setMouseWheelMultiplier(mouseWheelMult);
}
args.GetCmdLineArgument("shared_memory_key", gSharedMemoryKey);
float red, green, blue;
s_app->getBackgroundColor(&red, &green, &blue);
args.GetCmdLineArgument("background_color_red", red);
args.GetCmdLineArgument("background_color_green", green);
args.GetCmdLineArgument("background_color_blue", blue);
s_app->setBackgroundColor(red, green, blue);
b3SetCustomWarningMessageFunc(MyGuiPrintf);
b3SetCustomPrintfFunc(MyGuiPrintf);
b3SetCustomErrorMessageFunc(MyStatusBarError);
assert(glGetError() == GL_NO_ERROR);
{
GL3TexLoader* myTexLoader = new GL3TexLoader;
m_internalData->m_myTexLoader = myTexLoader;
if (sUseOpenGL2)
{
m_internalData->m_gwenRenderer = new Gwen::Renderer::OpenGL_DebugFont(s_window->getRetinaScale());
}
#ifndef NO_OPENGL3
else
{
sth_stash* fontstash = simpleApp->getFontStash();
m_internalData->m_gwenRenderer = new GwenOpenGL3CoreRenderer(simpleApp->m_primRenderer, fontstash, width, height, s_window->getRetinaScale(), myTexLoader);
}
#endif
gui2 = new GwenUserInterface;
m_internalData->m_gui = gui2;
m_internalData->m_myTexLoader = myTexLoader;
gui2->init(width, height, m_internalData->m_gwenRenderer, s_window->getRetinaScale());
}
//gui = 0;// new GwenUserInterface;
GL3TexLoader* myTexLoader = m_internalData->m_myTexLoader;
// = myTexLoader;
//
if (gui2)
{
// gui->getInternalData()->m_explorerPage
Gwen::Controls::TreeControl* tree = gui2->getInternalData()->m_explorerTreeCtrl;
//gui->getInternalData()->pRenderer->setTextureLoader(myTexLoader);
#ifndef BT_NO_PROFILE
s_profWindow = setupProfileWindow(gui2->getInternalData());
m_internalData->m_profWindow = s_profWindow;
profileWindowSetVisible(s_profWindow, false);
#endif //BT_NO_PROFILE
gui2->setFocus();
s_parameterInterface = s_app->m_parameterInterface = new GwenParameterInterface(gui2->getInternalData());
s_app->m_2dCanvasInterface = new QuickCanvas(myTexLoader);
///add some demos to the gAllExamples
int numDemos = gAllExamples->getNumRegisteredExamples();
//char nodeText[1024];
//int curDemo = 0;
int selectedDemo = 0;
Gwen::Controls::TreeNode* curNode = tree;
m_internalData->m_handler2 = new MyMenuItemHander(-1);
char* demoNameFromCommandOption = 0;
args.GetCmdLineArgument("start_demo_name", demoNameFromCommandOption);
if (demoNameFromCommandOption)
{
selectedDemo = -1;
}
tree->onReturnKeyDown.Add(m_internalData->m_handler2, &MyMenuItemHander::onButtonD);
int firstAvailableDemoIndex = -1;
Gwen::Controls::TreeNode* firstNode = 0;
for (int d = 0; d < numDemos; d++)
{
// sprintf(nodeText, "Node %d", i);
Gwen::UnicodeString nodeUText = Gwen::Utility::StringToUnicode(gAllExamples->getExampleName(d));
if (gAllExamples->getExampleCreateFunc(d)) //was test for gAllExamples[d].m_menuLevel==1
{
Gwen::Controls::TreeNode* pNode = curNode->AddNode(nodeUText);
if (firstAvailableDemoIndex < 0)
{
firstAvailableDemoIndex = d;
firstNode = pNode;
}
if (d == selectedDemo)
{
firstAvailableDemoIndex = d;
firstNode = pNode;
//pNode->SetSelected(true);
//tree->ExpandAll();
// tree->ForceUpdateScrollBars();
//tree->OnKeyLeft(true);
// tree->OnKeyRight(true);
//tree->ExpandAll();
// selectDemo(d);
}
if (demoNameFromCommandOption)
{
const char* demoName = gAllExamples->getExampleName(d);
int res = strcmp(demoName, demoNameFromCommandOption);
if (res == 0)
{
firstAvailableDemoIndex = d;
firstNode = pNode;
}
}
#if 1
MyMenuItemHander* handler = new MyMenuItemHander(d);
m_internalData->m_handlers.push_back(handler);
pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonA);
pNode->GetButton()->onDoubleClick.Add(handler, &MyMenuItemHander::onButtonB);
pNode->GetButton()->onDown.Add(handler, &MyMenuItemHander::onButtonC);
pNode->onSelect.Add(handler, &MyMenuItemHander::onButtonE);
pNode->onReturnKeyDown.Add(handler, &MyMenuItemHander::onButtonG);
pNode->onSelectChange.Add(handler, &MyMenuItemHander::onButtonF);
#endif
// pNode->onKeyReturn.Add(handler, &MyMenuItemHander::onButtonD);
// pNode->GetButton()->onKeyboardReturn.Add(handler, &MyMenuItemHander::onButtonD);
// pNode->onNamePress.Add(handler, &MyMenuItemHander::onButtonD);
// pNode->onKeyboardPressed.Add(handler, &MyMenuItemHander::onButtonD);
// pNode->OnKeyPress
}
else
{
curNode = tree->AddNode(nodeUText);
m_internalData->m_nodes.push_back(curNode);
}
}
if (sCurrentDemo == 0)
{
if (firstAvailableDemoIndex >= 0)
{
firstNode->SetSelected(true);
while (firstNode != tree)
{
firstNode->ExpandAll();
firstNode = (Gwen::Controls::TreeNode*)firstNode->GetParent();
}
selectDemo(firstAvailableDemoIndex);
}
}
free(demoNameFromCommandOption);
demoNameFromCommandOption = 0;
btAssert(sCurrentDemo != 0);
if (sCurrentDemo == 0)
{
printf("Error, no demo/example\n");
exit(0);
}
gui2->registerFileOpenCallback(fileOpenCallback);
gui2->registerQuitCallback(quitCallback);
}
return true;
}
CommonExampleInterface* OpenGLExampleBrowser::getCurrentExample()
{
btAssert(sCurrentDemo);
return sCurrentDemo;
}
bool OpenGLExampleBrowser::requestedExit()
{
return s_window->requestedExit();
}
void OpenGLExampleBrowser::updateGraphics()
{
if (sCurrentDemo)
{
if (!pauseSimulation || singleStepSimulation)
{
//B3_PROFILE("sCurrentDemo->updateGraphics");
sCurrentDemo->updateGraphics();
}
}
}
void OpenGLExampleBrowser::update(float deltaTime)
{
b3ChromeUtilsEnableProfiling();
if (!gEnableRenderLoop && !singleStepSimulation)
{
sCurrentDemo->updateGraphics();
return;
}
B3_PROFILE("OpenGLExampleBrowser::update");
assert(glGetError() == GL_NO_ERROR);
s_instancingRenderer->init();
DrawGridData dg;
dg.upAxis = s_app->getUpAxis();
{
BT_PROFILE("Update Camera and Light");
s_instancingRenderer->updateCamera(dg.upAxis);
}
static int frameCount = 0;
frameCount++;
if (0)
{
BT_PROFILE("Draw frame counter");
char bla[1024];
sprintf(bla, "Frame %d", frameCount);
s_app->drawText(bla, 10, 10);
}
if (gPngFileName)
{
static int skip = 0;
skip--;
if (skip < 0)
{
skip = gPngSkipFrames;
//printf("gPngFileName=%s\n",gPngFileName);
static int s_frameCount = 0;
sprintf(staticPngFileName, "%s%d.png", gPngFileName, s_frameCount++);
//b3Printf("Made screenshot %s",staticPngFileName);
s_app->dumpNextFrameToPng(staticPngFileName);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
if (sCurrentDemo)
{
if (!pauseSimulation || singleStepSimulation)
{
//printf("---------------------------------------------------\n");
//printf("Framecount = %d\n",frameCount);
B3_PROFILE("sCurrentDemo->stepSimulation");
if (gFixedTimeStep > 0)
{
sCurrentDemo->stepSimulation(gFixedTimeStep);
}
else
{
sCurrentDemo->stepSimulation(deltaTime); //1./60.f);
}
}
if (renderGrid)
{
BT_PROFILE("Draw Grid");
//glPolygonOffset(3.0, 3);
//glEnable(GL_POLYGON_OFFSET_FILL);
s_app->drawGrid(dg);
}
if (renderVisualGeometry && ((gDebugDrawFlags & btIDebugDraw::DBG_DrawWireframe) == 0))
{
if (visualWireframe)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
BT_PROFILE("Render Scene");
sCurrentDemo->renderScene();
}
else
{
B3_PROFILE("physicsDebugDraw");
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
sCurrentDemo->physicsDebugDraw(gDebugDrawFlags);
}
}
{
if (gui2 && s_guiHelper && s_guiHelper->getRenderInterface() && s_guiHelper->getRenderInterface()->getActiveCamera())
{
B3_PROFILE("setStatusBarMessage");
char msg[1024];
float camDist = s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraDistance();
float pitch = s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraPitch();
float yaw = s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraYaw();
float camTarget[3];
float camPos[3];
s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraPosition(camPos);
s_guiHelper->getRenderInterface()->getActiveCamera()->getCameraTargetPosition(camTarget);
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);
gui2->setStatusBarMessage(msg, true);
}
}
static int toggle = 1;
if (renderGui)
{
B3_PROFILE("renderGui");
#ifndef BT_NO_PROFILE
if (!pauseSimulation || singleStepSimulation)
{
if (isProfileWindowVisible(s_profWindow))
{
processProfileData(s_profWindow, false);
}
}
#endif //#ifndef BT_NO_PROFILE
if (sUseOpenGL2)
{
saveOpenGLState(s_instancingRenderer->getScreenWidth() * s_window->getRetinaScale(), s_instancingRenderer->getScreenHeight() * s_window->getRetinaScale());
}
if (m_internalData->m_gui)
{
gBlockGuiMessages = true;
m_internalData->m_gui->draw(s_instancingRenderer->getScreenWidth(), s_instancingRenderer->getScreenHeight());
gBlockGuiMessages = false;
}
if (sUseOpenGL2)
{
restoreOpenGLState();
}
}
singleStepSimulation = false;
toggle = 1 - toggle;
{
BT_PROFILE("Sync Parameters");
if (s_parameterInterface)
{
s_parameterInterface->syncParameters();
}
}
{
BT_PROFILE("Swap Buffers");
s_app->swapBuffer();
}
if (gui2)
{
B3_PROFILE("forceUpdateScrollBars");
gui2->forceUpdateScrollBars();
}
}
void OpenGLExampleBrowser::setSharedMemoryInterface(class SharedMemoryInterface* sharedMem)
{
gDisableDemoSelection = true;
sSharedMem = sharedMem;
}