#include "InProcessExampleBrowser.h" //#define EXAMPLE_CONSOLE_ONLY #ifdef EXAMPLE_CONSOLE_ONLY #include "EmptyBrowser.h" typedef EmptyBrowser DefaultBrowser; #else #include "OpenGLExampleBrowser.h" typedef OpenGLExampleBrowser DefaultBrowser; #endif //EXAMPLE_CONSOLE_ONLY #include "Bullet3Common/b3CommandLineArgs.h" #include "../Utils/b3Clock.h" #include "ExampleEntries.h" #include "Bullet3Common/b3Scalar.h" #include "../SharedMemory/InProcessMemory.h" void ExampleBrowserThreadFunc(void* userPtr, void* lsMemory); void* ExampleBrowserMemoryFunc(); void ExampleBrowserMemoryReleaseFunc(void* ptr); #include //#include "BulletMultiThreaded/PlatformDefinitions.h" #include "Bullet3Common/b3Logging.h" #include "ExampleEntries.h" #include "LinearMath/btAlignedObjectArray.h" #include "EmptyExample.h" #include "../SharedMemory/PhysicsServerExample.h" #include "../SharedMemory/PhysicsServerExampleBullet2.h" #include "../SharedMemory/GraphicsServerExample.h" #include "../SharedMemory/PhysicsClientExample.h" #ifndef _WIN32 #include "../MultiThreading/b3PosixThreadSupport.h" static b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads) { b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("testThreads", ExampleBrowserThreadFunc, ExampleBrowserMemoryFunc, ExampleBrowserMemoryReleaseFunc, numThreads); b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo); return threadSupport; } #elif defined(_WIN32) #include "../MultiThreading/b3Win32ThreadSupport.h" b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads) { b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("testThreads", ExampleBrowserThreadFunc, ExampleBrowserMemoryFunc, ExampleBrowserMemoryReleaseFunc, numThreads); b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo); return threadSupport; } #endif class ExampleEntriesPhysicsServer : public ExampleEntries { struct ExampleEntriesInternalData2* m_data; public: ExampleEntriesPhysicsServer(); virtual ~ExampleEntriesPhysicsServer(); static void registerExampleEntry(int menuLevel, const char* name, const char* description, CommonExampleInterface::CreateFunc* createFunc, int option = 0); virtual void initExampleEntries(); virtual void initOpenCLExampleEntries(); virtual int getNumRegisteredExamples(); virtual CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index); virtual const char* getExampleName(int index); virtual const char* getExampleDescription(int index); virtual int getExampleOption(int index); }; struct ExampleEntryPhysicsServer { int m_menuLevel; const char* m_name; const char* m_description; CommonExampleInterface::CreateFunc* m_createFunc; int m_option; ExampleEntryPhysicsServer(int menuLevel, const char* name) : m_menuLevel(menuLevel), m_name(name), m_description(0), m_createFunc(0), m_option(0) { } ExampleEntryPhysicsServer(int menuLevel, const char* name, const char* description, CommonExampleInterface::CreateFunc* createFunc, int option = 0) : m_menuLevel(menuLevel), m_name(name), m_description(description), m_createFunc(createFunc), m_option(option) { } }; struct ExampleEntriesInternalData2 { btAlignedObjectArray m_allExamples; }; static ExampleEntryPhysicsServer gDefaultExamplesPhysicsServer[] = { ExampleEntryPhysicsServer(0, "Robotics Control"), ExampleEntryPhysicsServer(1, "Physics Server", "Create a physics server that communicates with a physics client over shared memory", PhysicsServerCreateFuncBullet2), ExampleEntryPhysicsServer(1, "Physics Server (RTC)", "Create a physics server that communicates with a physics client over shared memory. At each update, the Physics Server will continue calling 'stepSimulation' based on the real-time clock (RTC).", PhysicsServerCreateFuncBullet2, PHYSICS_SERVER_USE_RTC_CLOCK), ExampleEntryPhysicsServer(1, "Physics Server (Logging)", "Create a physics server that communicates with a physics client over shared memory. It will log all commands to a file.", PhysicsServerCreateFuncBullet2, PHYSICS_SERVER_ENABLE_COMMAND_LOGGING), ExampleEntryPhysicsServer(1, "Physics Server (Replay Log)", "Create a physics server that replay a command log from disk.", PhysicsServerCreateFuncBullet2, PHYSICS_SERVER_REPLAY_FROM_COMMAND_LOG), ExampleEntryPhysicsServer(1, "Graphics Server", "Create a graphics server", GraphicsServerCreateFuncBullet), }; ExampleEntriesPhysicsServer::ExampleEntriesPhysicsServer() { m_data = new ExampleEntriesInternalData2; } ExampleEntriesPhysicsServer::~ExampleEntriesPhysicsServer() { delete m_data; } void ExampleEntriesPhysicsServer::initOpenCLExampleEntries() { } void ExampleEntriesPhysicsServer::initExampleEntries() { m_data->m_allExamples.clear(); int numDefaultEntries = sizeof(gDefaultExamplesPhysicsServer) / sizeof(ExampleEntryPhysicsServer); for (int i = 0; i < numDefaultEntries; i++) { m_data->m_allExamples.push_back(gDefaultExamplesPhysicsServer[i]); } } void ExampleEntriesPhysicsServer::registerExampleEntry(int menuLevel, const char* name, const char* description, CommonExampleInterface::CreateFunc* createFunc, int option) { } int ExampleEntriesPhysicsServer::getNumRegisteredExamples() { return m_data->m_allExamples.size(); } CommonExampleInterface::CreateFunc* ExampleEntriesPhysicsServer::getExampleCreateFunc(int index) { return m_data->m_allExamples[index].m_createFunc; } int ExampleEntriesPhysicsServer::getExampleOption(int index) { return m_data->m_allExamples[index].m_option; } const char* ExampleEntriesPhysicsServer::getExampleName(int index) { return m_data->m_allExamples[index].m_name; } const char* ExampleEntriesPhysicsServer::getExampleDescription(int index) { return m_data->m_allExamples[index].m_description; } struct ExampleBrowserArgs { ExampleBrowserArgs() : m_fakeWork(1), m_argc(0) { } b3CriticalSection* m_cs; float m_fakeWork; int m_argc; char** m_argv; }; struct ExampleBrowserThreadLocalStorage { SharedMemoryInterface* m_sharedMem; int threadId; }; enum TestExampleBrowserCommunicationEnums { eRequestTerminateExampleBrowser = 13, eExampleBrowserIsUnInitialized, eExampleBrowserIsInitialized, eExampleBrowserInitializationFailed, eExampleBrowserHasTerminated }; static double gMinUpdateTimeMicroSecs = 4000.; void ExampleBrowserThreadFunc(void* userPtr, void* lsMemory) { printf("ExampleBrowserThreadFunc started\n"); ExampleBrowserThreadLocalStorage* localStorage = (ExampleBrowserThreadLocalStorage*)lsMemory; ExampleBrowserArgs* args = (ExampleBrowserArgs*)userPtr; //int workLeft = true; b3CommandLineArgs args2(args->m_argc, args->m_argv); int minUpdateMs = 4000; if (args2.GetCmdLineArgument("minGraphicsUpdateTimeMs", minUpdateMs)) { gMinUpdateTimeMicroSecs = minUpdateMs; } b3Clock clock; ExampleEntriesPhysicsServer examples; examples.initExampleEntries(); DefaultBrowser* exampleBrowser = new DefaultBrowser(&examples); exampleBrowser->setSharedMemoryInterface(localStorage->m_sharedMem); bool init = exampleBrowser->init(args->m_argc, args->m_argv); clock.reset(); if (init) { args->m_cs->lock(); args->m_cs->setSharedParam(0, eExampleBrowserIsInitialized); args->m_cs->unlock(); do { clock.usleep(0); //B3_PROFILE("ExampleBrowserThreadFunc"); float deltaTimeInSeconds = clock.getTimeMicroseconds() / 1000000.f; { if (deltaTimeInSeconds > 0.1) { deltaTimeInSeconds = 0.1; } if (deltaTimeInSeconds < (gMinUpdateTimeMicroSecs / 1e6)) { //B3_PROFILE("clock.usleep"); exampleBrowser->updateGraphics(); } else { //B3_PROFILE("exampleBrowser->update"); clock.reset(); exampleBrowser->updateGraphics(); exampleBrowser->update(deltaTimeInSeconds); } } } while (!exampleBrowser->requestedExit() && (args->m_cs->getSharedParam(0) != eRequestTerminateExampleBrowser)); } else { args->m_cs->lock(); args->m_cs->setSharedParam(0, eExampleBrowserInitializationFailed); args->m_cs->unlock(); } delete exampleBrowser; args->m_cs->lock(); args->m_cs->setSharedParam(0, eExampleBrowserHasTerminated); args->m_cs->unlock(); printf("finished\n"); //do nothing } void* ExampleBrowserMemoryFunc() { //don't create local store memory, just return 0 return new ExampleBrowserThreadLocalStorage; } void ExampleBrowserMemoryReleaseFunc(void* ptr) { ExampleBrowserThreadLocalStorage* p = (ExampleBrowserThreadLocalStorage*)ptr; delete p; } struct btInProcessExampleBrowserInternalData { ExampleBrowserArgs m_args; b3ThreadSupportInterface* m_threadSupport; SharedMemoryInterface* m_sharedMem; }; btInProcessExampleBrowserInternalData* btCreateInProcessExampleBrowser(int argc, char** argv2, bool useInProcessMemory) { btInProcessExampleBrowserInternalData* data = new btInProcessExampleBrowserInternalData; data->m_sharedMem = useInProcessMemory ? new InProcessMemory : 0; int numThreads = 1; int i; data->m_threadSupport = createExampleBrowserThreadSupport(numThreads); printf("argc=%d\n", argc); for (i = 0; i < argc; i++) { printf("argv[%d] = %s\n", i, argv2[i]); } for (i = 0; i < data->m_threadSupport->getNumTasks(); i++) { ExampleBrowserThreadLocalStorage* storage = (ExampleBrowserThreadLocalStorage*)data->m_threadSupport->getThreadLocalMemory(i); b3Assert(storage); storage->threadId = i; storage->m_sharedMem = data->m_sharedMem; } data->m_args.m_cs = data->m_threadSupport->createCriticalSection(); data->m_args.m_cs->setSharedParam(0, eExampleBrowserIsUnInitialized); data->m_args.m_argc = argc; data->m_args.m_argv = argv2; for (i = 0; i < numThreads; i++) { data->m_threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*)&data->m_args, i); } while (data->m_args.m_cs->getSharedParam(0) == eExampleBrowserIsUnInitialized) { b3Clock::usleep(1000); } return data; } bool btIsExampleBrowserTerminated(btInProcessExampleBrowserInternalData* data) { return (data->m_args.m_cs->getSharedParam(0) == eExampleBrowserHasTerminated); } SharedMemoryInterface* btGetSharedMemoryInterface(btInProcessExampleBrowserInternalData* data) { return data->m_sharedMem; } void btShutDownExampleBrowser(btInProcessExampleBrowserInternalData* data) { int numActiveThreads = 1; data->m_args.m_cs->lock(); data->m_args.m_cs->setSharedParam(0, eRequestTerminateExampleBrowser); data->m_args.m_cs->unlock(); while (numActiveThreads) { int arg0, arg1; if (data->m_threadSupport->isTaskCompleted(&arg0, &arg1, 0)) { numActiveThreads--; printf("numActiveThreads = %d\n", numActiveThreads); } else { // printf("polling.."); b3Clock::usleep(0); } }; printf("btShutDownExampleBrowser stopping threads\n"); data->m_threadSupport->deleteCriticalSection(data->m_args.m_cs); delete data->m_threadSupport; delete data->m_sharedMem; delete data; } struct btInProcessExampleBrowserMainThreadInternalData { ExampleEntriesPhysicsServer m_examples; DefaultBrowser* m_exampleBrowser; SharedMemoryInterface* m_sharedMem; b3Clock m_clock; }; btInProcessExampleBrowserMainThreadInternalData* btCreateInProcessExampleBrowserMainThread(int argc, char** argv, bool useInProcessMemory) { btInProcessExampleBrowserMainThreadInternalData* data = new btInProcessExampleBrowserMainThreadInternalData; data->m_examples.initExampleEntries(); data->m_exampleBrowser = new DefaultBrowser(&data->m_examples); data->m_sharedMem = useInProcessMemory ? new InProcessMemory : 0; data->m_exampleBrowser->setSharedMemoryInterface(data->m_sharedMem); bool init; init = data->m_exampleBrowser->init(argc, argv); data->m_clock.reset(); return data; } bool btIsExampleBrowserMainThreadTerminated(btInProcessExampleBrowserMainThreadInternalData* data) { return data->m_exampleBrowser->requestedExit(); } void btUpdateInProcessExampleBrowserMainThread(btInProcessExampleBrowserMainThreadInternalData* data) { float deltaTimeInSeconds = data->m_clock.getTimeMicroseconds() / 1000000.f; data->m_clock.reset(); data->m_exampleBrowser->updateGraphics(); data->m_exampleBrowser->update(deltaTimeInSeconds); } void btShutDownExampleBrowserMainThread(btInProcessExampleBrowserMainThreadInternalData* data) { data->m_exampleBrowser->setSharedMemoryInterface(0); delete data->m_exampleBrowser; delete data; } class SharedMemoryInterface* btGetSharedMemoryInterfaceMainThread(btInProcessExampleBrowserMainThreadInternalData* data) { return data->m_sharedMem; }