bullet3/examples/SharedMemory/PhysicsServerExample.cpp
Erwin Coumans 27fbbfee7f pybullet removeAllParameters (sliders, buttons)
pybullet addUserDebugParameter adds button instead of slider, if min > max.
2020-03-16 21:29:30 -07:00

3300 lines
95 KiB
C++

//todo(erwincoumans): re-use the upcoming b3RobotSimAPI here
#include "PhysicsServerExample.h"
#include "../CommonInterfaces/Common2dCanvasInterface.h"
#include "PhysicsServerSharedMemory.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "SharedMemoryCommon.h"
#include "Bullet3Common/b3Matrix3x3.h"
#include "../Utils/b3Clock.h"
#include "../MultiThreading/b3ThreadSupportInterface.h"
#include "SharedMemoryPublic.h"
//#define BT_ENABLE_VR
#ifdef BT_ENABLE_VR
#include "../RenderingExamples/TinyVRGui.h"
#endif //BT_ENABLE_VR
#include "../CommonInterfaces/CommonParameterInterface.h"
#include "../Importers/ImportURDFDemo/urdfStringSplit.h"
//@todo(erwincoumans) those globals are hacks for a VR demo, move this to Python/pybullet!
bool gEnablePicking = true;
bool gEnableTeleporting = true;
bool gEnableRendering = true;
bool gActivedVRRealTimeSimulation = false;
bool gEnableSyncPhysicsRendering = true;
static int gCamVisualizerWidth = 228;
static int gCamVisualizerHeight = 192;
static bool gEnableDefaultKeyboardShortcuts = true;
static bool gEnableDefaultMousePicking = true;
btScalar gVRTeleportRotZ = 0;
extern int gInternalSimFlags;
extern bool gResetSimulation;
int gGraspingController = -1;
extern btScalar simTimeScalingFactor;
bool gBatchUserDebugLines = true;
const char* startFileNameVR = "0_VRDemoSettings.txt";
#include <vector>
static void loadCurrentSettingsVR(b3CommandLineArgs& args)
{
//int currentEntry = 0;
FILE* f = fopen(startFileNameVR, "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);
}
};
//remember the settings (you don't want to re-tune again and again...)
static void saveCurrentSettingsVR(const btVector3& VRTeleportPos1)
{
FILE* f = fopen(startFileNameVR, "w");
if (f)
{
fprintf(f, "--camPosX= %f\n", VRTeleportPos1[0]);
fprintf(f, "--camPosY= %f\n", VRTeleportPos1[1]);
fprintf(f, "--camPosZ= %f\n", VRTeleportPos1[2]);
fprintf(f, "--camRotZ= %f\n", gVRTeleportRotZ);
fclose(f);
}
};
bool gDebugRenderToggle = false;
void MotionThreadFunc(void* userPtr, void* lsMemory);
void* MotionlsMemoryFunc();
void MotionlsMemoryReleaseFunc(void* ptr);
#define MAX_MOTION_NUM_THREADS 1
enum
{
numCubesX = 20,
numCubesY = 20
};
enum TestExampleBrowserCommunicationEnums
{
eRequestTerminateMotion = 13,
eMotionIsUnInitialized,
eMotionIsInitialized,
eMotionInitializationFailed,
eMotionHasTerminated
};
enum MultiThreadedGUIHelperCommunicationEnums
{
eGUIHelperIdle = 13,
eGUIHelperRegisterTexture,
eGUIHelperRegisterGraphicsShape,
eGUIHelperRegisterGraphicsInstance,
eGUIHelperCreateCollisionShapeGraphicsObject,
eGUIHelperCreateCollisionObjectGraphicsObject,
eGUIHelperCreateRigidBodyGraphicsObject,
eGUIHelperRemoveAllGraphicsInstances,
eGUIHelperCopyCameraImageData,
eGUIHelperDisplayCameraImageData,
eGUIHelperAutogenerateGraphicsObjects,
eGUIUserDebugAddText,
eGUIUserDebugAddLine,
eGUIUserDebugAddParameter,
eGUIUserDebugRemoveItem,
eGUIUserDebugRemoveAllItems,
eGUIDumpFramesToVideo,
eGUIHelperRemoveGraphicsInstance,
eGUIHelperChangeGraphicsInstanceRGBAColor,
eGUIHelperChangeGraphicsInstanceSpecularColor,
eGUIHelperSetVisualizerFlag,
eGUIHelperChangeGraphicsInstanceTextureId,
eGUIHelperGetShapeIndexFromInstance,
eGUIHelperChangeTexture,
eGUIHelperRemoveTexture,
eGUIHelperSetVisualizerFlagCheckRenderedFrame,
eGUIHelperUpdateShape,
eGUIUserDebugRemoveAllParameters,
};
#include <stdio.h>
//#include "BulletMultiThreaded/PlatformDefinitions.h"
#ifndef _WIN32
#include "../MultiThreading/b3PosixThreadSupport.h"
b3ThreadSupportInterface* createMotionThreadSupport(int numThreads)
{
b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("MotionThreads",
MotionThreadFunc,
MotionlsMemoryFunc,
MotionlsMemoryReleaseFunc,
numThreads);
b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo);
return threadSupport;
}
#elif defined(_WIN32)
#include "../MultiThreading/b3Win32ThreadSupport.h"
b3ThreadSupportInterface* createMotionThreadSupport(int numThreads)
{
b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("MotionThreads", MotionThreadFunc, MotionlsMemoryFunc, MotionlsMemoryReleaseFunc, numThreads);
b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo);
return threadSupport;
}
#endif
enum MyMouseCommandType
{
MyMouseMove = 1,
MyMouseButtonDown,
MyMouseButtonUp
};
struct MyMouseCommand
{
btVector3 m_rayFrom;
btVector3 m_rayTo;
int m_type;
};
struct MotionArgs
{
MotionArgs()
: m_debugDrawFlags(0),
m_enableUpdateDebugDrawLines(true),
m_physicsServerPtr(0)
{
for (int i = 0; i < MAX_VR_CONTROLLERS; i++)
{
m_vrControllerEvents[i].m_numButtonEvents = 0;
m_vrControllerEvents[i].m_numMoveEvents = 0;
for (int b = 0; b < MAX_VR_BUTTONS; b++)
{
m_vrControllerEvents[i].m_buttons[b] = 0;
}
m_vrControllerPos[i].setValue(0, 0, 0);
m_vrControllerOrn[i].setValue(0, 0, 0, 1);
m_isVrControllerPicking[i] = false;
m_isVrControllerDragging[i] = false;
m_isVrControllerReleasing[i] = false;
m_isVrControllerTeleporting[i] = false;
}
}
b3CriticalSection* m_cs;
b3CriticalSection* m_cs2;
b3CriticalSection* m_cs3;
b3CriticalSection* m_csGUI;
int m_debugDrawFlags;
bool m_enableUpdateDebugDrawLines;
btAlignedObjectArray<MyMouseCommand> m_mouseCommands;
b3VRControllerEvent m_vrControllerEvents[MAX_VR_CONTROLLERS];
b3VRControllerEvent m_sendVrControllerEvents[MAX_VR_CONTROLLERS];
btAlignedObjectArray<b3KeyboardEvent> m_keyboardEvents;
btAlignedObjectArray<b3KeyboardEvent> m_sendKeyEvents;
btAlignedObjectArray<b3MouseEvent> m_allMouseEvents;
btAlignedObjectArray<b3MouseEvent> m_sendMouseEvents;
PhysicsServerSharedMemory* m_physicsServerPtr;
b3AlignedObjectArray<b3Vector3> m_positions;
btVector3 m_vrControllerPos[MAX_VR_CONTROLLERS];
btQuaternion m_vrControllerOrn[MAX_VR_CONTROLLERS];
bool m_isVrControllerPicking[MAX_VR_CONTROLLERS];
bool m_isVrControllerDragging[MAX_VR_CONTROLLERS];
bool m_isVrControllerReleasing[MAX_VR_CONTROLLERS];
bool m_isVrControllerTeleporting[MAX_VR_CONTROLLERS];
};
struct MotionThreadLocalStorage
{
int threadId;
};
float clampedDeltaTime = 0.2;
void MotionThreadFunc(void* userPtr, void* lsMemory)
{
printf("MotionThreadFunc thread started\n");
//MotionThreadLocalStorage* localStorage = (MotionThreadLocalStorage*) lsMemory;
MotionArgs* args = (MotionArgs*)userPtr;
//int workLeft = true;
b3Clock clock;
clock.reset();
b3Clock sleepClock;
bool init = true;
if (init)
{
unsigned int cachedSharedParam = eMotionIsInitialized;
args->m_cs->lock();
args->m_cs->setSharedParam(0, eMotionIsInitialized);
args->m_cs->unlock();
double deltaTimeInSeconds = 0;
int numCmdSinceSleep1ms = 0;
unsigned long long int prevTime = clock.getTimeMicroseconds();
do
{
{
b3Clock::usleep(0);
}
{
if (sleepClock.getTimeMilliseconds() > 1)
{
sleepClock.reset();
numCmdSinceSleep1ms = 0;
}
}
unsigned long long int curTime = clock.getTimeMicroseconds();
unsigned long long int dtMicro = curTime - prevTime;
prevTime = curTime;
#if 1
double dt = double(dtMicro) / 1000000.;
#else
double dt = double(clock.getTimeMicroseconds()) / 1000000.;
clock.reset();
#endif
deltaTimeInSeconds += dt;
{
//process special controller commands, such as
//VR controller button press/release and controller motion
for (int c = 0; c < MAX_VR_CONTROLLERS; c++)
{
btVector3 from = args->m_vrControllerPos[c];
btMatrix3x3 mat(args->m_vrControllerOrn[c]);
btScalar pickDistance = 1000.;
btVector3 to = from + mat.getColumn(0) * pickDistance;
// btVector3 toY = from+mat.getColumn(1)*pickDistance;
// btVector3 toZ = from+mat.getColumn(2)*pickDistance;
if (args->m_isVrControllerTeleporting[c])
{
args->m_isVrControllerTeleporting[c] = false;
args->m_physicsServerPtr->pickBody(from, to);
args->m_physicsServerPtr->removePickingConstraint();
}
// if (!gEnableKukaControl)
{
if (args->m_isVrControllerPicking[c])
{
args->m_isVrControllerPicking[c] = false;
args->m_isVrControllerDragging[c] = true;
args->m_physicsServerPtr->pickBody(from, to);
//printf("PICK!\n");
}
}
if (args->m_isVrControllerDragging[c])
{
args->m_physicsServerPtr->movePickedBody(from, to);
// printf(".");
}
if (args->m_isVrControllerReleasing[c])
{
args->m_isVrControllerDragging[c] = false;
args->m_isVrControllerReleasing[c] = false;
args->m_physicsServerPtr->removePickingConstraint();
//printf("Release pick\n");
}
}
//don't simulate over a huge timestep if we had some interruption (debugger breakpoint etc)
if (deltaTimeInSeconds > clampedDeltaTime)
{
deltaTimeInSeconds = clampedDeltaTime;
//b3Warning("Clamp deltaTime from %f to %f",deltaTimeInSeconds, clampedDeltaTime);
}
args->m_csGUI->lock();
int numSendVrControllers = 0;
for (int i = 0; i < MAX_VR_CONTROLLERS; i++)
{
if (args->m_vrControllerEvents[i].m_numButtonEvents + args->m_vrControllerEvents[i].m_numMoveEvents)
{
args->m_sendVrControllerEvents[numSendVrControllers++] =
args->m_vrControllerEvents[i];
if (args->m_vrControllerEvents[i].m_numButtonEvents)
{
for (int b = 0; b < MAX_VR_BUTTONS; b++)
{
args->m_vrControllerEvents[i].m_buttons[b] &= eButtonIsDown;
}
}
args->m_vrControllerEvents[i].m_numMoveEvents = 0;
args->m_vrControllerEvents[i].m_numButtonEvents = 0;
}
}
args->m_sendKeyEvents.resize(args->m_keyboardEvents.size());
for (int i = 0; i < args->m_keyboardEvents.size(); i++)
{
args->m_sendKeyEvents[i] = args->m_keyboardEvents[i];
if (args->m_keyboardEvents[i].m_keyState & eButtonReleased)
{
args->m_keyboardEvents[i].m_keyState = 0;
}
else
{
args->m_keyboardEvents[i].m_keyState &= ~eButtonTriggered;
}
}
//remove the 'released' events
for (int i = args->m_keyboardEvents.size() - 1; i >= 0; i--)
{
if (args->m_keyboardEvents[i].m_keyState == 0)
{
args->m_keyboardEvents.removeAtIndex(i);
}
}
b3KeyboardEvent* keyEvents = args->m_sendKeyEvents.size() ? &args->m_sendKeyEvents[0] : 0;
args->m_csGUI->unlock();
args->m_csGUI->lock();
if (gEnableDefaultMousePicking)
{
for (int i = 0; i < args->m_mouseCommands.size(); i++)
{
switch (args->m_mouseCommands[i].m_type)
{
case MyMouseMove:
{
args->m_physicsServerPtr->movePickedBody(args->m_mouseCommands[i].m_rayFrom, args->m_mouseCommands[i].m_rayTo);
break;
};
case MyMouseButtonDown:
{
args->m_physicsServerPtr->pickBody(args->m_mouseCommands[i].m_rayFrom, args->m_mouseCommands[i].m_rayTo);
break;
}
case MyMouseButtonUp:
{
args->m_physicsServerPtr->removePickingConstraint();
break;
}
default:
{
}
}
}
}
args->m_sendMouseEvents.resize(args->m_allMouseEvents.size());
for (int i = 0; i < args->m_allMouseEvents.size(); i++)
{
args->m_sendMouseEvents[i] = args->m_allMouseEvents[i];
}
b3MouseEvent* mouseEvents = args->m_sendMouseEvents.size() ? &args->m_sendMouseEvents[0] : 0;
args->m_allMouseEvents.clear();
args->m_mouseCommands.clear();
args->m_csGUI->unlock();
{
args->m_physicsServerPtr->stepSimulationRealTime(deltaTimeInSeconds, args->m_sendVrControllerEvents, numSendVrControllers, keyEvents, args->m_sendKeyEvents.size(), mouseEvents, args->m_sendMouseEvents.size());
}
{
args->m_csGUI->lock();
if (args->m_enableUpdateDebugDrawLines)
{
args->m_physicsServerPtr->physicsDebugDraw(args->m_debugDrawFlags);
args->m_enableUpdateDebugDrawLines = false;
}
args->m_csGUI->unlock();
}
deltaTimeInSeconds = 0;
}
{
args->m_physicsServerPtr->processClientCommands();
numCmdSinceSleep1ms++;
}
args->m_physicsServerPtr->reportNotifications();
args->m_cs->lock();
cachedSharedParam = args->m_cs->getSharedParam(0);
args->m_cs->unlock();
} while (cachedSharedParam != eRequestTerminateMotion);
}
else
{
args->m_cs->lock();
args->m_cs->setSharedParam(0, eMotionInitializationFailed);
args->m_cs->unlock();
}
args->m_physicsServerPtr->disconnectSharedMemory(true);
//do nothing
}
void* MotionlsMemoryFunc()
{
//don't create local store memory, just return 0
return new MotionThreadLocalStorage;
}
void MotionlsMemoryReleaseFunc(void* ptr)
{
MotionThreadLocalStorage* p = (MotionThreadLocalStorage*)ptr;
delete p;
}
struct UserDebugDrawLine
{
double m_debugLineFromXYZ[3];
double m_debugLineToXYZ[3];
double m_debugLineColorRGB[3];
double m_lineWidth;
double m_lifeTime;
int m_itemUniqueId;
int m_trackingVisualShapeIndex;
int m_replaceItemUid;
};
struct UserDebugParameter
{
char m_text[1024];
double m_rangeMin;
double m_rangeMax;
btScalar m_value;
int m_itemUniqueId;
};
static void UserButtonToggle(int buttonId, bool buttonState, void* userPointer)
{
UserDebugParameter* param = (UserDebugParameter*)userPointer;
param->m_value += 1;
}
struct UserDebugText
{
char m_text[1024];
double m_textPositionXYZ1[3];
double m_textColorRGB[3];
double textSize;
double m_lifeTime;
int m_itemUniqueId;
double m_textOrientation[4];
int m_trackingVisualShapeIndex;
int m_optionFlags;
};
struct LineSegment
{
btVector3 m_from;
btVector3 m_to;
};
struct ColorWidth
{
btVector3FloatData m_color;
int width;
int getHash() const
{
unsigned char r = (unsigned char)m_color.m_floats[0] * 255;
unsigned char g = (unsigned char)m_color.m_floats[1] * 255;
unsigned char b = (unsigned char)m_color.m_floats[2] * 255;
unsigned char w = width;
return r + (256 * g) + (256 * 256 * b) + (256 * 256 * 256 * w);
}
bool equals(const ColorWidth& other) const
{
bool same = ((width == other.width) && (m_color.m_floats[0] == other.m_color.m_floats[0]) &&
(m_color.m_floats[1] == other.m_color.m_floats[1]) &&
(m_color.m_floats[2] == other.m_color.m_floats[2]));
return same;
}
};
ATTRIBUTE_ALIGNED16(class)
MultithreadedDebugDrawer : public btIDebugDraw
{
struct GUIHelperInterface* m_guiHelper;
int m_debugMode;
btAlignedObjectArray<btAlignedObjectArray<unsigned int> > m_sortedIndices;
btAlignedObjectArray<btAlignedObjectArray<btVector3FloatData> > m_sortedLines;
btHashMap<ColorWidth, int> m_hashedLines;
public:
virtual void drawDebugDrawerLines()
{
if (m_hashedLines.size())
{
for (int i = 0; i < m_hashedLines.size(); i++)
{
ColorWidth cw = m_hashedLines.getKeyAtIndex(i);
int index = *m_hashedLines.getAtIndex(i);
int stride = sizeof(btVector3FloatData);
const float* positions = &m_sortedLines[index][0].m_floats[0];
int numPoints = m_sortedLines[index].size();
const unsigned int* indices = &m_sortedIndices[index][0];
int numIndices = m_sortedIndices[index].size();
m_guiHelper->getRenderInterface()->drawLines(positions, cw.m_color.m_floats, numPoints, stride, indices, numIndices, cw.width);
}
}
}
MultithreadedDebugDrawer(GUIHelperInterface * guiHelper)
: m_guiHelper(guiHelper),
m_debugMode(0)
{
}
virtual ~MultithreadedDebugDrawer()
{
}
virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color)
{
{
ColorWidth cw;
color.serializeFloat(cw.m_color);
cw.width = 1;
int index = -1;
int* indexPtr = m_hashedLines.find(cw);
if (indexPtr)
{
index = *indexPtr;
}
else
{
index = m_sortedLines.size();
m_sortedLines.expand();
m_sortedIndices.expand();
m_hashedLines.insert(cw, index);
}
btAssert(index >= 0);
if (index >= 0)
{
btVector3FloatData from1, toX1;
m_sortedIndices[index].push_back(m_sortedLines[index].size());
from.serializeFloat(from1);
m_sortedLines[index].push_back(from1);
m_sortedIndices[index].push_back(m_sortedLines[index].size());
to.serializeFloat(toX1);
m_sortedLines[index].push_back(toX1);
}
}
}
virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color)
{
drawLine(PointOnB, PointOnB + normalOnB * distance, color);
btVector3 ncolor(0, 0, 0);
drawLine(PointOnB, PointOnB + normalOnB * 0.01, ncolor);
}
virtual void reportErrorWarning(const char* warningString)
{
}
virtual void draw3dText(const btVector3& location, const char* textString)
{
}
virtual void setDebugMode(int debugMode)
{
m_debugMode = debugMode;
}
virtual int getDebugMode() const
{
return m_debugMode;
}
virtual void clearLines() override
{
m_hashedLines.clear();
m_sortedIndices.clear();
m_sortedLines.clear();
}
virtual void flushLines()
{
}
};
class MultiThreadedOpenGLGuiHelper : public GUIHelperInterface
{
// CommonGraphicsApp* m_app;
b3CriticalSection* m_cs;
b3CriticalSection* m_cs2;
b3CriticalSection* m_cs3;
b3CriticalSection* m_csGUI;
public:
MultithreadedDebugDrawer* m_debugDraw;
virtual void drawDebugDrawerLines()
{
if (m_debugDraw)
{
m_csGUI->lock();
//draw stuff and flush?
m_debugDraw->drawDebugDrawerLines();
m_csGUI->unlock();
}
}
virtual void clearLines()
{
m_csGUI->lock();
if (m_debugDraw)
{
m_debugDraw->clearLines();
}
m_csGUI->unlock();
}
GUIHelperInterface* m_childGuiHelper;
btHashMap<btHashPtr, int> m_cachedTextureIds;
int m_uidGenerator;
const unsigned char* m_texels;
int m_textureWidth;
int m_textureHeight;
int m_shapeIndex;
const float* m_position;
const float* m_quaternion;
const float* m_color;
const float* m_scaling;
const float* m_vertices;
int m_numvertices;
const int* m_indices;
int m_numIndices;
int m_primitiveType;
int m_textureId;
int m_instanceId;
bool m_skipGraphicsUpdate;
void mainThreadRelease()
{
BT_PROFILE("mainThreadRelease");
getCriticalSection()->setSharedParam(1, eGUIHelperIdle);
getCriticalSection3()->lock();
getCriticalSection2()->unlock();
getCriticalSection()->lock();
getCriticalSection2()->lock();
getCriticalSection()->unlock();
getCriticalSection3()->unlock();
}
void workerThreadWait()
{
BT_PROFILE("workerThreadWait");
if (m_skipGraphicsUpdate)
{
getCriticalSection()->setSharedParam(1, eGUIHelperIdle);
m_cs->unlock();
return;
}
m_cs2->lock();
m_cs->unlock();
m_cs2->unlock();
m_cs3->lock();
m_cs3->unlock();
while (m_cs->getSharedParam(1) != eGUIHelperIdle)
{
b3Clock::usleep(0);
}
}
MultiThreadedOpenGLGuiHelper(CommonGraphicsApp* app, GUIHelperInterface* guiHelper, int skipGraphicsUpdate)
: //m_app(app),
m_cs(0),
m_cs2(0),
m_cs3(0),
m_csGUI(0),
m_debugDraw(0),
m_uidGenerator(0),
m_texels(0),
m_shapeIndex(-1),
m_textureId(-1),
m_instanceId(-1),
m_skipGraphicsUpdate(skipGraphicsUpdate)
{
m_childGuiHelper = guiHelper;
}
virtual ~MultiThreadedOpenGLGuiHelper()
{
//delete m_childGuiHelper;
if (m_debugDraw)
{
delete m_debugDraw;
m_debugDraw = 0;
}
for (int i = 0; i < m_userDebugParams.size(); i++)
{
delete m_userDebugParams[i];
}
m_userDebugParams.clear();
}
void setCriticalSection(b3CriticalSection* cs)
{
m_cs = cs;
}
b3CriticalSection* getCriticalSection()
{
return m_cs;
}
void setCriticalSection2(b3CriticalSection* cs)
{
m_cs2 = cs;
}
b3CriticalSection* getCriticalSection2()
{
return m_cs2;
}
void setCriticalSection3(b3CriticalSection* cs)
{
m_cs3 = cs;
}
void setCriticalSectionGUI(b3CriticalSection* cs)
{
m_csGUI = cs;
}
b3CriticalSection* getCriticalSection3()
{
return m_cs3;
}
btRigidBody* m_body;
btVector3 m_color3;
virtual void createRigidBodyGraphicsObject(btRigidBody* body, const btVector3& color)
{
m_body = body;
m_color3 = color;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperCreateRigidBodyGraphicsObject);
workerThreadWait();
}
btCollisionObject* m_obj;
btVector3 m_color2;
virtual void createCollisionObjectGraphicsObject(btCollisionObject* obj, const btVector3& color)
{
m_obj = obj;
m_color2 = color;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperCreateCollisionObjectGraphicsObject);
workerThreadWait();
}
btCollisionShape* m_colShape;
virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape)
{
m_colShape = collisionShape;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperCreateCollisionShapeGraphicsObject);
workerThreadWait();
}
virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld)
{
//this check is to prevent a crash, in case we removed all graphics instances, but there are still physics objects.
//the check will be obsolete, once we have a better/safer way of synchronizing physics->graphics transforms
if (m_childGuiHelper->getRenderInterface() && m_childGuiHelper->getRenderInterface()->getTotalNumInstances() > 0)
{
m_childGuiHelper->syncPhysicsToGraphics(rbWorld);
}
}
virtual void syncPhysicsToGraphics2(const btDiscreteDynamicsWorld* rbWorld)
{
m_childGuiHelper->syncPhysicsToGraphics2(rbWorld);
}
virtual void syncPhysicsToGraphics2(const GUISyncPosition* positions, int numPositions)
{
m_childGuiHelper->syncPhysicsToGraphics2(positions, numPositions);
}
virtual void render(const btDiscreteDynamicsWorld* rbWorld)
{
m_childGuiHelper->render(0);
}
virtual void createPhysicsDebugDrawer(btDiscreteDynamicsWorld* rbWorld)
{
btAssert(rbWorld);
if (m_debugDraw)
{
delete m_debugDraw;
m_debugDraw = 0;
}
m_debugDraw = new MultithreadedDebugDrawer(this);
rbWorld->setDebugDrawer(m_debugDraw);
//m_childGuiHelper->createPhysicsDebugDrawer(rbWorld);
}
int m_removeTextureUid;
virtual void removeTexture(int textureUid)
{
m_removeTextureUid = textureUid;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperRemoveTexture);
workerThreadWait();
}
int m_updateShapeIndex;
float* m_updateShapeVertices;
virtual void updateShape(int shapeIndex, float* vertices)
{
m_updateShapeIndex = shapeIndex;
m_updateShapeVertices = vertices;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperUpdateShape);
workerThreadWait();
}
virtual int registerTexture(const unsigned char* texels, int width, int height)
{
int* cachedTexture = m_cachedTextureIds[texels];
if (cachedTexture)
{
return *cachedTexture;
}
m_texels = texels;
m_textureWidth = width;
m_textureHeight = height;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperRegisterTexture);
workerThreadWait();
m_cachedTextureIds.insert(texels, m_textureId);
return m_textureId;
}
virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices, int primitiveType, int textureId)
{
m_vertices = vertices;
m_numvertices = numvertices;
m_indices = indices;
m_numIndices = numIndices;
m_primitiveType = primitiveType;
m_textureId = textureId;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperRegisterGraphicsShape);
workerThreadWait();
return m_shapeIndex;
}
int m_visualizerFlag;
int m_visualizerEnable;
int m_renderedFrames;
void setVisualizerFlag(int flag, int enable)
{
m_visualizerFlag = flag;
m_visualizerEnable = enable;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperSetVisualizerFlag);
workerThreadWait();
}
void setVisualizerFlagCallback(VisualizerFlagCallback callback)
{
m_childGuiHelper->setVisualizerFlagCallback(callback);
}
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling)
{
m_shapeIndex = shapeIndex;
m_position = position;
m_quaternion = quaternion;
m_color = color;
m_scaling = scaling;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperRegisterGraphicsInstance);
workerThreadWait();
return m_instanceId;
}
virtual void removeAllGraphicsInstances()
{
m_cachedTextureIds.clear();
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperRemoveAllGraphicsInstances);
workerThreadWait();
}
int m_graphicsInstanceRemove;
virtual void removeGraphicsInstance(int graphicsUid)
{
m_graphicsInstanceRemove = graphicsUid;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperRemoveGraphicsInstance);
workerThreadWait();
}
int m_getShapeIndex_instance;
int getShapeIndex_shapeIndex;
virtual int getShapeIndexFromInstance(int instance)
{
m_getShapeIndex_instance = instance;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperGetShapeIndexFromInstance);
getShapeIndex_shapeIndex = -1;
workerThreadWait();
return getShapeIndex_shapeIndex;
}
int m_graphicsInstanceChangeTextureId;
int m_graphicsInstanceChangeTextureShapeIndex;
virtual void replaceTexture(int shapeIndex, int textureUid)
{
m_graphicsInstanceChangeTextureShapeIndex = shapeIndex;
m_graphicsInstanceChangeTextureId = textureUid;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperChangeGraphicsInstanceTextureId);
workerThreadWait();
}
int m_changeTextureUniqueId;
const unsigned char* m_changeTextureRgbTexels;
int m_changeTextureWidth;
int m_changeTextureHeight;
virtual void changeTexture(int textureUniqueId, const unsigned char* rgbTexels, int width, int height)
{
m_changeTextureUniqueId = textureUniqueId;
m_changeTextureRgbTexels = rgbTexels;
m_changeTextureWidth = width;
m_changeTextureHeight = height;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperChangeTexture);
workerThreadWait();
}
double m_rgbaColor[4];
int m_graphicsInstanceChangeColor;
virtual void changeRGBAColor(int instanceUid, const double rgbaColor[4])
{
m_graphicsInstanceChangeColor = instanceUid;
m_rgbaColor[0] = rgbaColor[0];
m_rgbaColor[1] = rgbaColor[1];
m_rgbaColor[2] = rgbaColor[2];
m_rgbaColor[3] = rgbaColor[3];
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperChangeGraphicsInstanceRGBAColor);
workerThreadWait();
}
double m_specularColor[3];
int m_graphicsInstanceChangeSpecular;
virtual void changeSpecularColor(int instanceUid, const double specularColor[3])
{
m_graphicsInstanceChangeSpecular = instanceUid;
m_specularColor[0] = specularColor[0];
m_specularColor[1] = specularColor[1];
m_specularColor[2] = specularColor[2];
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperChangeGraphicsInstanceSpecularColor);
workerThreadWait();
}
virtual Common2dCanvasInterface* get2dCanvasInterface()
{
return m_childGuiHelper->get2dCanvasInterface();
}
virtual CommonParameterInterface* getParameterInterface()
{
return 0;
}
virtual CommonRenderInterface* getRenderInterface()
{
return m_childGuiHelper->getRenderInterface();
}
virtual CommonGraphicsApp* getAppInterface()
{
return m_childGuiHelper->getAppInterface();
}
virtual void setUpAxis(int axis)
{
m_childGuiHelper->setUpAxis(axis);
}
virtual void resetCamera(float camDist, float yaw, float pitch, float camPosX, float camPosY, float camPosZ)
{
m_childGuiHelper->resetCamera(camDist, yaw, pitch, camPosX, camPosY, camPosZ);
}
virtual bool getCameraInfo(int* width, int* height, float viewMatrix[16], float projectionMatrix[16], float camUp[3], float camForward[3], float hor[3], float vert[3], float* yaw, float* pitch, float* camDist, float camTarget[3]) const
{
return m_childGuiHelper->getCameraInfo(width, height, viewMatrix, projectionMatrix, camUp, camForward, hor, vert, yaw, pitch, camDist, camTarget);
}
float m_viewMatrix[16];
float m_projectionMatrix[16];
unsigned char* m_pixelsRGBA;
int m_rgbaBufferSizeInPixels;
float* m_depthBuffer;
int m_depthBufferSizeInPixels;
int* m_segmentationMaskBuffer;
int m_segmentationMaskBufferSizeInPixels;
int m_startPixelIndex;
int m_destinationWidth;
int m_destinationHeight;
int* m_numPixelsCopied;
virtual void copyCameraImageData(const float viewMatrix[16], const float projectionMatrix[16],
unsigned char* pixelsRGBA, int rgbaBufferSizeInPixels,
float* depthBuffer, int depthBufferSizeInPixels,
int* segmentationMaskBuffer, int segmentationMaskBufferSizeInPixels,
int startPixelIndex, int destinationWidth,
int destinationHeight, int* numPixelsCopied)
{
m_cs->lock();
for (int i = 0; i < 16; i++)
{
m_viewMatrix[i] = viewMatrix[i];
m_projectionMatrix[i] = projectionMatrix[i];
}
m_pixelsRGBA = pixelsRGBA;
m_rgbaBufferSizeInPixels = rgbaBufferSizeInPixels;
m_depthBuffer = depthBuffer;
m_depthBufferSizeInPixels = depthBufferSizeInPixels;
m_segmentationMaskBuffer = segmentationMaskBuffer;
m_segmentationMaskBufferSizeInPixels = segmentationMaskBufferSizeInPixels;
m_startPixelIndex = startPixelIndex;
m_destinationWidth = destinationWidth;
m_destinationHeight = destinationHeight;
m_numPixelsCopied = numPixelsCopied;
m_cs->setSharedParam(1, eGUIHelperCopyCameraImageData);
workerThreadWait();
}
virtual void debugDisplayCameraImageData(const float viewMatrix[16], const float projectionMatrix[16],
unsigned char* pixelsRGBA, int rgbaBufferSizeInPixels,
float* depthBuffer, int depthBufferSizeInPixels,
int* segmentationMaskBuffer, int segmentationMaskBufferSizeInPixels,
int startPixelIndex, int destinationWidth, int destinationHeight, int* numPixelsCopied)
{
m_cs->lock();
for (int i = 0; i < 16; i++)
{
m_viewMatrix[i] = viewMatrix[i];
m_projectionMatrix[i] = projectionMatrix[i];
}
m_pixelsRGBA = pixelsRGBA;
m_rgbaBufferSizeInPixels = rgbaBufferSizeInPixels;
m_depthBuffer = depthBuffer;
m_depthBufferSizeInPixels = depthBufferSizeInPixels;
m_segmentationMaskBuffer = segmentationMaskBuffer;
m_segmentationMaskBufferSizeInPixels = segmentationMaskBufferSizeInPixels;
m_startPixelIndex = startPixelIndex;
m_destinationWidth = destinationWidth;
m_destinationHeight = destinationHeight;
m_numPixelsCopied = numPixelsCopied;
m_cs->setSharedParam(1, eGUIHelperDisplayCameraImageData);
workerThreadWait();
}
virtual void setProjectiveTextureMatrices(const float viewMatrix[16], const float projectionMatrix[16])
{
if (m_childGuiHelper->getAppInterface() && m_childGuiHelper->getAppInterface()->m_renderer)
{
m_childGuiHelper->getAppInterface()->m_renderer->setProjectiveTextureMatrices(viewMatrix, projectionMatrix);
}
}
virtual void setProjectiveTexture(bool useProjectiveTexture)
{
if (m_childGuiHelper->getAppInterface() && m_childGuiHelper->getAppInterface()->m_renderer)
{
m_childGuiHelper->getAppInterface()->m_renderer->setProjectiveTexture(useProjectiveTexture);
}
}
btDiscreteDynamicsWorld* m_dynamicsWorld;
virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld)
{
m_dynamicsWorld = rbWorld;
m_cs->lock();
m_cs->setSharedParam(1, eGUIHelperAutogenerateGraphicsObjects);
workerThreadWait();
}
virtual void drawText3D(const char* txt, float posX, float posZY, float posZ, float size)
{
}
virtual void drawText3D(const char* txt, float position[3], float orientation[4], float color[4], float size, int optionFlag)
{
}
btAlignedObjectArray<UserDebugText> m_userDebugText;
UserDebugText m_tmpText;
int m_resultUserDebugTextUid;
virtual int addUserDebugText3D(const char* txt, const double positionXYZ[3], const double orientation[4], const double textColorRGB[3], double size, double lifeTime, int trackingVisualShapeIndex, int optionFlags, int replaceItemUid)
{
if (replaceItemUid >= 0)
{
m_tmpText.m_itemUniqueId = replaceItemUid;
}
else
{
m_tmpText.m_itemUniqueId = m_uidGenerator++;
}
m_tmpText.m_lifeTime = lifeTime;
m_tmpText.textSize = size;
//int len = strlen(txt);
strcpy(m_tmpText.m_text, txt);
m_tmpText.m_textPositionXYZ1[0] = positionXYZ[0];
m_tmpText.m_textPositionXYZ1[1] = positionXYZ[1];
m_tmpText.m_textPositionXYZ1[2] = positionXYZ[2];
m_tmpText.m_textOrientation[0] = orientation[0];
m_tmpText.m_textOrientation[1] = orientation[1];
m_tmpText.m_textOrientation[2] = orientation[2];
m_tmpText.m_textOrientation[3] = orientation[3];
m_tmpText.m_textColorRGB[0] = textColorRGB[0];
m_tmpText.m_textColorRGB[1] = textColorRGB[1];
m_tmpText.m_textColorRGB[2] = textColorRGB[2];
m_tmpText.m_trackingVisualShapeIndex = trackingVisualShapeIndex;
m_tmpText.m_optionFlags = optionFlags;
m_tmpText.m_textOrientation[0] = orientation[0];
m_tmpText.m_textOrientation[1] = orientation[1];
m_tmpText.m_textOrientation[2] = orientation[2];
m_tmpText.m_textOrientation[3] = orientation[3];
m_cs->lock();
m_cs->setSharedParam(1, eGUIUserDebugAddText);
m_resultUserDebugTextUid = -1;
workerThreadWait();
return m_resultUserDebugTextUid;
}
btAlignedObjectArray<UserDebugParameter*> m_userDebugParams;
UserDebugParameter m_tmpParam;
virtual int readUserDebugParameter(int itemUniqueId, double* value)
{
for (int i = 0; i < m_userDebugParams.size(); i++)
{
if (m_userDebugParams[i]->m_itemUniqueId == itemUniqueId)
{
*value = m_userDebugParams[i]->m_value;
return 1;
}
}
return 0;
}
int m_userDebugParamUid;
virtual int addUserDebugParameter(const char* txt, double rangeMin, double rangeMax, double startValue)
{
strcpy(m_tmpParam.m_text, txt);
m_tmpParam.m_rangeMin = rangeMin;
m_tmpParam.m_rangeMax = rangeMax;
m_tmpParam.m_value = startValue;
m_tmpParam.m_itemUniqueId = m_uidGenerator++;
m_cs->lock();
m_cs->setSharedParam(1, eGUIUserDebugAddParameter);
m_userDebugParamUid = -1;
workerThreadWait();
return m_userDebugParamUid;
}
btAlignedObjectArray<UserDebugDrawLine> m_userDebugLines;
UserDebugDrawLine m_tmpLine;
int m_resultDebugLineUid;
virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime, int trackingVisualShapeIndex, int replaceItemUid)
{
m_tmpLine.m_lifeTime = lifeTime;
m_tmpLine.m_lineWidth = lineWidth;
m_tmpLine.m_itemUniqueId = replaceItemUid < 0 ? m_uidGenerator++ : replaceItemUid;
m_tmpLine.m_debugLineFromXYZ[0] = debugLineFromXYZ[0];
m_tmpLine.m_debugLineFromXYZ[1] = debugLineFromXYZ[1];
m_tmpLine.m_debugLineFromXYZ[2] = debugLineFromXYZ[2];
m_tmpLine.m_debugLineToXYZ[0] = debugLineToXYZ[0];
m_tmpLine.m_debugLineToXYZ[1] = debugLineToXYZ[1];
m_tmpLine.m_debugLineToXYZ[2] = debugLineToXYZ[2];
m_tmpLine.m_debugLineColorRGB[0] = debugLineColorRGB[0];
m_tmpLine.m_debugLineColorRGB[1] = debugLineColorRGB[1];
m_tmpLine.m_debugLineColorRGB[2] = debugLineColorRGB[2];
m_tmpLine.m_trackingVisualShapeIndex = trackingVisualShapeIndex;
m_tmpLine.m_replaceItemUid = replaceItemUid;
//don't block when replacing an item
if (replaceItemUid>=0 && replaceItemUid<m_userDebugLines.size())
{
//find the right slot
int slot=-1;
for (int i=0;i<m_userDebugLines.size();i++)
{
if (replaceItemUid == m_userDebugLines[i].m_itemUniqueId)
{
slot = i;
}
}
if (slot>=0)
{
m_userDebugLines[slot] = m_tmpLine;
}
m_resultDebugLineUid = replaceItemUid;
}
else
{
m_cs->lock();
m_cs->setSharedParam(1, eGUIUserDebugAddLine);
m_resultDebugLineUid = -1;
workerThreadWait();
}
return m_resultDebugLineUid;
}
int m_removeDebugItemUid;
virtual void removeUserDebugItem(int debugItemUniqueId)
{
m_removeDebugItemUid = debugItemUniqueId;
m_cs->lock();
m_cs->setSharedParam(1, eGUIUserDebugRemoveItem);
workerThreadWait();
}
virtual void removeAllUserDebugItems()
{
m_cs->lock();
m_cs->setSharedParam(1, eGUIUserDebugRemoveAllItems);
workerThreadWait();
}
virtual void removeAllUserParameters()
{
m_cs->lock();
m_cs->setSharedParam(1, eGUIUserDebugRemoveAllParameters);
workerThreadWait();
}
const char* m_mp4FileName;
virtual void dumpFramesToVideo(const char* mp4FileName)
{
m_cs->lock();
m_mp4FileName = mp4FileName;
m_cs->setSharedParam(1, eGUIDumpFramesToVideo);
workerThreadWait();
m_mp4FileName = 0;
}
};
class PhysicsServerExample : public SharedMemoryCommon
{
PhysicsServerSharedMemory m_physicsServer;
b3ThreadSupportInterface* m_threadSupport;
MotionArgs m_args[MAX_MOTION_NUM_THREADS];
MultiThreadedOpenGLGuiHelper* m_multiThreadedHelper;
bool m_wantsShutdown;
bool m_isConnected;
btClock m_clock;
bool m_replay;
struct Common2dCanvasInterface* m_canvas;
int m_canvasRGBIndex;
int m_canvasDepthIndex;
int m_canvasSegMaskIndex;
// int m_options;
#ifdef BT_ENABLE_VR
TinyVRGui* m_tinyVrGui;
#endif
int m_renderedFrames;
public:
PhysicsServerExample(MultiThreadedOpenGLGuiHelper* helper, CommandProcessorCreationInterface* commandProcessorCreator, SharedMemoryInterface* sharedMem = 0, int options = 0);
virtual ~PhysicsServerExample();
virtual void initPhysics();
virtual void stepSimulation(float deltaTime);
virtual void updateGraphics();
void enableCommandLogging()
{
m_physicsServer.enableCommandLogging(true, "BulletPhysicsCommandLog.bin");
}
void replayFromLogFile()
{
m_replay = true;
m_physicsServer.replayFromLogFile("BulletPhysicsCommandLog.bin");
}
virtual void resetCamera()
{
float dist = 5;
float pitch = -35;
float yaw = 50;
float targetPos[3] = {0, 0, 0}; //-3,2.8,-2.5};
m_guiHelper->resetCamera(dist, yaw, pitch, targetPos[0], targetPos[1], targetPos[2]);
}
virtual bool wantsTermination();
virtual bool isConnected();
virtual void renderScene();
void drawUserDebugLines();
virtual void exitPhysics();
virtual void physicsDebugDraw(int debugFlags);
btVector3 getRayTo(int x, int y);
virtual void vrControllerButtonCallback(int controllerId, int button, int state, float pos[4], float orn[4]);
virtual void vrControllerMoveCallback(int controllerId, float pos[4], float orn[4], float analogAxis, float auxAnalogAxes[10]);
virtual void vrHMDMoveCallback(int controllerId, float pos[4], float orientation[4]);
virtual void vrGenericTrackerMoveCallback(int controllerId, float pos[4], float orientation[4]);
virtual bool mouseMoveCallback(float x, float y)
{
if (m_replay)
return false;
CommonRenderInterface* renderer = m_multiThreadedHelper->m_childGuiHelper->getRenderInterface(); // m_guiHelper->getRenderInterface();
if (!renderer)
{
return false;
}
b3MouseEvent event;
event.m_buttonState = 0;
event.m_buttonIndex = -1;
event.m_mousePosX = x;
event.m_mousePosY = y;
event.m_eventType = MOUSE_MOVE_EVENT;
m_args[0].m_csGUI->lock();
m_args[0].m_allMouseEvents.push_back(event);
m_args[0].m_csGUI->unlock();
btVector3 rayTo = getRayTo(int(x), int(y));
btVector3 rayFrom;
renderer->getActiveCamera()->getCameraPosition(rayFrom);
MyMouseCommand cmd;
cmd.m_rayFrom = rayFrom;
cmd.m_rayTo = rayTo;
cmd.m_type = MyMouseMove;
m_args[0].m_csGUI->lock();
m_args[0].m_mouseCommands.push_back(cmd);
m_args[0].m_csGUI->unlock();
return false;
};
virtual bool mouseButtonCallback(int button, int state, float x, float y)
{
if (m_replay)
return false;
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
if (!renderer)
{
return false;
}
CommonWindowInterface* window = m_guiHelper->getAppInterface()->m_window;
b3MouseEvent event;
event.m_buttonIndex = button;
event.m_mousePosX = x;
event.m_mousePosY = y;
event.m_eventType = MOUSE_BUTTON_EVENT;
if (state)
{
event.m_buttonState = eButtonIsDown + eButtonTriggered;
}
else
{
event.m_buttonState = eButtonReleased;
}
m_args[0].m_csGUI->lock();
m_args[0].m_allMouseEvents.push_back(event);
m_args[0].m_csGUI->unlock();
if (state == 1)
{
if (button == 0 && (!window->isModifierKeyPressed(B3G_ALT) && !window->isModifierKeyPressed(B3G_CONTROL)))
{
btVector3 camPos;
renderer->getActiveCamera()->getCameraPosition(camPos);
btVector3 rayFrom = camPos;
btVector3 rayTo = getRayTo(int(x), int(y));
MyMouseCommand cmd;
cmd.m_rayFrom = rayFrom;
cmd.m_rayTo = rayTo;
cmd.m_type = MyMouseButtonDown;
m_args[0].m_csGUI->lock();
m_args[0].m_mouseCommands.push_back(cmd);
m_args[0].m_csGUI->unlock();
}
}
else
{
if (button == 0)
{
//m_physicsServer.removePickingConstraint();
MyMouseCommand cmd;
cmd.m_rayFrom.setValue(0, 0, 0);
cmd.m_rayTo.setValue(0, 0, 0);
cmd.m_type = MyMouseButtonUp;
m_args[0].m_csGUI->lock();
m_args[0].m_mouseCommands.push_back(cmd);
m_args[0].m_csGUI->unlock();
//remove p2p
}
}
//printf("button=%d, state=%d\n",button,state);
return false;
}
virtual bool keyboardCallback(int key, int state)
{
//printf("key=%d, state=%d\n", key,state);
{
m_args[0].m_csGUI->lock();
int keyIndex = -1;
//is already there?
for (int i = 0; i < m_args[0].m_keyboardEvents.size(); i++)
{
if (m_args[0].m_keyboardEvents[i].m_keyCode == key)
{
keyIndex = i;
break;
}
}
if (state)
{
b3KeyboardEvent ev;
ev.m_keyCode = key;
ev.m_keyState = eButtonIsDown + eButtonTriggered;
if (keyIndex >= 0)
{
if (0 == (m_args[0].m_keyboardEvents[keyIndex].m_keyState & eButtonIsDown))
{
m_args[0].m_keyboardEvents[keyIndex] = ev;
}
}
else
{
m_args[0].m_keyboardEvents.push_back(ev);
}
}
else
{
b3KeyboardEvent ev;
ev.m_keyCode = key;
ev.m_keyState = eButtonReleased;
if (keyIndex >= 0)
{
m_args[0].m_keyboardEvents[keyIndex] = ev;
}
else
{
m_args[0].m_keyboardEvents.push_back(ev);
}
}
m_args[0].m_csGUI->unlock();
}
/*printf("m_args[0].m_keyboardEvents.size()=%d\n", m_args[0].m_keyboardEvents.size());
for (int i=0;i<m_args[0].m_keyboardEvents.size();i++)
{
printf("key[%d]=%d state = %d\n",i,m_args[0].m_keyboardEvents[i].m_keyCode,m_args[0].m_keyboardEvents[i].m_keyState);
}
*/
double shift = 0.1;
CommonWindowInterface* window = m_guiHelper->getAppInterface()->m_window;
if (window->isModifierKeyPressed(B3G_SHIFT))
shift = 0.01;
btVector3 VRTeleportPos = this->m_physicsServer.getVRTeleportPosition();
if (gEnableDefaultKeyboardShortcuts)
{
if (m_guiHelper->getAppInterface()->m_renderer->getActiveCamera()->isVRCamera())
{
if (key == 'w' && state)
{
VRTeleportPos[0] += shift;
m_physicsServer.setVRTeleportPosition(VRTeleportPos);
saveCurrentSettingsVR(VRTeleportPos);
}
if (key == 's' && state)
{
VRTeleportPos[0] -= shift;
m_physicsServer.setVRTeleportPosition(VRTeleportPos);
saveCurrentSettingsVR(VRTeleportPos);
}
if (key == 'a' && state)
{
VRTeleportPos[1] -= shift;
m_physicsServer.setVRTeleportPosition(VRTeleportPos);
saveCurrentSettingsVR(VRTeleportPos);
}
if (key == 'd' && state)
{
VRTeleportPos[1] += shift;
m_physicsServer.setVRTeleportPosition(VRTeleportPos);
saveCurrentSettingsVR(VRTeleportPos);
}
if (key == 'q' && state)
{
VRTeleportPos[2] += shift;
m_physicsServer.setVRTeleportPosition(VRTeleportPos);
saveCurrentSettingsVR(VRTeleportPos);
}
if (key == 'e' && state)
{
VRTeleportPos[2] -= shift;
m_physicsServer.setVRTeleportPosition(VRTeleportPos);
saveCurrentSettingsVR(VRTeleportPos);
}
if (key == 'z' && state)
{
gVRTeleportRotZ += shift;
btQuaternion VRTeleportOrn = btQuaternion(btVector3(0, 0, 1), gVRTeleportRotZ);
m_physicsServer.setVRTeleportOrientation(VRTeleportOrn);
saveCurrentSettingsVR(VRTeleportPos);
}
}
}
return false;
}
virtual void setSharedMemoryKey(int key)
{
m_physicsServer.setSharedMemoryKey(key);
}
virtual void processCommandLineArgs(int argc, char* argv[])
{
b3CommandLineArgs args(argc, argv);
loadCurrentSettingsVR(args);
int shmemKey;
if (args.GetCmdLineArgument("sharedMemoryKey", shmemKey))
{
setSharedMemoryKey(shmemKey);
}
btVector3 vrTeleportPos = m_physicsServer.getVRTeleportPosition();
if (args.GetCmdLineArgument("camPosX", vrTeleportPos[0]))
{
printf("camPosX=%f\n", vrTeleportPos[0]);
}
if (args.GetCmdLineArgument("camPosY", vrTeleportPos[1]))
{
printf("camPosY=%f\n", vrTeleportPos[1]);
}
if (args.GetCmdLineArgument("camPosZ", vrTeleportPos[2]))
{
printf("camPosZ=%f\n", vrTeleportPos[2]);
}
m_physicsServer.setVRTeleportPosition(vrTeleportPos);
float camRotZ = 0.f;
if (args.GetCmdLineArgument("camRotZ", camRotZ))
{
printf("camRotZ = %f\n", camRotZ);
btQuaternion ornZ(btVector3(0, 0, 1), camRotZ);
m_physicsServer.setVRTeleportOrientation(ornZ);
}
if (args.CheckCmdLineFlag("realtimesimulation"))
{
//gEnableRealTimeSimVR = true;
m_physicsServer.enableRealTimeSimulation(true);
}
if (args.CheckCmdLineFlag("disableDefaultKeyboardShortcuts"))
{
gEnableDefaultKeyboardShortcuts = false;
}
if (args.CheckCmdLineFlag("enableDefaultKeyboardShortcuts"))
{
gEnableDefaultKeyboardShortcuts = true;
}
if (args.CheckCmdLineFlag("disableDefaultMousePicking"))
{
gEnableDefaultMousePicking = false;
}
if (args.CheckCmdLineFlag("enableDefaultMousePicking"))
{
gEnableDefaultMousePicking = true;
}
}
};
PhysicsServerExample::PhysicsServerExample(MultiThreadedOpenGLGuiHelper* helper, CommandProcessorCreationInterface* commandProcessorCreator, SharedMemoryInterface* sharedMem, int options)
: SharedMemoryCommon(helper),
m_physicsServer(commandProcessorCreator, sharedMem, 0),
m_wantsShutdown(false),
m_isConnected(false),
m_replay(false),
m_canvas(0),
m_canvasRGBIndex(-1),
m_canvasDepthIndex(-1),
m_canvasSegMaskIndex(-1)
//m_options(options)
#ifdef BT_ENABLE_VR
,
m_tinyVrGui(0)
#endif
,
m_renderedFrames(0)
{
m_multiThreadedHelper = helper;
// b3Printf("Started PhysicsServer\n");
}
PhysicsServerExample::~PhysicsServerExample()
{
if (m_canvas)
{
if (m_canvasRGBIndex >= 0)
m_canvas->destroyCanvas(m_canvasRGBIndex);
if (m_canvasDepthIndex >= 0)
m_canvas->destroyCanvas(m_canvasDepthIndex);
if (m_canvasSegMaskIndex >= 0)
m_canvas->destroyCanvas(m_canvasSegMaskIndex);
}
#ifdef BT_ENABLE_VR
delete m_tinyVrGui;
#endif
bool deInitializeSharedMemory = true;
m_physicsServer.disconnectSharedMemory(deInitializeSharedMemory);
m_isConnected = false;
delete m_multiThreadedHelper;
}
bool PhysicsServerExample::isConnected()
{
return m_isConnected;
}
void PhysicsServerExample::initPhysics()
{
///for this testing we use Z-axis up
int upAxis = 2;
m_guiHelper->setUpAxis(upAxis);
m_threadSupport = createMotionThreadSupport(MAX_MOTION_NUM_THREADS);
m_isConnected = m_physicsServer.connectSharedMemory(m_guiHelper);
for (int i = 0; i < m_threadSupport->getNumTasks(); i++)
{
MotionThreadLocalStorage* storage = (MotionThreadLocalStorage*)m_threadSupport->getThreadLocalMemory(i);
b3Assert(storage);
storage->threadId = i;
//storage->m_sharedMem = data->m_sharedMem;
}
for (int w = 0; w < MAX_MOTION_NUM_THREADS; w++)
{
m_args[w].m_cs = m_threadSupport->createCriticalSection();
m_args[w].m_cs2 = m_threadSupport->createCriticalSection();
m_args[w].m_cs3 = m_threadSupport->createCriticalSection();
m_args[w].m_csGUI = m_threadSupport->createCriticalSection();
m_multiThreadedHelper->setCriticalSection(m_args[w].m_cs);
m_multiThreadedHelper->setCriticalSection2(m_args[w].m_cs2);
m_multiThreadedHelper->setCriticalSection3(m_args[w].m_cs3);
m_multiThreadedHelper->setCriticalSectionGUI(m_args[w].m_csGUI);
m_args[w].m_cs->lock();
m_args[w].m_cs->setSharedParam(0, eMotionIsUnInitialized);
m_args[w].m_cs->unlock();
int numMoving = 0;
m_args[w].m_positions.resize(numMoving);
m_args[w].m_physicsServerPtr = &m_physicsServer;
//int index = 0;
m_threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*)&this->m_args[w], w);
bool isUninitialized = true;
while (isUninitialized)
{
m_args[w].m_cs->lock();
isUninitialized = (m_args[w].m_cs->getSharedParam(0) == eMotionIsUnInitialized);
m_args[w].m_cs->unlock();
#ifdef _WIN32
b3Clock::usleep(1000);
#endif
}
}
m_args[0].m_cs->lock();
m_args[0].m_cs->setSharedParam(1, eGUIHelperIdle);
m_args[0].m_cs->unlock();
m_args[0].m_cs2->lock();
{
m_canvas = m_guiHelper->get2dCanvasInterface();
if (m_canvas)
{
m_canvasRGBIndex = m_canvas->createCanvas("Synthetic Camera RGB data", gCamVisualizerWidth, gCamVisualizerHeight, 8, 55);
m_canvasDepthIndex = m_canvas->createCanvas("Synthetic Camera Depth data", gCamVisualizerWidth, gCamVisualizerHeight, 8, 75 + gCamVisualizerHeight);
m_canvasSegMaskIndex = m_canvas->createCanvas("Synthetic Camera Segmentation Mask", gCamVisualizerWidth, gCamVisualizerHeight, 8, 95 + gCamVisualizerHeight * 2);
for (int i = 0; i < gCamVisualizerWidth; i++)
{
for (int j = 0; j < gCamVisualizerHeight; j++)
{
unsigned char red = 255;
unsigned char green = 255;
unsigned char blue = 255;
unsigned char alpha = 255;
if (i == j)
{
red = 0;
green = 0;
blue = 0;
}
m_canvas->setPixel(m_canvasRGBIndex, i, j, red, green, blue, alpha);
if (m_canvasSegMaskIndex >= 0)
m_canvas->setPixel(m_canvasDepthIndex, i, j, red, green, blue, alpha);
if (m_canvasSegMaskIndex >= 0)
m_canvas->setPixel(m_canvasSegMaskIndex, i, j, red, green, blue, alpha);
}
}
m_canvas->refreshImageData(m_canvasRGBIndex);
if (m_canvasDepthIndex >= 0)
m_canvas->refreshImageData(m_canvasDepthIndex);
if (m_canvasSegMaskIndex >= 0)
m_canvas->refreshImageData(m_canvasSegMaskIndex);
}
}
}
void PhysicsServerExample::exitPhysics()
{
for (int i = 0; i < MAX_MOTION_NUM_THREADS; i++)
{
m_args[i].m_cs2->unlock();
m_args[i].m_cs->lock();
m_args[i].m_cs->setSharedParam(0, eRequestTerminateMotion);
m_args[i].m_cs->unlock();
}
int numActiveThreads = MAX_MOTION_NUM_THREADS;
while (numActiveThreads)
{
int arg0, arg1;
if (m_threadSupport->isTaskCompleted(&arg0, &arg1, 0))
{
numActiveThreads--;
printf("numActiveThreads = %d\n", numActiveThreads);
}
else
{
b3Clock::usleep(0);
}
//we need to call 'stepSimulation' to make sure that
//other threads get out of blocking state (workerThreadWait)
stepSimulation(0);
};
printf("stopping threads\n");
m_threadSupport->deleteCriticalSection(m_args[0].m_cs);
m_threadSupport->deleteCriticalSection(m_args[0].m_cs2);
m_threadSupport->deleteCriticalSection(m_args[0].m_cs3);
m_threadSupport->deleteCriticalSection(m_args[0].m_csGUI);
delete m_threadSupport;
m_threadSupport = 0;
//m_physicsServer.resetDynamicsWorld();
}
bool PhysicsServerExample::wantsTermination()
{
return m_wantsShutdown;
}
void PhysicsServerExample::updateGraphics()
{
//check if any graphics related tasks are requested
switch (m_multiThreadedHelper->getCriticalSection()->getSharedParam(1))
{
case eGUIHelperCreateCollisionShapeGraphicsObject:
{
B3_PROFILE("eGUIHelperCreateCollisionShapeGraphicsObject");
m_multiThreadedHelper->m_childGuiHelper->createCollisionShapeGraphicsObject(m_multiThreadedHelper->m_colShape);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperCreateCollisionObjectGraphicsObject:
{
B3_PROFILE("eGUIHelperCreateCollisionObjectGraphicsObject");
m_multiThreadedHelper->m_childGuiHelper->createCollisionObjectGraphicsObject(m_multiThreadedHelper->m_obj,
m_multiThreadedHelper->m_color2);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperCreateRigidBodyGraphicsObject:
{
B3_PROFILE("eGUIHelperCreateRigidBodyGraphicsObject");
m_multiThreadedHelper->m_childGuiHelper->createRigidBodyGraphicsObject(m_multiThreadedHelper->m_body, m_multiThreadedHelper->m_color3);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperRegisterTexture:
{
B3_PROFILE("eGUIHelperRegisterTexture");
m_multiThreadedHelper->m_textureId = m_multiThreadedHelper->m_childGuiHelper->registerTexture(m_multiThreadedHelper->m_texels,
m_multiThreadedHelper->m_textureWidth, m_multiThreadedHelper->m_textureHeight);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperRemoveTexture:
{
B3_PROFILE("eGUIHelperRemoveTexture");
m_multiThreadedHelper->m_childGuiHelper->removeTexture(m_multiThreadedHelper->m_removeTextureUid);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperUpdateShape:
{
B3_PROFILE("eGUIHelperUpdateShape");
m_multiThreadedHelper->m_childGuiHelper->updateShape(m_multiThreadedHelper->m_updateShapeIndex, m_multiThreadedHelper->m_updateShapeVertices);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperRegisterGraphicsShape:
{
B3_PROFILE("eGUIHelperRegisterGraphicsShape");
m_multiThreadedHelper->m_shapeIndex = m_multiThreadedHelper->m_childGuiHelper->registerGraphicsShape(
m_multiThreadedHelper->m_vertices,
m_multiThreadedHelper->m_numvertices,
m_multiThreadedHelper->m_indices,
m_multiThreadedHelper->m_numIndices,
m_multiThreadedHelper->m_primitiveType,
m_multiThreadedHelper->m_textureId);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperSetVisualizerFlag:
{
B3_PROFILE("eGUIHelperSetVisualizerFlag");
int flag = m_multiThreadedHelper->m_visualizerFlag;
int enable = m_multiThreadedHelper->m_visualizerEnable;
if (flag == COV_ENABLE_RGB_BUFFER_PREVIEW)
{
if (enable)
{
if (m_canvasRGBIndex < 0)
{
m_canvasRGBIndex = m_canvas->createCanvas("Synthetic Camera RGB data", gCamVisualizerWidth, gCamVisualizerHeight, 8, 55);
}
}
else
{
if (m_canvasRGBIndex >= 0)
{
m_canvas->destroyCanvas(m_canvasRGBIndex);
m_canvasRGBIndex = -1;
}
}
}
if (flag == COV_ENABLE_DEPTH_BUFFER_PREVIEW)
{
if (enable)
{
if (m_canvasDepthIndex < 0)
{
m_canvasDepthIndex = m_canvas->createCanvas("Synthetic Camera Depth data", gCamVisualizerWidth, gCamVisualizerHeight, 8, 75 + gCamVisualizerHeight);
}
}
else
{
if (m_canvasDepthIndex >= 0)
{
m_canvas->destroyCanvas(m_canvasDepthIndex);
m_canvasDepthIndex = -1;
}
}
}
if (flag == COV_ENABLE_SEGMENTATION_MARK_PREVIEW)
{
if (enable)
{
if (m_canvasSegMaskIndex < 0)
{
m_canvasSegMaskIndex = m_canvas->createCanvas("Synthetic Camera Segmentation Mask", gCamVisualizerWidth, gCamVisualizerHeight, 8, 95 + gCamVisualizerHeight * 2);
}
}
else
{
if (m_canvasSegMaskIndex >= 0)
{
m_canvas->destroyCanvas(m_canvasSegMaskIndex);
m_canvasSegMaskIndex = -1;
}
}
}
if (flag == COV_ENABLE_VR_TELEPORTING)
{
gEnableTeleporting = (enable != 0);
}
if (flag == COV_ENABLE_VR_PICKING)
{
gEnablePicking = (enable != 0);
}
if (flag == COV_ENABLE_SYNC_RENDERING_INTERNAL)
{
gEnableSyncPhysicsRendering = (enable != 0);
}
if (flag == COV_ENABLE_RENDERING)
{
gEnableRendering = (enable != 0);
}
if (flag == COV_ENABLE_KEYBOARD_SHORTCUTS)
{
gEnableDefaultKeyboardShortcuts = (enable != 0);
}
if (flag == COV_ENABLE_MOUSE_PICKING)
{
gEnableDefaultMousePicking = (enable != 0);
}
m_multiThreadedHelper->m_renderedFrames = m_renderedFrames;
m_multiThreadedHelper->m_childGuiHelper->setVisualizerFlag(m_multiThreadedHelper->m_visualizerFlag, m_multiThreadedHelper->m_visualizerEnable);
//postpone the release until an actual frame is rendered
if (flag == COV_ENABLE_SINGLE_STEP_RENDERING)
{
m_multiThreadedHelper->getCriticalSection()->setSharedParam(1, eGUIHelperSetVisualizerFlagCheckRenderedFrame);
}
else
{
m_multiThreadedHelper->mainThreadRelease();
}
break;
}
case eGUIHelperSetVisualizerFlagCheckRenderedFrame:
{
if (m_renderedFrames != m_multiThreadedHelper->m_renderedFrames)
{
m_multiThreadedHelper->mainThreadRelease();
}
break;
}
case eGUIHelperRegisterGraphicsInstance:
{
B3_PROFILE("eGUIHelperRegisterGraphicsInstance");
m_multiThreadedHelper->m_instanceId = m_multiThreadedHelper->m_childGuiHelper->registerGraphicsInstance(
m_multiThreadedHelper->m_shapeIndex,
m_multiThreadedHelper->m_position,
m_multiThreadedHelper->m_quaternion,
m_multiThreadedHelper->m_color,
m_multiThreadedHelper->m_scaling);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperRemoveAllGraphicsInstances:
{
B3_PROFILE("eGUIHelperRemoveAllGraphicsInstances");
#ifdef BT_ENABLE_VR
if (m_tinyVrGui)
{
delete m_tinyVrGui;
m_tinyVrGui = 0;
}
#endif //BT_ENABLE_VR
m_multiThreadedHelper->m_childGuiHelper->removeAllGraphicsInstances();
if (m_multiThreadedHelper->m_childGuiHelper->getRenderInterface())
{
int numRenderInstances;
numRenderInstances = m_multiThreadedHelper->m_childGuiHelper->getRenderInterface()->getTotalNumInstances();
b3Assert(numRenderInstances == 0);
}
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperRemoveGraphicsInstance:
{
B3_PROFILE("eGUIHelperRemoveGraphicsInstance");
m_multiThreadedHelper->m_childGuiHelper->removeGraphicsInstance(m_multiThreadedHelper->m_graphicsInstanceRemove);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperGetShapeIndexFromInstance:
{
B3_PROFILE("eGUIHelperGetShapeIndexFromInstance");
m_multiThreadedHelper->getShapeIndex_shapeIndex = m_multiThreadedHelper->m_childGuiHelper->getShapeIndexFromInstance(m_multiThreadedHelper->m_getShapeIndex_instance);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperChangeGraphicsInstanceTextureId:
{
B3_PROFILE("eGUIHelperChangeGraphicsInstanceTextureId");
m_multiThreadedHelper->m_childGuiHelper->replaceTexture(
m_multiThreadedHelper->m_graphicsInstanceChangeTextureShapeIndex,
m_multiThreadedHelper->m_graphicsInstanceChangeTextureId);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperChangeTexture:
{
B3_PROFILE("eGUIHelperChangeTexture");
m_multiThreadedHelper->m_childGuiHelper->changeTexture(
m_multiThreadedHelper->m_changeTextureUniqueId,
m_multiThreadedHelper->m_changeTextureRgbTexels,
m_multiThreadedHelper->m_changeTextureWidth,
m_multiThreadedHelper->m_changeTextureHeight);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperChangeGraphicsInstanceRGBAColor:
{
B3_PROFILE("eGUIHelperChangeGraphicsInstanceRGBAColor");
m_multiThreadedHelper->m_childGuiHelper->changeRGBAColor(m_multiThreadedHelper->m_graphicsInstanceChangeColor, m_multiThreadedHelper->m_rgbaColor);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperChangeGraphicsInstanceSpecularColor:
{
B3_PROFILE("eGUIHelperChangeGraphicsInstanceSpecularColor");
m_multiThreadedHelper->m_childGuiHelper->changeSpecularColor(m_multiThreadedHelper->m_graphicsInstanceChangeSpecular, m_multiThreadedHelper->m_specularColor);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperDisplayCameraImageData:
{
B3_PROFILE("eGUIHelperDisplayCameraImageData");
if (m_canvas)
{
int numBytesPerPixel = 4;
int startRGBIndex = m_multiThreadedHelper->m_startPixelIndex * numBytesPerPixel;
int endRGBIndex = startRGBIndex + (*m_multiThreadedHelper->m_numPixelsCopied * numBytesPerPixel);
int startDepthIndex = m_multiThreadedHelper->m_startPixelIndex;
int endDepthIndex = startDepthIndex + (*m_multiThreadedHelper->m_numPixelsCopied);
int startSegIndex = m_multiThreadedHelper->m_startPixelIndex;
int endSegIndex = startSegIndex + (*m_multiThreadedHelper->m_numPixelsCopied);
//btScalar frustumZNear = m_multiThreadedHelper->m_projectionMatrix[14]/(m_multiThreadedHelper->m_projectionMatrix[10]-1);
//btScalar frustumZFar = m_multiThreadedHelper->m_projectionMatrix[14]/(m_multiThreadedHelper->m_projectionMatrix[10]+1);
for (int i = 0; i < gCamVisualizerWidth; i++)
{
for (int j = 0; j < gCamVisualizerHeight; j++)
{
int xIndex = int(float(i) * (float(m_multiThreadedHelper->m_destinationWidth) / float(gCamVisualizerWidth)));
int yIndex = int(float(j) * (float(m_multiThreadedHelper->m_destinationHeight) / float(gCamVisualizerHeight)));
btClamp(xIndex, 0, m_multiThreadedHelper->m_destinationWidth);
btClamp(yIndex, 0, m_multiThreadedHelper->m_destinationHeight);
int bytesPerPixel = 4; //RGBA
if (m_canvasRGBIndex >= 0)
{
int rgbPixelIndex = (xIndex + yIndex * m_multiThreadedHelper->m_destinationWidth) * bytesPerPixel;
if (rgbPixelIndex >= startRGBIndex && rgbPixelIndex < endRGBIndex)
{
m_canvas->setPixel(m_canvasRGBIndex, i, j,
m_multiThreadedHelper->m_pixelsRGBA[rgbPixelIndex - startRGBIndex],
m_multiThreadedHelper->m_pixelsRGBA[rgbPixelIndex + 1 - startRGBIndex],
m_multiThreadedHelper->m_pixelsRGBA[rgbPixelIndex + 2 - startRGBIndex],
255); //alpha set to 255
}
}
if (m_canvasDepthIndex >= 0 && 0 != m_multiThreadedHelper->m_depthBuffer)
{
int depthPixelIndex = (xIndex + yIndex * m_multiThreadedHelper->m_destinationWidth);
if (depthPixelIndex >= startDepthIndex && depthPixelIndex < endDepthIndex)
{
float depthValue = m_multiThreadedHelper->m_depthBuffer[depthPixelIndex - startDepthIndex];
//todo: rescale the depthValue to [0..255]
if (depthValue > -1e20)
{
int rgb = 0;
btScalar frustumZNear = 0.1;
btScalar frustumZFar = 30;
btScalar minDepthValue = frustumZNear; //todo: compute more reasonably min/max depth range
btScalar maxDepthValue = frustumZFar;
float depth = depthValue;
btScalar linearDepth = 255. * (2.0 * frustumZNear) / (frustumZFar + frustumZNear - depth * (frustumZFar - frustumZNear));
btClamp(linearDepth, btScalar(0), btScalar(255));
rgb = linearDepth;
m_canvas->setPixel(m_canvasDepthIndex, i, j,
rgb,
rgb,
255, 255); //alpha set to 255
}
else
{
m_canvas->setPixel(m_canvasDepthIndex, i, j,
0,
0,
0, 255); //alpha set to 255
}
}
}
if (m_canvasSegMaskIndex >= 0 && (0 != m_multiThreadedHelper->m_segmentationMaskBuffer))
{
int segmentationMaskPixelIndex = (xIndex + yIndex * m_multiThreadedHelper->m_destinationWidth);
if (segmentationMaskPixelIndex >= startSegIndex && segmentationMaskPixelIndex < endSegIndex)
{
int segmentationMask = m_multiThreadedHelper->m_segmentationMaskBuffer[segmentationMaskPixelIndex - startSegIndex];
btVector4 palette[4] = {btVector4(32, 255, 32, 255),
btVector4(32, 32, 255, 255),
btVector4(255, 255, 32, 255),
btVector4(32, 255, 255, 255)};
if (segmentationMask >= 0)
{
int obIndex = segmentationMask & ((1 << 24) - 1);
int linkIndex = (segmentationMask >> 24) - 1;
btVector4 rgb = palette[(obIndex + linkIndex) & 3];
m_canvas->setPixel(m_canvasSegMaskIndex, i, j,
rgb.x(),
rgb.y(),
rgb.z(), 255); //alpha set to 255
}
else
{
m_canvas->setPixel(m_canvasSegMaskIndex, i, j,
0,
0,
0, 255); //alpha set to 255
}
}
}
}
}
if (m_canvasRGBIndex >= 0)
m_canvas->refreshImageData(m_canvasRGBIndex);
if (m_canvasDepthIndex >= 0)
m_canvas->refreshImageData(m_canvasDepthIndex);
if (m_canvasSegMaskIndex >= 0)
m_canvas->refreshImageData(m_canvasSegMaskIndex);
}
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperCopyCameraImageData:
{
B3_PROFILE("eGUIHelperCopyCameraImageData");
if (m_multiThreadedHelper->m_startPixelIndex == 0)
{
m_physicsServer.syncPhysicsToGraphics();
}
m_multiThreadedHelper->m_childGuiHelper->copyCameraImageData(m_multiThreadedHelper->m_viewMatrix,
m_multiThreadedHelper->m_projectionMatrix,
m_multiThreadedHelper->m_pixelsRGBA,
m_multiThreadedHelper->m_rgbaBufferSizeInPixels,
m_multiThreadedHelper->m_depthBuffer,
m_multiThreadedHelper->m_depthBufferSizeInPixels,
m_multiThreadedHelper->m_segmentationMaskBuffer,
m_multiThreadedHelper->m_segmentationMaskBufferSizeInPixels,
m_multiThreadedHelper->m_startPixelIndex,
m_multiThreadedHelper->m_destinationWidth,
m_multiThreadedHelper->m_destinationHeight,
m_multiThreadedHelper->m_numPixelsCopied);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperAutogenerateGraphicsObjects:
{
B3_PROFILE("eGUIHelperAutogenerateGraphicsObjects");
m_multiThreadedHelper->m_childGuiHelper->autogenerateGraphicsObjects(m_multiThreadedHelper->m_dynamicsWorld);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIUserDebugAddText:
{
B3_PROFILE("eGUIUserDebugAddText");
bool replaced = false;
for (int i = 0; i < m_multiThreadedHelper->m_userDebugText.size(); i++)
{
if (m_multiThreadedHelper->m_userDebugText[i].m_itemUniqueId == m_multiThreadedHelper->m_tmpText.m_itemUniqueId)
{
m_multiThreadedHelper->m_userDebugText[i] = m_multiThreadedHelper->m_tmpText;
m_multiThreadedHelper->m_resultUserDebugTextUid = m_multiThreadedHelper->m_tmpText.m_itemUniqueId;
replaced = true;
}
}
if (!replaced)
{
m_multiThreadedHelper->m_userDebugText.push_back(m_multiThreadedHelper->m_tmpText);
m_multiThreadedHelper->m_resultUserDebugTextUid = m_multiThreadedHelper->m_userDebugText[m_multiThreadedHelper->m_userDebugText.size() - 1].m_itemUniqueId;
}
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIUserDebugAddParameter:
{
B3_PROFILE("eGUIUserDebugAddParameter");
UserDebugParameter* param = new UserDebugParameter(m_multiThreadedHelper->m_tmpParam);
m_multiThreadedHelper->m_userDebugParams.push_back(param);
if (param->m_rangeMin<= param->m_rangeMax)
{
SliderParams slider(param->m_text, &param->m_value);
slider.m_minVal = param->m_rangeMin;
slider.m_maxVal = param->m_rangeMax;
if (m_multiThreadedHelper->m_childGuiHelper->getParameterInterface())
m_multiThreadedHelper->m_childGuiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
}
else
{
int buttonId = -1;
bool isTrigger = false;
ButtonParams button(param->m_text, buttonId, isTrigger);
button.m_callback = UserButtonToggle;
button.m_userPointer = param;
button.m_initialState = false;
//create a button
if (m_multiThreadedHelper->m_childGuiHelper->getParameterInterface())
m_multiThreadedHelper->m_childGuiHelper->getParameterInterface()->registerButtonParameter(button);
}
m_multiThreadedHelper->m_userDebugParamUid = (*m_multiThreadedHelper->m_userDebugParams[m_multiThreadedHelper->m_userDebugParams.size() - 1]).m_itemUniqueId;
//also add actual menu
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIUserDebugAddLine:
{
B3_PROFILE("eGUIUserDebugAddLine");
if (m_multiThreadedHelper->m_tmpLine.m_replaceItemUid >= 0)
{
for (int i = 0; i < m_multiThreadedHelper->m_userDebugLines.size(); i++)
{
if (m_multiThreadedHelper->m_userDebugLines[i].m_itemUniqueId == m_multiThreadedHelper->m_tmpLine.m_replaceItemUid)
{
m_multiThreadedHelper->m_userDebugLines[i] = m_multiThreadedHelper->m_tmpLine;
m_multiThreadedHelper->m_resultDebugLineUid = m_multiThreadedHelper->m_tmpLine.m_replaceItemUid;
}
}
}
else
{
m_multiThreadedHelper->m_userDebugLines.push_back(m_multiThreadedHelper->m_tmpLine);
m_multiThreadedHelper->m_resultDebugLineUid = m_multiThreadedHelper->m_userDebugLines[m_multiThreadedHelper->m_userDebugLines.size() - 1].m_itemUniqueId;
}
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIUserDebugRemoveItem:
{
B3_PROFILE("eGUIUserDebugRemoveItem");
for (int i = 0; i < m_multiThreadedHelper->m_userDebugLines.size(); i++)
{
if (m_multiThreadedHelper->m_userDebugLines[i].m_itemUniqueId == m_multiThreadedHelper->m_removeDebugItemUid)
{
m_multiThreadedHelper->m_userDebugLines.swap(i, m_multiThreadedHelper->m_userDebugLines.size() - 1);
m_multiThreadedHelper->m_userDebugLines.pop_back();
break;
}
}
for (int i = 0; i < m_multiThreadedHelper->m_userDebugText.size(); i++)
{
if (m_multiThreadedHelper->m_userDebugText[i].m_itemUniqueId == m_multiThreadedHelper->m_removeDebugItemUid)
{
m_multiThreadedHelper->m_userDebugText.swap(i, m_multiThreadedHelper->m_userDebugText.size() - 1);
m_multiThreadedHelper->m_userDebugText.pop_back();
break;
}
}
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIUserDebugRemoveAllParameters:
{
B3_PROFILE("eGUIUserDebugRemoveAllParameters");
if (m_multiThreadedHelper->m_childGuiHelper->getParameterInterface())
m_multiThreadedHelper->m_childGuiHelper->getParameterInterface()->removeAllParameters();
for (int i = 0; i < m_multiThreadedHelper->m_userDebugParams.size(); i++)
{
delete m_multiThreadedHelper->m_userDebugParams[i];
}
m_multiThreadedHelper->m_userDebugParams.clear();
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIUserDebugRemoveAllItems:
{
B3_PROFILE("eGUIUserDebugRemoveAllItems");
m_multiThreadedHelper->m_userDebugLines.clear();
m_multiThreadedHelper->m_userDebugText.clear();
m_multiThreadedHelper->m_uidGenerator = 0;
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIDumpFramesToVideo:
{
B3_PROFILE("eGUIDumpFramesToVideo");
m_multiThreadedHelper->m_childGuiHelper->dumpFramesToVideo(m_multiThreadedHelper->m_mp4FileName);
m_multiThreadedHelper->mainThreadRelease();
break;
}
case eGUIHelperIdle:
{
break;
}
default:
{
btAssert(0);
}
}
}
void PhysicsServerExample::stepSimulation(float deltaTime)
{
BT_PROFILE("PhysicsServerExample::stepSimulation");
//this->m_physicsServer.processClientCommands();
for (int i = m_multiThreadedHelper->m_userDebugLines.size() - 1; i >= 0; i--)
{
if (m_multiThreadedHelper->m_userDebugLines[i].m_lifeTime)
{
m_multiThreadedHelper->m_userDebugLines[i].m_lifeTime -= deltaTime;
if (m_multiThreadedHelper->m_userDebugLines[i].m_lifeTime <= 0)
{
m_multiThreadedHelper->m_userDebugLines.swap(i, m_multiThreadedHelper->m_userDebugLines.size() - 1);
m_multiThreadedHelper->m_userDebugLines.pop_back();
}
}
}
for (int i = m_multiThreadedHelper->m_userDebugText.size() - 1; i >= 0; i--)
{
if (m_multiThreadedHelper->m_userDebugText[i].m_lifeTime)
{
m_multiThreadedHelper->m_userDebugText[i].m_lifeTime -= deltaTime;
if (m_multiThreadedHelper->m_userDebugText[i].m_lifeTime <= 0)
{
m_multiThreadedHelper->m_userDebugText.swap(i, m_multiThreadedHelper->m_userDebugText.size() - 1);
m_multiThreadedHelper->m_userDebugText.pop_back();
}
}
}
updateGraphics();
{
if (m_multiThreadedHelper->m_childGuiHelper->getRenderInterface())
{
m_multiThreadedHelper->m_childGuiHelper->getRenderInterface()->writeTransforms();
}
}
}
static float vrOffset[16] = {1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 0};
extern int gDroppedSimulationSteps;
extern int gNumSteps;
extern double gDtInSec;
extern double gSubStep;
extern btTransform gVRTrackingObjectTr;
void PhysicsServerExample::drawUserDebugLines()
{
//static char line0[1024];
//static char line1[1024];
//draw all user-debug-lines
//add array of lines
//draw all user- 'text3d' messages
if (m_multiThreadedHelper)
{
//if gBatchUserDebugLines is true, batch lines based on color+width, to reduce line draw calls
btAlignedObjectArray<btAlignedObjectArray<unsigned int> > sortedIndices;
btAlignedObjectArray<btAlignedObjectArray<btVector3FloatData> > sortedLines;
btHashMap<ColorWidth, int> hashedLines;
for (int i = 0; i < m_multiThreadedHelper->m_userDebugLines.size(); i++)
{
btVector3 from;
from.setValue(m_multiThreadedHelper->m_userDebugLines[i].m_debugLineFromXYZ[0],
m_multiThreadedHelper->m_userDebugLines[i].m_debugLineFromXYZ[1],
m_multiThreadedHelper->m_userDebugLines[i].m_debugLineFromXYZ[2]);
btVector3 toX;
toX.setValue(m_multiThreadedHelper->m_userDebugLines[i].m_debugLineToXYZ[0],
m_multiThreadedHelper->m_userDebugLines[i].m_debugLineToXYZ[1],
m_multiThreadedHelper->m_userDebugLines[i].m_debugLineToXYZ[2]);
int graphicsIndex = m_multiThreadedHelper->m_userDebugLines[i].m_trackingVisualShapeIndex;
if (graphicsIndex >= 0)
{
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
if (renderer)
{
float parentPos[3];
float parentOrn[4];
if (renderer->readSingleInstanceTransformToCPU(parentPos, parentOrn, graphicsIndex))
{
btTransform parentTrans;
parentTrans.setOrigin(btVector3(parentPos[0], parentPos[1], parentPos[2]));
parentTrans.setRotation(btQuaternion(parentOrn[0], parentOrn[1], parentOrn[2], parentOrn[3]));
from = parentTrans * from;
toX = parentTrans * toX;
}
}
}
btVector3 color;
color.setValue(m_multiThreadedHelper->m_userDebugLines[i].m_debugLineColorRGB[0],
m_multiThreadedHelper->m_userDebugLines[i].m_debugLineColorRGB[1],
m_multiThreadedHelper->m_userDebugLines[i].m_debugLineColorRGB[2]);
ColorWidth cw;
color.serializeFloat(cw.m_color);
cw.width = m_multiThreadedHelper->m_userDebugLines[i].m_lineWidth;
int index = -1;
if (gBatchUserDebugLines)
{
int* indexPtr = hashedLines.find(cw);
if (indexPtr)
{
index = *indexPtr;
}
else
{
index = sortedLines.size();
sortedLines.expand();
sortedIndices.expand();
hashedLines.insert(cw, index);
}
btAssert(index >= 0);
if (index >= 0)
{
btVector3FloatData from1, toX1;
sortedIndices[index].push_back(sortedLines[index].size());
from.serializeFloat(from1);
sortedLines[index].push_back(from1);
sortedIndices[index].push_back(sortedLines[index].size());
toX.serializeFloat(toX1);
sortedLines[index].push_back(toX1);
}
}
else
{
m_guiHelper->getAppInterface()->m_renderer->drawLine(from, toX, color, m_multiThreadedHelper->m_userDebugLines[i].m_lineWidth);
}
}
if (gBatchUserDebugLines)
{
for (int i = 0; i < hashedLines.size(); i++)
{
ColorWidth cw = hashedLines.getKeyAtIndex(i);
int index = *hashedLines.getAtIndex(i);
int stride = sizeof(btVector3FloatData);
const float* positions = &sortedLines[index][0].m_floats[0];
int numPoints = sortedLines[index].size();
const unsigned int* indices = &sortedIndices[index][0];
int numIndices = sortedIndices[index].size();
m_guiHelper->getAppInterface()->m_renderer->drawLines(positions, cw.m_color.m_floats, numPoints, stride, indices, numIndices, cw.width);
}
}
for (int i = 0; i < m_multiThreadedHelper->m_userDebugText.size(); i++)
{
//int optionFlag = 0;//CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera|CommonGraphicsApp::eDrawText3D_TrueType;
//int optionFlag = CommonGraphicsApp::eDrawText3D_TrueType;
float orientation[4] = {0, 0, 0, 1};
//int optionFlag = CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera;
int optionFlag = 0;
if (m_multiThreadedHelper->m_userDebugText[i].m_optionFlags & CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera)
{
optionFlag |= CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera;
}
else
{
orientation[0] = (float)m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[0];
orientation[1] = (float)m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[1];
orientation[2] = (float)m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[2];
orientation[3] = (float)m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[3];
optionFlag |= CommonGraphicsApp::eDrawText3D_TrueType;
}
float colorRGBA[4] = {
(float)m_multiThreadedHelper->m_userDebugText[i].m_textColorRGB[0],
(float)m_multiThreadedHelper->m_userDebugText[i].m_textColorRGB[1],
(float)m_multiThreadedHelper->m_userDebugText[i].m_textColorRGB[2],
(float)1.};
float pos[3] = {(float)m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ1[0],
(float)m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ1[1],
(float)m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ1[2]};
int graphicsIndex = m_multiThreadedHelper->m_userDebugText[i].m_trackingVisualShapeIndex;
if (graphicsIndex >= 0)
{
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
if (renderer)
{
float parentPos[3];
float parentOrn[4];
if (renderer->readSingleInstanceTransformToCPU(parentPos, parentOrn, graphicsIndex))
{
btTransform parentTrans;
parentTrans.setOrigin(btVector3(parentPos[0], parentPos[1], parentPos[2]));
parentTrans.setRotation(btQuaternion(parentOrn[0], parentOrn[1], parentOrn[2], parentOrn[3]));
btTransform childTr;
childTr.setOrigin(btVector3(pos[0], pos[1], pos[2]));
childTr.setRotation(btQuaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
btTransform siteTr = parentTrans * childTr;
pos[0] = siteTr.getOrigin()[0];
pos[1] = siteTr.getOrigin()[1];
pos[2] = siteTr.getOrigin()[2];
btQuaternion siteOrn = siteTr.getRotation();
orientation[0] = siteOrn[0];
orientation[1] = siteOrn[1];
orientation[2] = siteOrn[2];
orientation[3] = siteOrn[3];
}
}
}
{
btAlignedObjectArray<std::string> pieces;
btAlignedObjectArray<std::string> separators;
separators.push_back("\n");
urdfStringSplit(pieces, m_multiThreadedHelper->m_userDebugText[i].m_text, separators);
double sz = m_multiThreadedHelper->m_userDebugText[i].textSize;
btTransform tr;
tr.setIdentity();
tr.setOrigin(btVector3(pos[0], pos[1], pos[2]));
tr.setRotation(btQuaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
//float newpos[3]={pos[0]-float(t)*sz,pos[1],pos[2]};
for (int t = 0; t < pieces.size(); t++)
{
btTransform offset;
offset.setIdentity();
offset.setOrigin(btVector3(0, -float(t) * sz, 0));
btTransform result = tr * offset;
float newpos[3] = {(float)result.getOrigin()[0],
(float)result.getOrigin()[1],
(float)result.getOrigin()[2]};
m_guiHelper->getAppInterface()->drawText3D(pieces[t].c_str(),
newpos, orientation, colorRGBA,
sz, optionFlag);
}
}
/*m_guiHelper->getAppInterface()->drawText3D(m_multiThreadedHelper->m_userDebugText[i].m_text,
m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ[0],
m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ[1],
m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ[2],
m_multiThreadedHelper->m_userDebugText[i].textSize);
*/
}
}
}
void PhysicsServerExample::renderScene()
{
m_renderedFrames++;
btTransform vrTrans;
B3_PROFILE("PhysicsServerExample::RenderScene");
if (m_physicsServer.isRealTimeSimulationEnabled())
{
static int frameCount = 0;
static btScalar prevTime = m_clock.getTimeSeconds();
frameCount++;
static char line0[1024] = {0};
static char line1[1024] = {0};
#if 0
static btScalar worseFps = 1000000;
int numFrames = 200;
static int count = 0;
count++;
if (0 == (count & 1))
{
btScalar curTime = m_clock.getTimeSeconds();
btScalar fps = 1. / (curTime - prevTime);
prevTime = curTime;
if (fps < worseFps)
{
worseFps = fps;
}
if (count > numFrames)
{
count = 0;
sprintf(line0, "fps:%f frame:%d", worseFps, frameCount / 2);
sprintf(line1, "drop:%d tscale:%f dt:%f, substep %f)", gDroppedSimulationSteps, simTimeScalingFactor,gDtInSec, gSubStep);
gDroppedSimulationSteps = 0;
worseFps = 1000000;
}
}
#endif
#ifdef BT_ENABLE_VR
if ((gInternalSimFlags & 2) && m_tinyVrGui == 0)
{
ComboBoxParams comboParams;
comboParams.m_comboboxId = 0;
comboParams.m_numItems = 0;
comboParams.m_startItem = 0;
comboParams.m_callback = 0; //MyComboBoxCallback;
comboParams.m_userPointer = 0; //this;
m_tinyVrGui = new TinyVRGui(comboParams, this->m_multiThreadedHelper->m_childGuiHelper->getRenderInterface());
m_tinyVrGui->init();
}
if (m_tinyVrGui)
{
b3Transform tr;
tr.setIdentity();
btVector3 VRController2Pos = m_physicsServer.getVRTeleportPosition();
btQuaternion VRController2Orn = m_physicsServer.getVRTeleportOrientation();
tr.setOrigin(b3MakeVector3(VRController2Pos[0], VRController2Pos[1], VRController2Pos[2]));
tr.setRotation(b3Quaternion(VRController2Orn[0], VRController2Orn[1], VRController2Orn[2], VRController2Orn[3]));
tr = tr * b3Transform(b3Quaternion(0, 0, -SIMD_HALF_PI), b3MakeVector3(0, 0, 0));
b3Scalar dt = 0.01;
m_tinyVrGui->clearTextArea();
m_tinyVrGui->grapicalPrintf(line0, 0, 0, 0, 0, 0, 255);
m_tinyVrGui->grapicalPrintf(line1, 0, 16, 255, 255, 255, 255);
m_tinyVrGui->tick(dt, tr);
}
#endif //BT_ENABLE_VR
}
///debug rendering
//m_args[0].m_cs->lock();
//gVRTeleportPos[0] += 0.01;
btTransform tr2a, tr2;
tr2a.setIdentity();
tr2.setIdentity();
tr2.setOrigin(m_physicsServer.getVRTeleportPosition());
tr2a.setRotation(m_physicsServer.getVRTeleportOrientation());
btTransform trTotal = tr2 * tr2a;
btTransform trInv = trTotal.inverse();
btMatrix3x3 vrOffsetRot;
vrOffsetRot.setRotation(trInv.getRotation());
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
vrOffset[i + 4 * j] = vrOffsetRot[i][j];
}
}
vrOffset[12] = trInv.getOrigin()[0];
vrOffset[13] = trInv.getOrigin()[1];
vrOffset[14] = trInv.getOrigin()[2];
if (m_multiThreadedHelper->m_childGuiHelper->getRenderInterface())
{
m_multiThreadedHelper->m_childGuiHelper->getRenderInterface()->getActiveCamera()->setVRCameraOffsetTransform(vrOffset);
}
if (gEnableRendering)
{
int renderFlags = 0;
if (!gEnableSyncPhysicsRendering)
{
renderFlags |= 1; //COV_DISABLE_SYNC_RENDERING;
}
m_physicsServer.renderScene(renderFlags);
}
if (gEnablePicking)
{
for (int i = 0; i < MAX_VR_CONTROLLERS; i++)
{
if (m_args[0].m_isVrControllerPicking[i] || m_args[0].m_isVrControllerDragging[i])
{
btVector3 from = m_args[0].m_vrControllerPos[i];
btMatrix3x3 mat(m_args[0].m_vrControllerOrn[i]);
btVector3 toX = from + mat.getColumn(0);
btVector3 toY = from + mat.getColumn(1);
btVector3 toZ = from + mat.getColumn(2);
int width = 2;
btVector4 color;
color = btVector4(1, 0, 0, 1);
m_guiHelper->getAppInterface()->m_renderer->drawLine(from, toX, color, width);
color = btVector4(0, 1, 0, 1);
m_guiHelper->getAppInterface()->m_renderer->drawLine(from, toY, color, width);
color = btVector4(0, 0, 1, 1);
m_guiHelper->getAppInterface()->m_renderer->drawLine(from, toZ, color, width);
}
}
}
if (m_guiHelper->getAppInterface()->m_renderer->getActiveCamera()->isVRCamera())
{
if (!m_physicsServer.isRealTimeSimulationEnabled() && !gActivedVRRealTimeSimulation)
{
//only activate real-time simulation once (for backward compatibility)
gActivedVRRealTimeSimulation = true;
m_physicsServer.enableRealTimeSimulation(1);
}
}
drawUserDebugLines();
//m_args[0].m_cs->unlock();
}
void PhysicsServerExample::physicsDebugDraw(int debugDrawFlags)
{
m_renderedFrames++;
if (gEnableSyncPhysicsRendering)
{
m_physicsServer.syncPhysicsToGraphics();
}
drawUserDebugLines();
if (gEnableRendering)
{
///debug rendering
//m_physicsServer.physicsDebugDraw(debugDrawFlags);
m_args[0].m_csGUI->lock();
//draw stuff and flush?
this->m_multiThreadedHelper->m_debugDraw->drawDebugDrawerLines();
m_args[0].m_debugDrawFlags = debugDrawFlags;
m_args[0].m_enableUpdateDebugDrawLines = true;
m_args[0].m_csGUI->unlock();
}
}
btVector3 PhysicsServerExample::getRayTo(int x, int y)
{
CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
if (!renderer)
{
btAssert(0);
return btVector3(0, 0, 0);
}
float top = 1.f;
float bottom = -1.f;
float nearPlane = 1.f;
float tanFov = (top - bottom) * 0.5f / nearPlane;
float fov = btScalar(2.0) * btAtan(tanFov);
btVector3 camPos, camTarget;
renderer->getActiveCamera()->getCameraPosition(camPos);
renderer->getActiveCamera()->getCameraTargetPosition(camTarget);
btVector3 rayFrom = camPos;
btVector3 rayForward = (camTarget - camPos);
rayForward.normalize();
float farPlane = 10000.f;
rayForward *= farPlane;
btVector3 rightOffset;
btVector3 cameraUp = btVector3(0, 0, 0);
cameraUp[m_guiHelper->getAppInterface()->getUpAxis()] = 1;
btVector3 vertical = cameraUp;
btVector3 hor;
hor = rayForward.cross(vertical);
hor.safeNormalize();
vertical = hor.cross(rayForward);
vertical.safeNormalize();
float tanfov = tanf(0.5f * fov);
hor *= 2.f * farPlane * tanfov;
vertical *= 2.f * farPlane * tanfov;
btScalar aspect;
float width = float(renderer->getScreenWidth());
float height = float(renderer->getScreenHeight());
aspect = width / height;
hor *= aspect;
btVector3 rayToCenter = rayFrom + rayForward;
btVector3 dHor = hor * 1.f / width;
btVector3 dVert = vertical * 1.f / height;
btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
rayTo += btScalar(x) * dHor;
rayTo -= btScalar(y) * dVert;
return rayTo;
}
void PhysicsServerExample::vrControllerButtonCallback(int controllerId, int button, int state, float pos[4], float orn[4])
{
//printf("controllerId %d, button=%d\n",controllerId, button);
if (controllerId < 0 || controllerId >= MAX_VR_CONTROLLERS)
return;
if (gGraspingController < 0)
{
gGraspingController = controllerId;
}
btTransform trLocal;
trLocal.setIdentity();
trLocal.setRotation(btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI) * btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI));
btTransform trOrg;
trOrg.setIdentity();
trOrg.setOrigin(btVector3(pos[0], pos[1], pos[2]));
trOrg.setRotation(btQuaternion(orn[0], orn[1], orn[2], orn[3]));
btTransform tr2a;
tr2a.setIdentity();
btTransform tr2;
tr2.setIdentity();
tr2.setOrigin(m_physicsServer.getVRTeleportPosition());
tr2a.setRotation(m_physicsServer.getVRTeleportOrientation());
btTransform trTotal = tr2 * tr2a * trOrg * trLocal;
if (controllerId != gGraspingController)
{
if (button == 1 && state == 0)
{
}
}
else
{
if (button == 1)
{
if (state == 1)
{
gDebugRenderToggle = 1;
}
else
{
gDebugRenderToggle = 0;
#if 0 //it confuses people, make it into a debug option in a VR GUI?
if (simTimeScalingFactor==0)
{
simTimeScalingFactor = 1;
} else
{
if (simTimeScalingFactor==1)
{
simTimeScalingFactor = 0.25;
}
else
{
simTimeScalingFactor = 0;
}
}
#endif
}
}
else
{
}
}
if (button == 32 && state == 0)
{
if (controllerId == gGraspingController)
{
}
else
{
// gEnableKukaControl = !gEnableKukaControl;
}
}
if (button == 1 && gEnableTeleporting)
{
m_args[0].m_isVrControllerTeleporting[controllerId] = true;
}
if (controllerId == gGraspingController && (button == 33))
{
}
else
{
if (button == 33 && gEnablePicking)
{
m_args[0].m_isVrControllerPicking[controllerId] = (state != 0);
m_args[0].m_isVrControllerReleasing[controllerId] = (state == 0);
}
if ((button == 33) || (button == 1))
{
// m_args[0].m_vrControllerPos[controllerId].setValue(pos[0] + gVRTeleportPos[0], pos[1] + gVRTeleportPos[1], pos[2] + gVRTeleportPos[2]);
// m_args[0].m_vrControllerOrn[controllerId].setValue(orn[0], orn[1], orn[2], orn[3]);
m_args[0].m_vrControllerPos[controllerId] = trTotal.getOrigin();
m_args[0].m_vrControllerOrn[controllerId] = trTotal.getRotation();
}
}
m_args[0].m_csGUI->lock();
m_args[0].m_vrControllerEvents[controllerId].m_controllerId = controllerId;
m_args[0].m_vrControllerEvents[controllerId].m_deviceType = VR_DEVICE_CONTROLLER;
m_args[0].m_vrControllerEvents[controllerId].m_pos[0] = trTotal.getOrigin()[0];
m_args[0].m_vrControllerEvents[controllerId].m_pos[1] = trTotal.getOrigin()[1];
m_args[0].m_vrControllerEvents[controllerId].m_pos[2] = trTotal.getOrigin()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[0] = trTotal.getRotation()[0];
m_args[0].m_vrControllerEvents[controllerId].m_orn[1] = trTotal.getRotation()[1];
m_args[0].m_vrControllerEvents[controllerId].m_orn[2] = trTotal.getRotation()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[3] = trTotal.getRotation()[3];
m_args[0].m_vrControllerEvents[controllerId].m_numButtonEvents++;
if (state)
{
m_args[0].m_vrControllerEvents[controllerId].m_buttons[button] |= eButtonIsDown + eButtonTriggered;
}
else
{
m_args[0].m_vrControllerEvents[controllerId].m_buttons[button] |= eButtonReleased;
m_args[0].m_vrControllerEvents[controllerId].m_buttons[button] &= ~eButtonIsDown;
}
m_args[0].m_csGUI->unlock();
}
void PhysicsServerExample::vrControllerMoveCallback(int controllerId, float pos[4], float orn[4], float analogAxis, float auxAnalogAxes[10])
{
if (controllerId < 0 || controllerId >= MAX_VR_CONTROLLERS)
{
printf("Controller Id exceeds max: %d > %d", controllerId, MAX_VR_CONTROLLERS);
return;
}
btTransform trLocal;
trLocal.setIdentity();
trLocal.setRotation(btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI) * btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI));
btTransform trOrg;
trOrg.setIdentity();
trOrg.setOrigin(btVector3(pos[0], pos[1], pos[2]));
trOrg.setRotation(btQuaternion(orn[0], orn[1], orn[2], orn[3]));
btTransform tr2a;
tr2a.setIdentity();
btTransform tr2;
tr2.setIdentity();
tr2.setOrigin(m_physicsServer.getVRTeleportPosition());
tr2a.setRotation(m_physicsServer.getVRTeleportOrientation());
btTransform trTotal = tr2 * tr2a * trOrg * trLocal;
if (controllerId == gGraspingController)
{
}
else
{
m_args[0].m_vrControllerPos[controllerId] = trTotal.getOrigin();
m_args[0].m_vrControllerOrn[controllerId] = trTotal.getRotation();
}
m_args[0].m_csGUI->lock();
m_args[0].m_vrControllerEvents[controllerId].m_controllerId = controllerId;
m_args[0].m_vrControllerEvents[controllerId].m_deviceType = VR_DEVICE_CONTROLLER;
m_args[0].m_vrControllerEvents[controllerId].m_pos[0] = trTotal.getOrigin()[0];
m_args[0].m_vrControllerEvents[controllerId].m_pos[1] = trTotal.getOrigin()[1];
m_args[0].m_vrControllerEvents[controllerId].m_pos[2] = trTotal.getOrigin()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[0] = trTotal.getRotation()[0];
m_args[0].m_vrControllerEvents[controllerId].m_orn[1] = trTotal.getRotation()[1];
m_args[0].m_vrControllerEvents[controllerId].m_orn[2] = trTotal.getRotation()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[3] = trTotal.getRotation()[3];
m_args[0].m_vrControllerEvents[controllerId].m_numMoveEvents++;
m_args[0].m_vrControllerEvents[controllerId].m_analogAxis = analogAxis;
for (int i = 0; i < 10; i++)
{
m_args[0].m_vrControllerEvents[controllerId].m_auxAnalogAxis[i] = auxAnalogAxes[i];
}
m_args[0].m_csGUI->unlock();
}
void PhysicsServerExample::vrHMDMoveCallback(int controllerId, float pos[4], float orn[4])
{
if (controllerId < 0 || controllerId >= MAX_VR_CONTROLLERS)
{
printf("Controller Id exceeds max: %d > %d", controllerId, MAX_VR_CONTROLLERS);
return;
}
//we may need to add some trLocal transform, to align the camera to our preferences
btTransform trLocal;
trLocal.setIdentity();
// trLocal.setRotation(btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI)*btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI));
btTransform trOrg;
trOrg.setIdentity();
trOrg.setOrigin(btVector3(pos[0], pos[1], pos[2]));
trOrg.setRotation(btQuaternion(orn[0], orn[1], orn[2], orn[3]));
btTransform tr2a;
tr2a.setIdentity();
btTransform tr2;
tr2.setIdentity();
tr2.setOrigin(m_physicsServer.getVRTeleportPosition());
tr2a.setRotation(m_physicsServer.getVRTeleportOrientation());
btTransform trTotal = tr2 * tr2a * trOrg * trLocal;
m_args[0].m_csGUI->lock();
m_args[0].m_vrControllerEvents[controllerId].m_controllerId = controllerId;
m_args[0].m_vrControllerEvents[controllerId].m_deviceType = VR_DEVICE_HMD;
m_args[0].m_vrControllerEvents[controllerId].m_pos[0] = trTotal.getOrigin()[0];
m_args[0].m_vrControllerEvents[controllerId].m_pos[1] = trTotal.getOrigin()[1];
m_args[0].m_vrControllerEvents[controllerId].m_pos[2] = trTotal.getOrigin()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[0] = trTotal.getRotation()[0];
m_args[0].m_vrControllerEvents[controllerId].m_orn[1] = trTotal.getRotation()[1];
m_args[0].m_vrControllerEvents[controllerId].m_orn[2] = trTotal.getRotation()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[3] = trTotal.getRotation()[3];
m_args[0].m_vrControllerEvents[controllerId].m_numMoveEvents++;
m_args[0].m_csGUI->unlock();
}
void PhysicsServerExample::vrGenericTrackerMoveCallback(int controllerId, float pos[4], float orn[4])
{
if (controllerId < 0 || controllerId >= MAX_VR_CONTROLLERS)
{
printf("Controller Id exceeds max: %d > %d", controllerId, MAX_VR_CONTROLLERS);
return;
}
//we may need to add some trLocal transform, to align the camera to our preferences
btTransform trLocal;
trLocal.setIdentity();
trLocal.setRotation(btQuaternion(btVector3(0, 0, 1), SIMD_HALF_PI) * btQuaternion(btVector3(0, 1, 0), SIMD_HALF_PI));
btTransform trOrg;
trOrg.setIdentity();
trOrg.setOrigin(btVector3(pos[0], pos[1], pos[2]));
trOrg.setRotation(btQuaternion(orn[0], orn[1], orn[2], orn[3]));
btTransform tr2a;
tr2a.setIdentity();
btTransform tr2;
tr2.setIdentity();
tr2.setOrigin(m_physicsServer.getVRTeleportPosition());
tr2a.setRotation(m_physicsServer.getVRTeleportOrientation());
btTransform trTotal = tr2 * tr2a * trOrg * trLocal;
m_args[0].m_csGUI->lock();
m_args[0].m_vrControllerEvents[controllerId].m_controllerId = controllerId;
m_args[0].m_vrControllerEvents[controllerId].m_deviceType = VR_DEVICE_GENERIC_TRACKER;
m_args[0].m_vrControllerEvents[controllerId].m_pos[0] = trTotal.getOrigin()[0];
m_args[0].m_vrControllerEvents[controllerId].m_pos[1] = trTotal.getOrigin()[1];
m_args[0].m_vrControllerEvents[controllerId].m_pos[2] = trTotal.getOrigin()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[0] = trTotal.getRotation()[0];
m_args[0].m_vrControllerEvents[controllerId].m_orn[1] = trTotal.getRotation()[1];
m_args[0].m_vrControllerEvents[controllerId].m_orn[2] = trTotal.getRotation()[2];
m_args[0].m_vrControllerEvents[controllerId].m_orn[3] = trTotal.getRotation()[3];
m_args[0].m_vrControllerEvents[controllerId].m_numMoveEvents++;
m_args[0].m_csGUI->unlock();
}
extern int gSharedMemoryKey;
class CommonExampleInterface* PhysicsServerCreateFuncInternal(struct CommonExampleOptions& options)
{
MultiThreadedOpenGLGuiHelper* guiHelperWrapper = new MultiThreadedOpenGLGuiHelper(options.m_guiHelper->getAppInterface(), options.m_guiHelper, options.m_skipGraphicsUpdate);
PhysicsServerExample* example = new PhysicsServerExample(guiHelperWrapper,
options.m_commandProcessorCreation,
options.m_sharedMem,
options.m_option);
if (gSharedMemoryKey >= 0)
{
example->setSharedMemoryKey(gSharedMemoryKey);
}
if (options.m_option & PHYSICS_SERVER_ENABLE_COMMAND_LOGGING)
{
example->enableCommandLogging();
}
if (options.m_option & PHYSICS_SERVER_REPLAY_FROM_COMMAND_LOG)
{
example->replayFromLogFile();
}
return example;
}