bullet3/examples/ExampleBrowser/InProcessExampleBrowser.cpp
Erwin Coumans c06859723b Embed graphics server (shared memory) in PyBullet. Use pybullet.connect(pybullet.GRAPHICS_SERVER) to enable it.
TODO: enable for Mac OSX on mainloop, add tcp bridges from and to shared memory.
2020-03-19 14:18:35 -07:00

433 lines
12 KiB
C++

#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 <stdio.h>
//#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<ExampleEntryPhysicsServer> 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;
}