//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" #ifdef BT_ENABLE_VR #include "../RenderingExamples/TinyVRGui.h" #endif//BT_ENABLE_VR #include "../CommonInterfaces/CommonParameterInterface.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 gEnableSyncPhysicsRendering= true; bool gEnableUpdateDebugDrawLines = true; static int gCamVisualizerWidth = 320; static int gCamVisualizerHeight = 240; //extern btVector3 gLastPickPos; btVector3 gVRTeleportPosLocal(0,0,0); btQuaternion gVRTeleportOrnLocal(0,0,0,1); 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 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(); #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, }; #include //#include "BulletMultiThreaded/PlatformDefinitions.h" #ifndef _WIN32 #include "../MultiThreading/b3PosixThreadSupport.h" b3ThreadSupportInterface* createMotionThreadSupport(int numThreads) { b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("MotionThreads", MotionThreadFunc, MotionlsMemoryFunc, 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,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_physicsServerPtr(0) { for (int i=0;i m_mouseCommands; b3VRControllerEvent m_vrControllerEvents[MAX_VR_CONTROLLERS]; b3VRControllerEvent m_sendVrControllerEvents[MAX_VR_CONTROLLERS]; btAlignedObjectArray m_keyboardEvents; btAlignedObjectArray m_sendKeyEvents; PhysicsServerSharedMemory* m_physicsServerPtr; b3AlignedObjectArray 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) { 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;cm_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;im_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;bm_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;im_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_physicsServerPtr->stepSimulationRealTime(deltaTimeInSeconds, args->m_sendVrControllerEvents,numSendVrControllers, keyEvents, args->m_sendKeyEvents.size()); } { if (gEnableUpdateDebugDrawLines) { args->m_csGUI->lock(); args->m_physicsServerPtr->physicsDebugDraw(args->m_debugDrawFlags); gEnableUpdateDebugDrawLines=false; args->m_csGUI->unlock(); } } deltaTimeInSeconds = 0; } args->m_csGUI->lock(); 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_mouseCommands.clear(); args->m_csGUI->unlock(); { args->m_physicsServerPtr->processClientCommands(); numCmdSinceSleep1ms++; } } while (args->m_cs->getSharedParam(0)!=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; } 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; }; struct UserDebugParameter { char m_text[1024]; double m_rangeMin; double m_rangeMax; btScalar m_value; int m_itemUniqueId; }; 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 > m_sortedIndices; btAlignedObjectArray< btAlignedObjectArray > m_sortedLines; btHashMap m_hashedLines; public: void drawDebugDrawerLines() { if (m_hashedLines.size()) { for (int i=0;igetRenderInterface()->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() { 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; void drawDebugDrawerLines() { if (m_debugDraw) { m_debugDraw->drawDebugDrawerLines(); } } GUIHelperInterface* m_childGuiHelper; 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; 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"); 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) : //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_textureId(-1) { m_childGuiHelper = guiHelper; } virtual ~MultiThreadedOpenGLGuiHelper() { //delete m_childGuiHelper; if (m_debugDraw) { delete m_debugDraw; m_debugDraw = 0; } } 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 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); } virtual int registerTexture(const unsigned char* texels, int width, int height) { m_texels = texels; m_textureWidth = width; m_textureHeight = height; m_cs->lock(); m_cs->setSharedParam(1,eGUIHelperRegisterTexture); workerThreadWait(); 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; 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_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(); } 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(); } 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 m_userDebugText; UserDebugText m_tmpText; 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) { 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); workerThreadWait(); return m_userDebugText[m_userDebugText.size()-1].m_itemUniqueId; } btAlignedObjectArray m_userDebugParams; UserDebugParameter m_tmpParam; virtual int readUserDebugParameter(int itemUniqueId, double* value) { for (int i=0;im_itemUniqueId == itemUniqueId) { *value = m_userDebugParams[i]->m_value; return 1; } } return 0; } 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); workerThreadWait(); return (*m_userDebugParams[m_userDebugParams.size()-1]).m_itemUniqueId; } btAlignedObjectArray m_userDebugLines; UserDebugDrawLine m_tmpLine; virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime , int trackingVisualShapeIndex) { m_tmpLine.m_lifeTime = lifeTime; m_tmpLine.m_lineWidth = lineWidth; m_tmpLine.m_itemUniqueId = m_uidGenerator++; 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_cs->lock(); m_cs->setSharedParam(1, eGUIUserDebugAddLine); workerThreadWait(); return m_userDebugLines[m_userDebugLines.size()-1].m_itemUniqueId; } 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(); } 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 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 orientation[4]); virtual void vrControllerMoveCallback(int controllerId, float pos[4], float orientation[4], float analogAxis); 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; } 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; 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); { int keyIndex = -1; //is already there? for (int i=0;ilock(); 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); } m_args[0].m_csGUI->unlock(); } else { m_args[0].m_csGUI->lock(); 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;igetAppInterface()->m_window; if (window->isModifierKeyPressed(B3G_SHIFT)) shift=0.01; btVector3 VRTeleportPos =this->m_physicsServer.getVRTeleportPosition(); 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); } } }; 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_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); for (int i=0;igetNumTasks();i++) { MotionThreadLocalStorage* storage = (MotionThreadLocalStorage*) m_threadSupport->getThreadLocalMemory(i); b3Assert(storage); storage->threadId = i; //storage->m_sharedMem = data->m_sharedMem; } for (int w=0;wcreateCriticalSection(); 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_args[w].m_cs->setSharedParam(0,eMotionIsUnInitialized); 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); while (m_args[w].m_cs->getSharedParam(0)==eMotionIsUnInitialized) { b3Clock::usleep(1000); } } m_args[0].m_cs->setSharedParam(1,eGUIHelperIdle); m_multiThreadedHelper->setCriticalSection(m_args[0].m_cs); m_multiThreadedHelper->setCriticalSection2(m_args[0].m_cs2); m_multiThreadedHelper->setCriticalSection3(m_args[0].m_cs3); m_multiThreadedHelper->setCriticalSectionGUI(m_args[0].m_csGUI); m_args[0].m_cs2->lock(); m_isConnected = m_physicsServer.connectSharedMemory( m_guiHelper); { m_canvas = m_guiHelper->get2dCanvasInterface(); if (m_canvas) { m_canvasRGBIndex = m_canvas->createCanvas("Synthetic Camera RGB data",gCamVisualizerWidth, gCamVisualizerHeight); //m_canvasDepthIndex = m_canvas->createCanvas("Synthetic Camera Depth data",gCamVisualizerWidth, gCamVisualizerHeight); //m_canvasSegMaskIndex = m_canvas->createCanvas("Synthetic Camera Segmentation Mask",gCamVisualizerWidth, gCamVisualizerHeight); for (int i=0;isetPixel(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;ilock(); 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(1000); } //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: { m_multiThreadedHelper->m_childGuiHelper->createCollisionShapeGraphicsObject(m_multiThreadedHelper->m_colShape); m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIHelperCreateCollisionObjectGraphicsObject: { m_multiThreadedHelper->m_childGuiHelper->createCollisionObjectGraphicsObject(m_multiThreadedHelper->m_obj, m_multiThreadedHelper->m_color2); m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIHelperCreateRigidBodyGraphicsObject: { m_multiThreadedHelper->m_childGuiHelper->createRigidBodyGraphicsObject(m_multiThreadedHelper->m_body,m_multiThreadedHelper->m_color3); m_multiThreadedHelper->mainThreadRelease(); break; } case 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 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: { int flag = m_multiThreadedHelper->m_visualizerFlag; int enable = m_multiThreadedHelper->m_visualizerEnable; 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); } m_multiThreadedHelper->m_childGuiHelper->setVisualizerFlag(m_multiThreadedHelper->m_visualizerFlag,m_multiThreadedHelper->m_visualizerEnable); m_multiThreadedHelper->mainThreadRelease(); break; } case 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: { #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: { m_multiThreadedHelper->m_childGuiHelper->removeGraphicsInstance(m_multiThreadedHelper->m_graphicsInstanceRemove); m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIHelperChangeGraphicsInstanceRGBAColor: { m_multiThreadedHelper->m_childGuiHelper->changeRGBAColor(m_multiThreadedHelper->m_graphicsInstanceChangeColor,m_multiThreadedHelper->m_rgbaColor); m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIHelperChangeGraphicsInstanceSpecularColor: { m_multiThreadedHelper->m_childGuiHelper->changeSpecularColor(m_multiThreadedHelper->m_graphicsInstanceChangeSpecular,m_multiThreadedHelper->m_specularColor); m_multiThreadedHelper->mainThreadRelease(); break; } case 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 = 20;//m_multiThreadedHelper->m_projectionMatrix[14]/(m_multiThreadedHelper->m_projectionMatrix[10]+1); for (int i=0;im_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 minDepthValue = 0.98;//todo: compute more reasonably min/max depth range btScalar maxDepthValue = 1; if (maxDepthValue!=minDepthValue) { rgb = (depthValue-minDepthValue)*(255. / (btFabs(maxDepthValue-minDepthValue))); if (rgb<0 || rgb>255) { //printf("rgb=%d\n",rgb); } } 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) { btVector4 rgb = palette[segmentationMask&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: { 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: { m_multiThreadedHelper->m_childGuiHelper->autogenerateGraphicsObjects(m_multiThreadedHelper->m_dynamicsWorld); m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIUserDebugAddText: { m_multiThreadedHelper->m_userDebugText.push_back(m_multiThreadedHelper->m_tmpText); m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIUserDebugAddParameter: { UserDebugParameter* param = new UserDebugParameter(m_multiThreadedHelper->m_tmpParam); m_multiThreadedHelper->m_userDebugParams.push_back(param); { SliderParams slider(param->m_text,¶m->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); } //also add actual menu m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIUserDebugAddLine: { m_multiThreadedHelper->m_userDebugLines.push_back(m_multiThreadedHelper->m_tmpLine); m_multiThreadedHelper->mainThreadRelease(); break; } case eGUIUserDebugRemoveItem: { for (int i=0;im_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;im_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 eGUIUserDebugRemoveAllItems: { m_multiThreadedHelper->m_userDebugLines.clear(); m_multiThreadedHelper->m_userDebugText.clear(); m_multiThreadedHelper->m_uidGenerator = 0; m_multiThreadedHelper->mainThreadRelease(); break; } case 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 > sortedIndices; btAlignedObjectArray< btAlignedObjectArray > sortedLines; btHashMap hashedLines; for (int i = 0; im_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;igetAppInterface()->m_renderer->drawLines(positions,cw.m_color.m_floats,numPoints, stride, indices,numIndices,cw.width); } } for (int i = 0; im_userDebugText.size(); i++) { // int optionFlag = CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera|CommonGraphicsApp::eDrawText3D_TrueType; //int optionFlag = CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera; int optionFlag = 0; float orientation[4] = {0,0,0,1}; if (m_multiThreadedHelper->m_userDebugText[i].m_optionFlags&CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera) { orientation[0] = m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[0]; orientation[1] = m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[1]; orientation[2] = m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[2]; orientation[3] = m_multiThreadedHelper->m_userDebugText[i].m_textOrientation[3]; optionFlag |= CommonGraphicsApp::eDrawText3D_TrueType; } else { optionFlag |= CommonGraphicsApp::eDrawText3D_OrtogonalFaceCamera; } float colorRGBA[4] = { m_multiThreadedHelper->m_userDebugText[i].m_textColorRGB[0], m_multiThreadedHelper->m_userDebugText[i].m_textColorRGB[1], m_multiThreadedHelper->m_userDebugText[i].m_textColorRGB[2], 1.}; float pos[3] = {m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ1[0], m_multiThreadedHelper->m_userDebugText[i].m_textPositionXYZ1[1], 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]; } } } m_guiHelper->getAppInterface()->drawText3D(m_multiThreadedHelper->m_userDebugText[i].m_text, pos,orientation,colorRGBA, m_multiThreadedHelper->m_userDebugText[i].textSize,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() { btTransform vrTrans; B3_PROFILE("PhysicsServerExample::RenderScene"); drawUserDebugLines(); 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;igetAppInterface()->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()) { m_physicsServer.enableRealTimeSimulation(1); } } //m_args[0].m_cs->unlock(); } void PhysicsServerExample::physicsDebugDraw(int debugDrawFlags) { 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; gEnableUpdateDebugDrawLines = 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.normalize(); vertical = hor.cross(rayForward); vertical.normalize(); 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) { 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; 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); 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; }