diff --git a/examples/SharedMemory/RemoteGUIHelper.cpp b/examples/SharedMemory/RemoteGUIHelper.cpp new file mode 100644 index 000000000..80d1062a9 --- /dev/null +++ b/examples/SharedMemory/RemoteGUIHelper.cpp @@ -0,0 +1,550 @@ +#include "RemoteGUIHelper.h" + +#include "../CommonInterfaces/CommonExampleInterface.h" +#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "Bullet3Common/b3Logging.h" +#include "GraphicsSharedMemoryCommands.h" +#include "PosixSharedMemory.h" +#include "Win32SharedMemory.h" +#include "GraphicsSharedMemoryBlock.h" +#include "Bullet3Common/b3Scalar.h" +#include "LinearMath/btMinMax.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "Bullet3Common/b3AlignedObjectArray.h" + +struct RemoteGUIHelperInternalData +{ +// GUIHelperInterface* m_guiHelper; + bool m_waitingForServer; + GraphicsSharedMemoryBlock* m_testBlock1; + SharedMemoryInterface* m_sharedMemory; + GraphicsSharedMemoryStatus m_lastServerStatus; + int m_sharedMemoryKey; + bool m_isConnected; + + RemoteGUIHelperInternalData() + : m_waitingForServer(false), + m_testBlock1(0) + { +#ifdef _WIN32 + m_sharedMemory = new Win32SharedMemoryClient(); +#else + m_sharedMemory = new PosixSharedMemory(); +#endif + m_sharedMemoryKey = GRAPHICS_SHARED_MEMORY_KEY; + m_isConnected = false; + connect(); + + } + + virtual ~RemoteGUIHelperInternalData() + { + disconnect(); + delete m_sharedMemory; + } + + virtual bool isConnected() + { + return m_isConnected; + } + + bool canSubmitCommand() const + { + if (m_isConnected && !m_waitingForServer) + { + if (m_testBlock1->m_magicId == GRAPHICS_SHARED_MEMORY_MAGIC_NUMBER) + { + return true; + } + else + { + return false; + } + } + return false; + } + + struct GraphicsSharedMemoryCommand* getAvailableSharedMemoryCommand() + { + static int sequence = 0; + if (m_testBlock1) + { + m_testBlock1->m_clientCommands[0].m_sequenceNumber = sequence++; + return &m_testBlock1->m_clientCommands[0]; + } + return 0; + } + + bool submitClientCommand(const GraphicsSharedMemoryCommand& command) + { + /// at the moment we allow a maximum of 1 outstanding command, so we check for this + // once the server processed the command and returns a status, we clear the flag + // "m_data->m_waitingForServer" and allow submitting the next command + btAssert(!m_waitingForServer); + if (!m_waitingForServer) + { + //printf("submit command of type %d\n", command.m_type); + + if (&m_testBlock1->m_clientCommands[0] != &command) + { + m_testBlock1->m_clientCommands[0] = command; + } + m_testBlock1->m_numClientCommands++; + m_waitingForServer = true; + return true; + } + return false; + } + + + const GraphicsSharedMemoryStatus* processServerStatus() + { + // SharedMemoryStatus* stat = 0; + + if (!m_testBlock1) + { + m_lastServerStatus.m_type = GFX_CMD_SHARED_MEMORY_NOT_INITIALIZED; + return &m_lastServerStatus; + } + + if (!m_waitingForServer) + { + return 0; + } + + if (m_testBlock1->m_magicId != GRAPHICS_SHARED_MEMORY_MAGIC_NUMBER) + { + m_lastServerStatus.m_type = GFX_CMD_SHARED_MEMORY_NOT_INITIALIZED; + return &m_lastServerStatus; + } + + + if (m_testBlock1->m_numServerCommands > + m_testBlock1->m_numProcessedServerCommands) + { + B3_PROFILE("processServerCMD"); + b3Assert(m_testBlock1->m_numServerCommands == + m_testBlock1->m_numProcessedServerCommands + 1); + + const GraphicsSharedMemoryStatus& serverCmd = m_testBlock1->m_serverCommands[0]; + + m_lastServerStatus = serverCmd; + + // EnumSharedMemoryServerStatus s = (EnumSharedMemoryServerStatus)serverCmd.m_type; + // consume the command + switch (serverCmd.m_type) + { + case GFX_CMD_CLIENT_COMMAND_COMPLETED: + { + B3_PROFILE("CMD_CLIENT_COMMAND_COMPLETED"); + + + break; + } + default: + { + } + } + + m_testBlock1->m_numProcessedServerCommands++; + // we don't have more than 1 command outstanding (in total, either server or client) + b3Assert(m_testBlock1->m_numProcessedServerCommands == + m_testBlock1->m_numServerCommands); + + if (m_testBlock1->m_numServerCommands == + m_testBlock1->m_numProcessedServerCommands) + { + m_waitingForServer = false; + } + else + { + m_waitingForServer = true; + } + + + return &m_lastServerStatus; + } + return 0; + } + + bool connect() + { + /// server always has to create and initialize shared memory + bool allowCreation = false; + m_testBlock1 = (GraphicsSharedMemoryBlock*)m_sharedMemory->allocateSharedMemory( + m_sharedMemoryKey, GRAPHICS_SHARED_MEMORY_SIZE, allowCreation); + + if (m_testBlock1) + { + if (m_testBlock1->m_magicId != GRAPHICS_SHARED_MEMORY_MAGIC_NUMBER) + { + b3Error("Error connecting to shared memory: please start server before client\n"); + m_sharedMemory->releaseSharedMemory(m_sharedMemoryKey, + GRAPHICS_SHARED_MEMORY_SIZE); + m_testBlock1 = 0; + return false; + } + else + { + m_isConnected = true; + } + } + else + { + b3Warning("Cannot connect to shared memory"); + return false; + } + return true; + } + + + void disconnect() + { + if (m_isConnected && m_sharedMemory) + { + m_sharedMemory->releaseSharedMemory(m_sharedMemoryKey, GRAPHICS_SHARED_MEMORY_SIZE); + } + m_isConnected = false; + } + +}; + + + + + + + +RemoteGUIHelper::RemoteGUIHelper() +{ + m_data = new RemoteGUIHelperInternalData; + if (m_data->canSubmitCommand()) + { + removeAllGraphicsInstances(); + } +} + +RemoteGUIHelper::~RemoteGUIHelper() +{ + delete m_data; +} + +void RemoteGUIHelper::setVisualizerFlag(int flag, int enable) +{ + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_updateFlags = 0; + cmd->m_visualizerFlagCommand.m_visualizerFlag = flag; + cmd->m_visualizerFlagCommand.m_enable = enable; + cmd->m_type = GFX_CMD_SET_VISUALIZER_FLAG; + m_data->submitClientCommand(*cmd); + } + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } +} + +void RemoteGUIHelper::createRigidBodyGraphicsObject(btRigidBody* body, const btVector3& color) +{ + printf("createRigidBodyGraphicsObject\n"); +} + +void RemoteGUIHelper::createCollisionObjectGraphicsObject(btCollisionObject* body, const btVector3& color) +{ + if (body->getUserIndex() < 0) + { + btCollisionShape* shape = body->getCollisionShape(); + btTransform startTransform = body->getWorldTransform(); + int graphicsShapeId = shape->getUserIndex(); + if (graphicsShapeId >= 0) + { + // btAssert(graphicsShapeId >= 0); + //the graphics shape is already scaled + float localScaling[4] = { 1.f, 1.f, 1.f, 1.f }; + float colorRGBA[4] = { (float)color[0], (float)color[1], (float)color[2], (float) color[3] }; + float pos[4] = { (float)startTransform.getOrigin()[0], (float)startTransform.getOrigin()[1], (float)startTransform.getOrigin()[2], (float)startTransform.getOrigin()[3] }; + float orn[4] = { (float)startTransform.getRotation()[0], (float)startTransform.getRotation()[1], (float)startTransform.getRotation()[2], (float)startTransform.getRotation()[3] }; + int graphicsInstanceId = registerGraphicsInstance(graphicsShapeId, pos,orn, colorRGBA, localScaling); + body->setUserIndex(graphicsInstanceId); + } + } +} + +void RemoteGUIHelper::createCollisionShapeGraphicsObject(btCollisionShape* collisionShape) +{ + printf("createCollisionShapeGraphicsObject\n"); +} + +void RemoteGUIHelper::syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld) +{ +} + +void RemoteGUIHelper::syncPhysicsToGraphics2(const GUISyncPosition* positions, int numPositions) +{ + uploadData((unsigned char*) positions, numPositions * sizeof(GUISyncPosition), 0); + + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_updateFlags = 0; + cmd->m_syncTransformsCommand.m_numPositions = numPositions; + cmd->m_type = GFX_CMD_SYNCHRONIZE_TRANSFORMS; + m_data->submitClientCommand(*cmd); + } + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + + +} + +void RemoteGUIHelper::render(const btDiscreteDynamicsWorld* rbWorld) +{ +} + +void RemoteGUIHelper::createPhysicsDebugDrawer(btDiscreteDynamicsWorld* rbWorld) +{ +} + +int RemoteGUIHelper::uploadData(const unsigned char* data, int sizeInBytes, int slot) +{ + int chunkSize = GRAPHICS_SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE; + int remainingBytes = sizeInBytes; + int offset = 0; + while (remainingBytes) + { + btAssert(remainingBytes >= 0); + int curBytes = btMin(remainingBytes, chunkSize); + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + for (int i = 0; i < curBytes; i++) + { + m_data->m_testBlock1->m_bulletStreamData[i] = data[i]; + } + + cmd->m_updateFlags = 0; + cmd->m_type = GFX_CMD_UPLOAD_DATA; + cmd->m_uploadDataCommand.m_numBytes = curBytes; + cmd->m_uploadDataCommand.m_dataOffset = offset; + cmd->m_uploadDataCommand.m_dataSlot = slot; + m_data->submitClientCommand(*cmd); + + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + offset += curBytes; + remainingBytes -= curBytes; + } + } + return 0; +} + +int RemoteGUIHelper::registerTexture(const unsigned char* texels, int width, int height) +{ + int textureId = -1; + + //first upload all data + int sizeInBytes = width*height * 3;//rgb + uploadData(texels, sizeInBytes, 0); + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_updateFlags = 0; + cmd->m_type = GFX_CMD_REGISTER_TEXTURE; + cmd->m_registerTextureCommand.m_width = width; + cmd->m_registerTextureCommand.m_height = height; + m_data->submitClientCommand(*cmd); + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + if (status->m_type == GFX_CMD_REGISTER_TEXTURE_COMPLETED) + { + textureId = status->m_registerTextureStatus.m_textureId; + } + } + + + return textureId; +} + +int RemoteGUIHelper::registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices, int primitiveType, int textureId) +{ + int shapeId = -1; + + uploadData((unsigned char*)vertices, numvertices * 9*sizeof(float), 0); + uploadData((unsigned char*)indices, numIndices * sizeof(int), 1); + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_type = GFX_CMD_REGISTER_GRAPHICS_SHAPE; + cmd->m_updateFlags = 0; + cmd->m_registerGraphicsShapeCommand.m_numVertices = numvertices; + cmd->m_registerGraphicsShapeCommand.m_numIndices = numIndices; + cmd->m_registerGraphicsShapeCommand.m_primitiveType = primitiveType; + cmd->m_registerGraphicsShapeCommand.m_textureId = textureId; + + m_data->submitClientCommand(*cmd); + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + if (status->m_type == GFX_CMD_REGISTER_GRAPHICS_SHAPE_COMPLETED) + { + shapeId = status->m_registerGraphicsShapeStatus.m_shapeId; + } + } + + return shapeId; +} + +int RemoteGUIHelper::registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) +{ + int graphicsInstanceId = -1; + + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_type = GFX_CMD_REGISTER_GRAPHICS_INSTANCE; + cmd->m_updateFlags = 0; + cmd->m_registerGraphicsInstanceCommand.m_shapeIndex = shapeIndex; + for (int i = 0; i < 4; i++) + { + cmd->m_registerGraphicsInstanceCommand.m_position[i] = position[i]; + cmd->m_registerGraphicsInstanceCommand.m_quaternion[i] = quaternion[i]; + cmd->m_registerGraphicsInstanceCommand.m_color[i] = color[i]; + cmd->m_registerGraphicsInstanceCommand.m_scaling[i] = scaling[i]; + } + m_data->submitClientCommand(*cmd); + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + if (status->m_type == GFX_CMD_REGISTER_GRAPHICS_INSTANCE_COMPLETED) + { + graphicsInstanceId = status->m_registerGraphicsInstanceStatus.m_graphicsInstanceId; + } + + } + return graphicsInstanceId; +} + +void RemoteGUIHelper::removeAllGraphicsInstances() +{ + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_updateFlags = 0; + cmd->m_type = GFX_CMD_REMOVE_ALL_GRAPHICS_INSTANCES; + m_data->submitClientCommand(*cmd); + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + } +} + +void RemoteGUIHelper::removeGraphicsInstance(int graphicsUid) +{ + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_updateFlags = 0; + cmd->m_type = GFX_CMD_REMOVE_SINGLE_GRAPHICS_INSTANCE; + cmd->m_removeGraphicsInstanceCommand.m_graphicsUid = graphicsUid; + m_data->submitClientCommand(*cmd); + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + } +} +void RemoteGUIHelper::changeRGBAColor(int instanceUid, const double rgbaColor[4]) +{ +} +Common2dCanvasInterface* RemoteGUIHelper::get2dCanvasInterface() +{ + return 0; +} + +CommonParameterInterface* RemoteGUIHelper::getParameterInterface() +{ + return 0; +} + +CommonRenderInterface* RemoteGUIHelper::getRenderInterface() +{ + return 0; +} + +CommonGraphicsApp* RemoteGUIHelper::getAppInterface() +{ + return 0; +} + +void RemoteGUIHelper::setUpAxis(int axis) +{ + GraphicsSharedMemoryCommand* cmd = m_data->getAvailableSharedMemoryCommand(); + if (cmd) + { + cmd->m_updateFlags = 0; + cmd->m_upAxisYCommand.m_enableUpAxisY = axis == 1; + cmd->m_type = GFX_CMD_0; + m_data->submitClientCommand(*cmd); + const GraphicsSharedMemoryStatus* status = 0; + while ((status = m_data->processServerStatus()) == 0) + { + } + } +} +void RemoteGUIHelper::resetCamera(float camDist, float yaw, float pitch, float camPosX, float camPosY, float camPosZ) +{ +} + +void RemoteGUIHelper::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 width, int height, int* numPixelsCopied) + +{ + if (numPixelsCopied) + *numPixelsCopied = 0; +} + +void RemoteGUIHelper::setProjectiveTextureMatrices(const float viewMatrix[16], const float projectionMatrix[16]) +{ +} + +void RemoteGUIHelper::setProjectiveTexture(bool useProjectiveTexture) +{ +} + +void RemoteGUIHelper::autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld) +{ +} + +void RemoteGUIHelper::drawText3D(const char* txt, float posX, float posZY, float posZ, float size) +{ +} + +void RemoteGUIHelper::drawText3D(const char* txt, float position[3], float orientation[4], float color[4], float size, int optionFlag) +{ +} + +int RemoteGUIHelper::addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime, int trackingVisualShapeIndex, int replaceItemUid) +{ + return -1; +} +void RemoteGUIHelper::removeUserDebugItem(int debugItemUniqueId) +{ +} +void RemoteGUIHelper::removeAllUserDebugItems() +{ +} diff --git a/examples/SharedMemory/RemoteGUIHelper.h b/examples/SharedMemory/RemoteGUIHelper.h new file mode 100644 index 000000000..2acaaf007 --- /dev/null +++ b/examples/SharedMemory/RemoteGUIHelper.h @@ -0,0 +1,72 @@ +#ifndef REMOTE_HELPER_H +#define REMOTE_HELPER_H + +#include "../CommonInterfaces/CommonGUIHelperInterface.h" + +///a RemoteGUIHelper will connect to an existing graphics server through shared memory +struct RemoteGUIHelper : public GUIHelperInterface +{ + struct RemoteGUIHelperInternalData* m_data; + + RemoteGUIHelper(); + + virtual ~RemoteGUIHelper(); + + virtual void setVisualizerFlag(int flag, int enable); + + virtual void createRigidBodyGraphicsObject(btRigidBody* body, const btVector3& color); + + virtual void createCollisionObjectGraphicsObject(btCollisionObject* body, const btVector3& color); + + virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape); + + virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld); + virtual void syncPhysicsToGraphics2(const GUISyncPosition* positions, int numPositions); + + virtual void render(const btDiscreteDynamicsWorld* rbWorld); + + virtual void createPhysicsDebugDrawer(btDiscreteDynamicsWorld* rbWorld); + + virtual int registerTexture(const unsigned char* texels, int width, int height); + virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices, int primitiveType, int textureId); + virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); + virtual void removeAllGraphicsInstances(); + virtual void removeGraphicsInstance(int graphicsUid); + virtual void changeRGBAColor(int instanceUid, const double rgbaColor[4]); + + virtual Common2dCanvasInterface* get2dCanvasInterface(); + + virtual CommonParameterInterface* getParameterInterface(); + + virtual CommonRenderInterface* getRenderInterface(); + + virtual CommonGraphicsApp* getAppInterface(); + + virtual void setUpAxis(int axis); + + virtual void resetCamera(float camDist, float yaw, float pitch, float camPosX, float camPosY, float camPosZ); + + 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 width, int height, int* numPixelsCopied); + + virtual void setProjectiveTextureMatrices(const float viewMatrix[16], const float projectionMatrix[16]); + + virtual void setProjectiveTexture(bool useProjectiveTexture); + + virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld); + + 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); + + virtual int addUserDebugLine(const double debugLineFromXYZ[3], const double debugLineToXYZ[3], const double debugLineColorRGB[3], double lineWidth, double lifeTime, int trackingVisualShapeIndex, int replaceItemUid); + virtual void removeUserDebugItem(int debugItemUniqueId); + virtual void removeAllUserDebugItems(); + + int uploadData(const unsigned char* data, int sizeInBytes, int slot); +}; + +#endif //REMOTE_HELPER_H