From 97083923220845ef04e73cfa6ef34d0142f07576 Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Fri, 4 Nov 2016 13:15:10 -0700 Subject: [PATCH] work-in-progress add UDP network connection for physics client <-> server. also set spinning friction in rolling friction demo (otherwise objects may keep on spinning forever) --- build3/premake4.lua | 19 +- build_cmake_pybullet_win32.bat | 4 + examples/ExampleBrowser/CMakeLists.txt | 1 + .../ExampleBrowser/OpenGLExampleBrowser.cpp | 6 +- examples/ExampleBrowser/main.cpp | 4 + examples/ExampleBrowser/premake4.lua | 8 + .../MultiThreading/MultiThreadingExample.cpp | 3 + .../OpenGLWindow/GLInstancingRenderer.cpp | 8 +- examples/RoboticsLearning/b3RobotSimAPI.cpp | 5 +- .../RollingFrictionDemo.cpp | 10 +- examples/SharedMemory/PhysicsClientC_API.cpp | 132 ++-- examples/SharedMemory/PhysicsClientC_API.h | 12 +- .../PhysicsClientSharedMemory.cpp | 14 +- .../SharedMemory/PhysicsClientSharedMemory.h | 2 +- .../PhysicsClientSharedMemory2.cpp | 27 + .../SharedMemory/PhysicsClientSharedMemory2.h | 18 + .../PhysicsClientSharedMemory2_C_API.cpp | 19 + .../PhysicsClientSharedMemory2_C_API.h | 18 + .../PhysicsClientSharedMemory_C_API.cpp | 11 + .../PhysicsClientSharedMemory_C_API.h | 16 + examples/SharedMemory/PhysicsClientUDP.cpp | 577 ++++++++++++++++++ examples/SharedMemory/PhysicsClientUDP.h | 37 ++ .../SharedMemory/PhysicsClientUDP_C_API.cpp | 21 + .../SharedMemory/PhysicsClientUDP_C_API.h | 19 + .../PhysicsCommandProcessorInterface.h | 27 + examples/SharedMemory/PhysicsDirect.cpp | 264 +++++--- examples/SharedMemory/PhysicsDirect.h | 7 +- examples/SharedMemory/PhysicsDirectC_API.cpp | 10 +- .../PhysicsServerCommandProcessor.cpp | 21 +- .../PhysicsServerCommandProcessor.h | 38 +- .../SharedMemoryCommandProcessor.cpp | 216 +++++++ .../SharedMemoryCommandProcessor.h | 37 ++ examples/SharedMemory/SharedMemoryCommands.h | 5 +- examples/SharedMemory/premake4.lua | 13 +- examples/SharedMemory/udp/main.cpp | 187 ++++++ examples/SharedMemory/udp/premake4.lua | 46 ++ .../StandaloneMain/hellovr_opengl_main.cpp | 4 +- examples/ThirdPartyLibs/enet/premake4.lua | 3 +- examples/pybullet/CMakeLists.txt | 51 +- examples/pybullet/premake4.lua | 29 +- examples/pybullet/pybullet.c | 23 +- test/SharedMemory/CMakeLists.txt | 5 +- test/SharedMemory/premake4.lua | 2 + test/SharedMemory/test.c | 12 +- test/enet/chat/client/main.cpp | 165 +++++ test/enet/{ => chat}/client/premake4.lua | 4 +- test/enet/chat/server/main.cpp | 103 ++++ test/enet/{ => chat}/server/premake4.lua | 4 +- .../{ => nat_punchthrough}/client/main.cpp | 0 .../enet/nat_punchthrough/client/premake4.lua | 25 + .../{ => nat_punchthrough}/server/main.cpp | 0 .../enet/nat_punchthrough/server/premake4.lua | 26 + 52 files changed, 2104 insertions(+), 214 deletions(-) create mode 100644 build_cmake_pybullet_win32.bat create mode 100644 examples/SharedMemory/PhysicsClientSharedMemory2.cpp create mode 100644 examples/SharedMemory/PhysicsClientSharedMemory2.h create mode 100644 examples/SharedMemory/PhysicsClientSharedMemory2_C_API.cpp create mode 100644 examples/SharedMemory/PhysicsClientSharedMemory2_C_API.h create mode 100644 examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp create mode 100644 examples/SharedMemory/PhysicsClientSharedMemory_C_API.h create mode 100644 examples/SharedMemory/PhysicsClientUDP.cpp create mode 100644 examples/SharedMemory/PhysicsClientUDP.h create mode 100644 examples/SharedMemory/PhysicsClientUDP_C_API.cpp create mode 100644 examples/SharedMemory/PhysicsClientUDP_C_API.h create mode 100644 examples/SharedMemory/PhysicsCommandProcessorInterface.h create mode 100644 examples/SharedMemory/SharedMemoryCommandProcessor.cpp create mode 100644 examples/SharedMemory/SharedMemoryCommandProcessor.h create mode 100644 examples/SharedMemory/udp/main.cpp create mode 100644 examples/SharedMemory/udp/premake4.lua create mode 100644 test/enet/chat/client/main.cpp rename test/enet/{ => chat}/client/premake4.lua (70%) create mode 100644 test/enet/chat/server/main.cpp rename test/enet/{ => chat}/server/premake4.lua (70%) rename test/enet/{ => nat_punchthrough}/client/main.cpp (100%) create mode 100644 test/enet/nat_punchthrough/client/premake4.lua rename test/enet/{ => nat_punchthrough}/server/main.cpp (100%) create mode 100644 test/enet/nat_punchthrough/server/premake4.lua diff --git a/build3/premake4.lua b/build3/premake4.lua index f0de611fd..06e85d591 100644 --- a/build3/premake4.lua +++ b/build3/premake4.lua @@ -73,8 +73,8 @@ newoption { - trigger = "enet", - description = "Enable enet NAT punchthrough test" + trigger = "no-enet", + description = "Disable enet and enet tests" } newoption @@ -261,14 +261,19 @@ end if not _OPTIONS["no-test"] then include "../test/SharedMemory" - if _OPTIONS["enet"] then - include "../examples/ThirdPartyLibs/enet" - include "../test/enet/client" - include "../test/enet/server" - end + end end + if not _OPTIONS["no-enet"] then + include "../examples/ThirdPartyLibs/enet" + include "../test/enet/nat_punchthrough/client" + include "../test/enet/nat_punchthrough/server" + include "../test/enet/chat/client" + include "../test/enet/chat/server" + defines {"BT_ENABLE_ENET"} + end + if _OPTIONS["no-bullet3"] then print "--no-bullet3 implies --no-demos" _OPTIONS["no-demos"] = "1" diff --git a/build_cmake_pybullet_win32.bat b/build_cmake_pybullet_win32.bat new file mode 100644 index 000000000..33317f2c1 --- /dev/null +++ b/build_cmake_pybullet_win32.bat @@ -0,0 +1,4 @@ +mkdir cm +cd cm +cmake -DBUILD_PYBULLET=ON -DCMAKE_BUILD_TYPE=Release -DPYTHON_INCLUDE_DIR=c:\python-3.5.2\include -DPYTHON_LIBRARY=c:\python-3.5.2\libs\python35_d.lib .. +start . diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 024d928d3..f85beb6d5 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -146,6 +146,7 @@ SET(BulletExampleBrowser_SRCS ../SharedMemory/PhysicsServer.cpp ../SharedMemory/PhysicsClientSharedMemory.cpp + ../SharedMemory/PhysicsClientSharedMemory_C_API.cpp ../SharedMemory/PhysicsClient.cpp ../SharedMemory/PhysicsClientC_API.cpp ../SharedMemory/PhysicsServerExample.cpp diff --git a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp index 70e717159..962f04437 100644 --- a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp +++ b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp @@ -134,9 +134,9 @@ int gSharedMemoryKey=-1; int gPreferredOpenCLDeviceIndex=-1; int gPreferredOpenCLPlatformIndex=-1; -int gGpuArraySizeX=15; -int gGpuArraySizeY=15; -int gGpuArraySizeZ=15; +int gGpuArraySizeX=45; +int gGpuArraySizeY=55; +int gGpuArraySizeZ=45; //#include //unsigned int fp_control_state = _controlfp(_EM_INEXACT, _MCW_EM); diff --git a/examples/ExampleBrowser/main.cpp b/examples/ExampleBrowser/main.cpp index d0f132c1a..05985d41e 100644 --- a/examples/ExampleBrowser/main.cpp +++ b/examples/ExampleBrowser/main.cpp @@ -15,6 +15,8 @@ #include "../Importers/ImportURDFDemo/ImportURDFSetup.h" #include "../Importers/ImportSDFDemo/ImportSDFSetup.h" #include "../Importers/ImportSTLDemo/ImportSTLSetup.h" +#include "../Importers/ImportBullet/SerializeSetup.h" + #include "LinearMath/btAlignedAllocator.h" @@ -34,6 +36,8 @@ int main(int argc, char* argv[]) exampleBrowser->registerFileImporter(".sdf", ImportSDFCreateFunc); exampleBrowser->registerFileImporter(".obj", ImportObjCreateFunc); exampleBrowser->registerFileImporter(".stl", ImportSTLCreateFunc); + exampleBrowser->registerFileImporter(".bullet", SerializeBulletCreateFunc); + clock.reset(); if (init) diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index c28ae0e5a..ff47ffc73 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -63,6 +63,14 @@ project "App_BulletExampleBrowser" "../SharedMemory/PhysicsServer.cpp", "../SharedMemory/PhysicsServerSharedMemory.cpp", "../SharedMemory/PhysicsClientSharedMemory.cpp", + "../SharedMemory/PhysicsClientSharedMemory_C_API.cpp", + "../SharedMemory/PhysicsClientSharedMemory_C_API.h", + "../SharedMemory/PhysicsClientSharedMemory2.cpp", + "../SharedMemory/PhysicsClientSharedMemory2.h", + "../SharedMemory/PhysicsClientSharedMemory2_C_API.cpp", + "../SharedMemory/PhysicsClientSharedMemory2_C_API.h", + "../SharedMemory/SharedMemoryCommandProcessor.cpp", + "../SharedMemory/SharedMemoryCommandProcessor.h", "../SharedMemory/SharedMemoryInProcessPhysicsC_API.cpp", "../SharedMemory/PhysicsClient.cpp", "../SharedMemory/PosixSharedMemory.cpp", diff --git a/examples/MultiThreading/MultiThreadingExample.cpp b/examples/MultiThreading/MultiThreadingExample.cpp index 1969912b9..33eb0e751 100644 --- a/examples/MultiThreading/MultiThreadingExample.cpp +++ b/examples/MultiThreading/MultiThreadingExample.cpp @@ -11,6 +11,7 @@ #include "stb_image/stb_image.h" #include "Bullet3Common/b3Quaternion.h" #include "Bullet3Common/b3Matrix3x3.h" +#include "../Utils/b3Clock.h" #include "../CommonInterfaces/CommonParameterInterface.h" #include "LinearMath/btAlignedObjectArray.h" @@ -134,6 +135,8 @@ void SampleThreadFunc(void* userPtr,void* lsMemory) job->executeJob(localStorage->threadId); } + b3Clock::usleep(250); + args->m_cs->lock(); int exitMagicNumber = args->m_cs->getSharedParam(1); requestExit = (exitMagicNumber==MAGIC_RESET_NUMBER); diff --git a/examples/OpenGLWindow/GLInstancingRenderer.cpp b/examples/OpenGLWindow/GLInstancingRenderer.cpp index 718a9fc60..c6f620bab 100644 --- a/examples/OpenGLWindow/GLInstancingRenderer.cpp +++ b/examples/OpenGLWindow/GLInstancingRenderer.cpp @@ -17,9 +17,9 @@ subject to the following restrictions: ///todo: make this configurable in the gui bool useShadowMap = true;// true;//false;//true; -int shadowMapWidth= 2048; -int shadowMapHeight= 2048; -float shadowMapWorldSize=5; +int shadowMapWidth= 4096; +int shadowMapHeight= 4096; +float shadowMapWorldSize=10; #define MAX_POINTS_IN_BATCH 1024 #define MAX_LINES_IN_BATCH 1024 @@ -1539,7 +1539,7 @@ void GLInstancingRenderer::renderSceneInternal(int renderMode) b3Assert(glGetError() ==GL_NO_ERROR); } else { - //glDisable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } diff --git a/examples/RoboticsLearning/b3RobotSimAPI.cpp b/examples/RoboticsLearning/b3RobotSimAPI.cpp index 40527e481..81c308b92 100644 --- a/examples/RoboticsLearning/b3RobotSimAPI.cpp +++ b/examples/RoboticsLearning/b3RobotSimAPI.cpp @@ -5,6 +5,8 @@ #include "Bullet3Common/b3AlignedObjectArray.h" #include "../CommonInterfaces/CommonRenderInterface.h" //#include "../CommonInterfaces/CommonExampleInterface.h" +#include "../SharedMemory/PhysicsServerCommandProcessor.h" + #include "../CommonInterfaces/CommonGUIHelperInterface.h" #include "../SharedMemory/PhysicsServerSharedMemory.h" #include "../SharedMemory/PhysicsServerSharedMemory.h" @@ -893,7 +895,8 @@ bool b3RobotSimAPI::connect(GUIHelperInterface* guiHelper) } else { - m_data->m_clientServerDirect = new PhysicsDirect(); + PhysicsServerCommandProcessor* sdk = new PhysicsServerCommandProcessor; + m_data->m_clientServerDirect = new PhysicsDirect(sdk); bool connected = m_data->m_clientServerDirect->connect(guiHelper); m_data->m_physicsClient = (b3PhysicsClientHandle)m_data->m_clientServerDirect; diff --git a/examples/RollingFrictionDemo/RollingFrictionDemo.cpp b/examples/RollingFrictionDemo/RollingFrictionDemo.cpp index 7e53be9b0..65a2404d3 100644 --- a/examples/RollingFrictionDemo/RollingFrictionDemo.cpp +++ b/examples/RollingFrictionDemo/RollingFrictionDemo.cpp @@ -123,8 +123,8 @@ void RollingFrictionDemo::initPhysics() btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); - body->setFriction(1); - body->setRollingFriction(1); + body->setFriction(.5); + //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } @@ -153,8 +153,7 @@ void RollingFrictionDemo::initPhysics() btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); - body->setFriction(1); - body->setRollingFriction(1); + body->setFriction(.1); //add the body to the dynamics world m_dynamicsWorld->addRigidBody(body); } @@ -217,7 +216,8 @@ void RollingFrictionDemo::initPhysics() btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia); btRigidBody* body = new btRigidBody(rbInfo); body->setFriction(1.f); - body->setRollingFriction(.3); + body->setRollingFriction(.1); + body->setSpinningFriction(0.1); body->setAnisotropicFriction(colShape->getAnisotropicRollingFrictionDirection(),btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION); diff --git a/examples/SharedMemory/PhysicsClientC_API.cpp b/examples/SharedMemory/PhysicsClientC_API.cpp index 434a99b7f..325c12fed 100644 --- a/examples/SharedMemory/PhysicsClientC_API.cpp +++ b/examples/SharedMemory/PhysicsClientC_API.cpp @@ -58,21 +58,25 @@ b3SharedMemoryCommandHandle b3LoadUrdfCommandInit(b3PhysicsClientHandle physClie b3Assert(cl); b3Assert(cl->canSubmitCommand()); - - struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand(); - b3Assert(command); - command->m_type = CMD_LOAD_URDF; - int len = strlen(urdfFileName); - if (lencanSubmitCommand()) { - strcpy(command->m_urdfArguments.m_urdfFileName,urdfFileName); - } else - { - command->m_urdfArguments.m_urdfFileName[0] = 0; + struct SharedMemoryCommand* command = cl->getAvailableSharedMemoryCommand(); + b3Assert(command); + command->m_type = CMD_LOAD_URDF; + int len = strlen(urdfFileName); + if (len < MAX_URDF_FILENAME_LENGTH) + { + strcpy(command->m_urdfArguments.m_urdfFileName, urdfFileName); + } + else + { + command->m_urdfArguments.m_urdfFileName[0] = 0; + } + command->m_updateFlags = URDF_ARGS_FILE_NAME; + + return (b3SharedMemoryCommandHandle)command; } - command->m_updateFlags = URDF_ARGS_FILE_NAME; - - return (b3SharedMemoryCommandHandle) command; + return 0; } b3SharedMemoryCommandHandle b3LoadBunnyCommandInit(b3PhysicsClientHandle physClient) @@ -116,35 +120,52 @@ int b3LoadUrdfCommandSetUseFixedBase(b3SharedMemoryCommandHandle commandHandle, struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle; b3Assert(command); b3Assert(command->m_type == CMD_LOAD_URDF); - command->m_updateFlags |=URDF_ARGS_USE_FIXED_BASE; - command->m_urdfArguments.m_useFixedBase = useFixedBase; - - return 0; + if (command && (command->m_type == CMD_LOAD_URDF)) + { + command->m_updateFlags |= URDF_ARGS_USE_FIXED_BASE; + command->m_urdfArguments.m_useFixedBase = useFixedBase; + return 0; + } + return -1; } int b3LoadUrdfCommandSetStartPosition(b3SharedMemoryCommandHandle commandHandle, double startPosX,double startPosY,double startPosZ) { struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle; b3Assert(command); - b3Assert(command->m_type == CMD_LOAD_URDF); - command->m_urdfArguments.m_initialPosition[0] = startPosX; - command->m_urdfArguments.m_initialPosition[1] = startPosY; - command->m_urdfArguments.m_initialPosition[2] = startPosZ; - command->m_updateFlags|=URDF_ARGS_INITIAL_POSITION; - return 0; + if (command) + { + b3Assert(command->m_type == CMD_LOAD_URDF); + if (command->m_type == CMD_LOAD_URDF) + { + command->m_urdfArguments.m_initialPosition[0] = startPosX; + command->m_urdfArguments.m_initialPosition[1] = startPosY; + command->m_urdfArguments.m_initialPosition[2] = startPosZ; + command->m_updateFlags |= URDF_ARGS_INITIAL_POSITION; + } + return 0; + } + return -1; } int b3LoadUrdfCommandSetStartOrientation(b3SharedMemoryCommandHandle commandHandle, double startOrnX,double startOrnY,double startOrnZ, double startOrnW) { struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle; b3Assert(command); - b3Assert(command->m_type == CMD_LOAD_URDF); - command->m_urdfArguments.m_initialOrientation[0] = startOrnX; - command->m_urdfArguments.m_initialOrientation[1] = startOrnY; - command->m_urdfArguments.m_initialOrientation[2] = startOrnZ; - command->m_urdfArguments.m_initialOrientation[3] = startOrnW; - command->m_updateFlags|=URDF_ARGS_INITIAL_ORIENTATION; - return 0; + if (command) + { + b3Assert(command->m_type == CMD_LOAD_URDF); + if (command->m_type == CMD_LOAD_URDF) + { + command->m_urdfArguments.m_initialOrientation[0] = startOrnX; + command->m_urdfArguments.m_initialOrientation[1] = startOrnY; + command->m_urdfArguments.m_initialOrientation[2] = startOrnZ; + command->m_urdfArguments.m_initialOrientation[3] = startOrnW; + command->m_updateFlags |= URDF_ARGS_INITIAL_ORIENTATION; + } + return 0; + } + return -1; } b3SharedMemoryCommandHandle b3InitPhysicsParamCommand(b3PhysicsClientHandle physClient) @@ -174,7 +195,7 @@ int b3PhysicsParamSetRealTimeSimulation(b3SharedMemoryCommandHandle commandH { struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle; b3Assert(command->m_type == CMD_SEND_PHYSICS_SIMULATION_PARAMETERS); - command->m_physSimParamArgs.m_allowRealTimeSimulation = enableRealTimeSimulation; + command->m_physSimParamArgs.m_allowRealTimeSimulation = (enableRealTimeSimulation!=0); command->m_updateFlags |= SIM_PARAM_UPDATE_REAL_TIME_SIMULATION; return 0; } @@ -621,20 +642,11 @@ int b3CreateSensorEnableIMUForLink(b3SharedMemoryCommandHandle commandHandle, in } -b3PhysicsClientHandle b3ConnectSharedMemory(int key) -{ - - PhysicsClientSharedMemory* cl = new PhysicsClientSharedMemory(); - ///client should never create shared memory, only the server does - cl->setSharedMemoryKey(key); - cl->connect(); - return (b3PhysicsClientHandle ) cl; -} - void b3DisconnectSharedMemory(b3PhysicsClientHandle physClient) { PhysicsClient* cl = (PhysicsClient* ) physClient; + cl->disconnectSharedMemory(); delete cl; } @@ -772,22 +784,34 @@ int b3SubmitClientCommand(b3PhysicsClientHandle physClient, const b3SharedMemory { struct SharedMemoryCommand* command = (struct SharedMemoryCommand*) commandHandle; PhysicsClient* cl = (PhysicsClient* ) physClient; - return (int)cl->submitClientCommand(*command); + b3Assert(command); + b3Assert(cl); + if (command && cl) + { + return (int)cl->submitClientCommand(*command); + } + return -1; + } b3SharedMemoryStatusHandle b3SubmitClientCommandAndWaitStatus(b3PhysicsClientHandle physClient, const b3SharedMemoryCommandHandle commandHandle) { - int timeout = 1024*1024*1024; - b3SharedMemoryStatusHandle statusHandle=0; - - b3SubmitClientCommand(physClient,commandHandle); - - while ((statusHandle==0) && (timeout-- > 0)) - { - statusHandle =b3ProcessServerStatus(physClient); - } - return (b3SharedMemoryStatusHandle) statusHandle; - + int timeout = 1024 * 1024 * 1024; + b3SharedMemoryStatusHandle statusHandle = 0; + b3Assert(commandHandle); + b3Assert(physClient); + if (physClient && commandHandle) + { + b3SubmitClientCommand(physClient, commandHandle); + + while ((statusHandle == 0) && (timeout-- > 0)) + { + statusHandle = b3ProcessServerStatus(physClient); + } + return (b3SharedMemoryStatusHandle)statusHandle; + } + + return 0; } @@ -1546,4 +1570,4 @@ int b3GetStatusInverseKinematicsJointPositions(b3SharedMemoryStatusHandle status } return true; -} \ No newline at end of file +} diff --git a/examples/SharedMemory/PhysicsClientC_API.h b/examples/SharedMemory/PhysicsClientC_API.h index 68e579f6f..8a1381bf9 100644 --- a/examples/SharedMemory/PhysicsClientC_API.h +++ b/examples/SharedMemory/PhysicsClientC_API.h @@ -11,14 +11,18 @@ B3_DECLARE_HANDLE(b3SharedMemoryCommandHandle); B3_DECLARE_HANDLE(b3SharedMemoryStatusHandle); +///There are several connection methods, see following header files: +#include "PhysicsClientSharedMemory_C_API.h" +#include "PhysicsClientSharedMemory2_C_API.h" +#include "PhysicsDirectC_API.h" +#include "PhysicsClientUDP_C_API.h" +#include "SharedMemoryInProcessPhysicsC_API.h" + #ifdef __cplusplus extern "C" { #endif -///b3ConnectSharedMemory will connect to a physics server over shared memory, so -///make sure to start the server first. -///and a way to spawn an OpenGL 3D GUI physics server and connect (b3CreateInProcessPhysicsServerAndConnect) -b3PhysicsClientHandle b3ConnectSharedMemory(int key); + ///b3DisconnectSharedMemory will disconnect the client from the server and cleanup memory. void b3DisconnectSharedMemory(b3PhysicsClientHandle physClient); diff --git a/examples/SharedMemory/PhysicsClientSharedMemory.cpp b/examples/SharedMemory/PhysicsClientSharedMemory.cpp index 9dda6aca1..65f4d8aba 100644 --- a/examples/SharedMemory/PhysicsClientSharedMemory.cpp +++ b/examples/SharedMemory/PhysicsClientSharedMemory.cpp @@ -124,8 +124,11 @@ bool PhysicsClientSharedMemory::getJointInfo(int bodyUniqueId, int jointIndex, b if (bodyJointsPtr && *bodyJointsPtr) { BodyJointInfoCache* bodyJoints = *bodyJointsPtr; - info = bodyJoints->m_jointInfo[jointIndex]; - return true; + if ((jointIndex >= 0) && (jointIndex < bodyJoints->m_jointInfo.size())) + { + info = bodyJoints->m_jointInfo[jointIndex]; + return true; + } } return false; } @@ -210,7 +213,7 @@ void PhysicsClientSharedMemory::processBodyJointInfo(int bodyUniqueId, const Sha { bParse::btBulletFile bf( &this->m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor[0], - serverCmd.m_dataStreamArguments.m_streamChunkLength); + serverCmd.m_numDataStreamBytes); bf.setFileDNAisMemoryDNA(); bf.parse(false); @@ -291,16 +294,17 @@ const SharedMemoryStatus* PhysicsClientSharedMemory::processServerStatus() { break; } + case CMD_URDF_LOADING_COMPLETED: { if (m_data->m_verboseOutput) { b3Printf("Server loading the URDF OK\n"); } - if (serverCmd.m_dataStreamArguments.m_streamChunkLength > 0) { + if (serverCmd.m_numDataStreamBytes > 0) { bParse::btBulletFile bf( this->m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor, - serverCmd.m_dataStreamArguments.m_streamChunkLength); + serverCmd.m_numDataStreamBytes); bf.setFileDNAisMemoryDNA(); bf.parse(false); int bodyUniqueId = serverCmd.m_dataStreamArguments.m_bodyUniqueId; diff --git a/examples/SharedMemory/PhysicsClientSharedMemory.h b/examples/SharedMemory/PhysicsClientSharedMemory.h index 2dc659646..1ebe5bccd 100644 --- a/examples/SharedMemory/PhysicsClientSharedMemory.h +++ b/examples/SharedMemory/PhysicsClientSharedMemory.h @@ -12,7 +12,7 @@ class PhysicsClientSharedMemory : public PhysicsClient { protected: virtual void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem); void processBodyJointInfo(int bodyUniqueId, const struct SharedMemoryStatus& serverCmd); - + public: PhysicsClientSharedMemory(); diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2.cpp b/examples/SharedMemory/PhysicsClientSharedMemory2.cpp new file mode 100644 index 000000000..7eea2298d --- /dev/null +++ b/examples/SharedMemory/PhysicsClientSharedMemory2.cpp @@ -0,0 +1,27 @@ + +#include "PhysicsClientSharedMemory2.h" +#include "PosixSharedMemory.h" +#include "Win32SharedMemory.h" +#include "Bullet3Common/b3Logging.h" +#include "Bullet3Common/b3Scalar.h" + +#include "SharedMemoryCommandProcessor.h" + + +PhysicsClientSharedMemory2::PhysicsClientSharedMemory2(SharedMemoryCommandProcessor* proc) + :PhysicsDirect(proc) +{ + m_proc = proc; +} +PhysicsClientSharedMemory2::~PhysicsClientSharedMemory2() +{ +} + +void PhysicsClientSharedMemory2::setSharedMemoryInterface(class SharedMemoryInterface* sharedMem) +{ + if (m_proc) + { + m_proc->setSharedMemoryInterface(sharedMem); + } +} + diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2.h b/examples/SharedMemory/PhysicsClientSharedMemory2.h new file mode 100644 index 000000000..e3b109370 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientSharedMemory2.h @@ -0,0 +1,18 @@ +#ifndef PHYSICS_CLIENT_SHARED_MEMORY2_H +#define PHYSICS_CLIENT_SHARED_MEMORY2_H + +#include "PhysicsDirect.h" + +class PhysicsClientSharedMemory2 : public PhysicsDirect +{ + class SharedMemoryCommandProcessor* m_proc; + +public: + PhysicsClientSharedMemory2(SharedMemoryCommandProcessor* proc); + virtual ~PhysicsClientSharedMemory2(); + + void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem); + +}; + +#endif //PHYSICS_CLIENT_SHARED_MEMORY2_H \ No newline at end of file diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.cpp b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.cpp new file mode 100644 index 000000000..7323205d0 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.cpp @@ -0,0 +1,19 @@ +#include "PhysicsClientSharedMemory2_C_API.h" + +#include "PhysicsDirect.h" +#include "SharedMemoryCommandProcessor.h" + +b3PhysicsClientHandle b3ConnectSharedMemory2(int key) +{ + + SharedMemoryCommandProcessor* cmdProc = new SharedMemoryCommandProcessor(); + cmdProc->setSharedMemoryKey(key); + PhysicsDirect* cl = new PhysicsDirect(cmdProc); + + cl->setSharedMemoryKey(key); + + cl->connect(); + + return (b3PhysicsClientHandle)cl; +} + diff --git a/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.h b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.h new file mode 100644 index 000000000..95d4bf690 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientSharedMemory2_C_API.h @@ -0,0 +1,18 @@ +#ifndef PHYSICS_CLIENT_SHARED_MEMORY2_H +#define PHYSICS_CLIENT_SHARED_MEMORY2_H + +#include "PhysicsClientC_API.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +b3PhysicsClientHandle b3ConnectSharedMemory2(int key); + + +#ifdef __cplusplus +} +#endif + +#endif //PHYSICS_CLIENT_SHARED_MEMORY2_H diff --git a/examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp new file mode 100644 index 000000000..36c794f80 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp @@ -0,0 +1,11 @@ +#include "PhysicsClientSharedMemory_C_API.h" + +#include "PhysicsClientSharedMemory.h" + +b3PhysicsClientHandle b3ConnectSharedMemory(int key) +{ + PhysicsClientSharedMemory* cl = new PhysicsClientSharedMemory(); + cl->setSharedMemoryKey(key); + cl->connect(); + return (b3PhysicsClientHandle)cl; +} diff --git a/examples/SharedMemory/PhysicsClientSharedMemory_C_API.h b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.h new file mode 100644 index 000000000..2a4e4e665 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientSharedMemory_C_API.h @@ -0,0 +1,16 @@ +#ifndef PHYSICS_CLIENT_SHARED_MEMORY_H +#define PHYSICS_CLIENT_SHARED_MEMORY_H + +#include "PhysicsClientC_API.h" + +#ifdef __cplusplus +extern "C" { +#endif + + b3PhysicsClientHandle b3ConnectSharedMemory(int key); + +#ifdef __cplusplus +} +#endif + +#endif //PHYSICS_CLIENT_SHARED_MEMORY_H diff --git a/examples/SharedMemory/PhysicsClientUDP.cpp b/examples/SharedMemory/PhysicsClientUDP.cpp new file mode 100644 index 000000000..a112e0900 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientUDP.cpp @@ -0,0 +1,577 @@ +#include "PhysicsClientUDP.h" +#include +#include +#include +#include "../Utils/b3Clock.h" +#include "PhysicsClient.h" +//#include "LinearMath/btVector3.h" +#include "SharedMemoryCommands.h" +#include +#include "Bullet3Common/b3Logging.h" +#include "../MultiThreading/b3ThreadSupportInterface.h" +void UDPThreadFunc(void* userPtr, void* lsMemory); +void* UDPlsMemoryFunc(); + +#ifndef _WIN32 +#include "../MultiThreading/b3PosixThreadSupport.h" + +b3ThreadSupportInterface* createUDPThreadSupport(int numThreads) +{ + b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("UDPThread", + UDPThreadFunc, + UDPlsMemoryFunc, + numThreads); + b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo); + + return threadSupport; + +} + + +#elif defined( _WIN32) +#include "../MultiThreading/b3Win32ThreadSupport.h" + +b3ThreadSupportInterface* createUDPThreadSupport(int numThreads) +{ + b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("UDPThread", UDPThreadFunc, UDPlsMemoryFunc, numThreads); + b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo); + return threadSupport; + +} +#endif + + + +struct UDPThreadLocalStorage +{ + int threadId; +}; + + + +unsigned int b3DeserializeInt(const unsigned char* input) +{ + unsigned int tmp = (input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0]; + return tmp; +} + +struct UdpNetworkedInternalData +{ + ENetHost* m_client; + ENetAddress m_address; + ENetPeer* m_peer; + ENetEvent m_event; + bool m_isConnected; + + b3ThreadSupportInterface* m_threadSupport; + + b3CriticalSection* m_cs; + + UdpNetworkedInternalData* m_udpInternalData; + + + SharedMemoryCommand m_clientCmd; + bool m_hasCommand; + + bool m_hasStatus; + SharedMemoryStatus m_lastStatus; + b3AlignedObjectArray m_stream; + + std::string m_hostName; + int m_port; + + UdpNetworkedInternalData() + :m_client(0), + m_peer(0), + m_isConnected(false), + m_threadSupport(0), + m_hasCommand(false), + m_hasStatus(false) + { + + } + + bool connectUDP() + { + if (m_isConnected) + return true; + + + + if (enet_initialize() != 0) + { + fprintf(stderr, "Error initialising enet"); + exit(EXIT_FAILURE); + + } + + m_client = enet_host_create(NULL, /* create a client host */ + 1, /* number of clients */ + 2, /* number of channels */ + 57600 / 8, /* incoming bandwith */ + 14400 / 8); /* outgoing bandwith */ + + if (m_client == NULL) { + fprintf(stderr, "Could not create client host"); + return false; + } + + enet_address_set_host(&m_address, m_hostName.c_str()); + m_address.port = m_port; + + m_peer = enet_host_connect(m_client, + &m_address, /* address to connect to */ + 2, /* number of channels */ + 0); /* user data supplied to + the receiving host */ + + if (m_peer == NULL) { + fprintf(stderr, "No available peers for initiating an ENet " + "connection.\n"); + return false; + + } + + + /* Try to connect to server within 5 seconds */ + if (enet_host_service(m_client, &m_event, 5000) > 0 && + m_event.type == ENET_EVENT_TYPE_CONNECT) + { + puts("Connection to server succeeded."); + } + else + { + /* Either the 5 seconds are up or a disconnect event was */ + /* received. Reset the peer in the event the 5 seconds */ + /* had run out without any significant event. */ + enet_peer_reset(m_peer); + + fprintf(stderr, "Connection to server failed."); + return false; + } + + + int serviceResult = enet_host_service(m_client, &m_event, 0); + + if (serviceResult > 0) + { + switch (m_event.type) + { + case ENET_EVENT_TYPE_CONNECT: + printf("A new client connected from %x:%u.\n", + m_event.peer->address.host, + m_event.peer->address.port); + m_event.peer->data = (void*)"New User"; + break; + + case ENET_EVENT_TYPE_RECEIVE: + printf("A packet of length %u containing '%s' was " + "received from %s on channel %u.\n", + m_event.packet->dataLength, + m_event.packet->data, + m_event.peer->data, + m_event.channelID); + + /* Clean up the packet now that we're done using it. + > */ + enet_packet_destroy(m_event.packet); + + break; + + case ENET_EVENT_TYPE_DISCONNECT: + printf("%s disconected.\n", m_event.peer->data); + + break; + } + } + else if (serviceResult > 0) + { + puts("Error with servicing the client"); + return false; + } + + m_isConnected = true; + return m_isConnected; + } + + bool checkData() + { + bool hasStatus = false; + + int serviceResult = enet_host_service(m_client, &m_event, 100); + + if (serviceResult > 0) + { + switch (m_event.type) + { + case ENET_EVENT_TYPE_CONNECT: + printf("A new client connected from %x:%u.\n", + m_event.peer->address.host, + m_event.peer->address.port); + + m_event.peer->data = (void*)"New User"; + break; + + case ENET_EVENT_TYPE_RECEIVE: + { + printf("A packet of length %u containing '%s' was " + "received from %s on channel %u.\n", + m_event.packet->dataLength, + m_event.packet->data, + m_event.peer->data, + m_event.channelID); + + + int packetSizeInBytes = b3DeserializeInt(m_event.packet->data); + + if (packetSizeInBytes == m_event.packet->dataLength) + { + + SharedMemoryStatus* statPtr = (SharedMemoryStatus*)&m_event.packet->data[4]; + m_lastStatus = *statPtr; + int streamOffsetInBytes = 4 + sizeof(SharedMemoryStatus); + int numStreamBytes = packetSizeInBytes - streamOffsetInBytes; + m_stream.resize(numStreamBytes); + for (int i = 0; i < numStreamBytes; i++) + { + m_stream[i] = m_event.packet->data[i + streamOffsetInBytes]; + } + } + else + { + printf("unknown status message received\n"); + } + enet_packet_destroy(m_event.packet); + hasStatus = true; + break; + } + case ENET_EVENT_TYPE_DISCONNECT: + { + printf("%s disconected.\n", m_event.peer->data); + + break; + } + } + } + else if (serviceResult > 0) + { + puts("Error with servicing the client"); + } + + return hasStatus; + } + +}; + +enum UDPThreadEnums +{ + eUDPRequestTerminate = 13, + eUDPIsUnInitialized, + eUDPIsInitialized, + eUDPInitializationFailed, + eUDPHasTerminated +}; + + + +enum UDPCommandEnums +{ + eUDPIdle = 13, + eUDP_ConnectRequest, + eUDP_Connected, + eUDP_ConnectionFailed, + eUDP_DisconnectRequest, + eUDP_Disconnected, + +}; + +void UDPThreadFunc(void* userPtr, void* lsMemory) +{ + printf("UDPThreadFunc thread started\n"); + UDPThreadLocalStorage* localStorage = (UDPThreadLocalStorage*)lsMemory; + + UdpNetworkedInternalData* args = (UdpNetworkedInternalData*)userPtr; + int workLeft = true; + b3Clock clock; + clock.reset(); + bool init = true; + if (init) + { + + args->m_cs->lock(); + args->m_cs->setSharedParam(0, eUDPIsInitialized); + args->m_cs->unlock(); + + + double deltaTimeInSeconds = 0; + + do + { + deltaTimeInSeconds += double(clock.getTimeMicroseconds()) / 1000000.; + + if (deltaTimeInSeconds<(1. / 5000.)) + { +// b3Clock::usleep(250); + } + else + { + + clock.reset(); + deltaTimeInSeconds = 0.f; + switch (args->m_cs->getSharedParam(1)) + { + case eUDP_ConnectRequest: + { + bool connected = args->connectUDP(); + if (connected) + { + args->m_cs->setSharedParam(1, eUDP_Connected); + } + else + { + args->m_cs->setSharedParam(1, eUDP_ConnectionFailed); + } + break; + } + default: + { + } + }; + + if (args->m_isConnected) + { + + args->m_cs->lock(); + bool hasCommand = args->m_hasCommand; + args->m_cs->unlock(); + + + if (hasCommand) + { + + int sz = sizeof(SharedMemoryCommand); + ENetPacket *packet = enet_packet_create(&args->m_clientCmd, sz, ENET_PACKET_FLAG_RELIABLE); + int res = enet_peer_send(args->m_peer, 0, packet); + args->m_cs->lock(); + args->m_hasCommand = false; + args->m_cs->unlock(); + } + + + bool hasNewStatus = args->checkData(); + if (hasNewStatus) + { + if (args->m_hasStatus) + { + //overflow: last status hasn't been processed yet + b3Assert(0); + printf("Error: received new status but previous status not processed yet"); + } + else + { + args->m_cs->lock(); + args->m_hasStatus = hasNewStatus; + args->m_cs->unlock(); + } + } + } + + } + + } while (args->m_cs->getSharedParam(0) != eUDPRequestTerminate); + } + else + { + args->m_cs->lock(); + args->m_cs->setSharedParam(0, eUDPInitializationFailed); + args->m_cs->unlock(); + } + + + printf("finished\n"); + +} + + + +void* UDPlsMemoryFunc() +{ + //don't create local store memory, just return 0 + return new UDPThreadLocalStorage; +} + + + + + + + +UdpNetworkedPhysicsProcessor::UdpNetworkedPhysicsProcessor(const char* hostName, int port) +{ + m_data = new UdpNetworkedInternalData; + if (hostName) + { + m_data->m_hostName = hostName; + } + m_data->m_port = port; + +} + +UdpNetworkedPhysicsProcessor::~UdpNetworkedPhysicsProcessor() +{ + disconnect(); + delete m_data; +} + +bool UdpNetworkedPhysicsProcessor::processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) +{ + int sz = sizeof(SharedMemoryCommand); + int timeout = 1024 * 1024 * 1024; + + m_data->m_cs->lock(); + m_data->m_clientCmd = clientCmd; + m_data->m_hasCommand = true; + m_data->m_cs->unlock(); + + while (m_data->m_hasCommand && (timeout-- > 0)) + { +// b3Clock::usleep(100); + } + +#if 0 + + timeout = 1024 * 1024 * 1024; + + bool hasStatus = false; + + const SharedMemoryStatus* stat = 0; + while ((!hasStatus) && (timeout-- > 0)) + { + hasStatus = receiveStatus(serverStatusOut, bufferServerToClient, bufferSizeInBytes); + b3Clock::usleep(100); + } + return hasStatus; + +#endif + + return false; +} + +bool UdpNetworkedPhysicsProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) +{ + bool hasStatus = false; + if (m_data->m_hasStatus) + { + hasStatus = true; + serverStatusOut = m_data->m_lastStatus; + int numStreamBytes = m_data->m_stream.size(); + + if (numStreamBytes < bufferSizeInBytes) + { + for (int i = 0; i < numStreamBytes; i++) + { + bufferServerToClient[i] = m_data->m_stream[i]; + } + } + else + { + printf("Error: steam buffer overflow\n"); + } + + m_data->m_cs->lock(); + m_data->m_hasStatus = false; + m_data->m_cs->unlock(); + } + + + return hasStatus; + +} + + +void UdpNetworkedPhysicsProcessor::renderScene() +{ +} + +void UdpNetworkedPhysicsProcessor::physicsDebugDraw(int debugDrawFlags) +{ +} + +void UdpNetworkedPhysicsProcessor::setGuiHelper(struct GUIHelperInterface* guiHelper) +{ +} + +bool UdpNetworkedPhysicsProcessor::isConnected() const +{ + return m_data->m_isConnected; +} + + +bool UdpNetworkedPhysicsProcessor::connect() +{ + if (m_data->m_threadSupport==0) + { + m_data->m_threadSupport = createUDPThreadSupport(1); + + m_data->m_cs = m_data->m_threadSupport->createCriticalSection(); + m_data->m_cs->setSharedParam(0, eUDPIsUnInitialized); + m_data->m_threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*) m_data, 0); + + while (m_data->m_cs->getSharedParam(0) == eUDPIsUnInitialized) + { + b3Clock::usleep(1000); + } + + m_data->m_cs->lock(); + m_data->m_cs->setSharedParam(1, eUDP_ConnectRequest); + m_data->m_cs->unlock(); + + while (m_data->m_cs->getSharedParam(1) == eUDP_ConnectRequest) + { + b3Clock::usleep(1000); + } + + } + + + return true; +} + +void UdpNetworkedPhysicsProcessor::disconnect() +{ + if (m_data->m_threadSupport) + { + m_data->m_cs->lock(); + m_data->m_cs->setSharedParam(0, eUDPRequestTerminate); + m_data->m_cs->unlock(); + + int numActiveThreads = 1; + + while (numActiveThreads) + { + int arg0, arg1; + if (m_data->m_threadSupport->isTaskCompleted(&arg0, &arg1, 0)) + { + numActiveThreads--; + printf("numActiveThreads = %d\n", numActiveThreads); + } + else + { + b3Clock::usleep(1000); + } + }; + + printf("stopping threads\n"); + + delete m_data->m_threadSupport; + m_data->m_threadSupport = 0; + } + + + +} + + + + + diff --git a/examples/SharedMemory/PhysicsClientUDP.h b/examples/SharedMemory/PhysicsClientUDP.h new file mode 100644 index 000000000..27b94fd48 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientUDP.h @@ -0,0 +1,37 @@ +#ifndef PHYSICS_CLIENT_UDP_H +#define PHYSICS_CLIENT_UDP_H + +#include "PhysicsDirect.h" +#include "PhysicsServerCommandProcessor.h" + +class UdpNetworkedPhysicsProcessor : public PhysicsCommandProcessorInterface +{ + + struct UdpNetworkedInternalData* m_data; + +public: + UdpNetworkedPhysicsProcessor(const char* hostName, int port); + + virtual ~UdpNetworkedPhysicsProcessor(); + + virtual bool connect(); + + virtual void disconnect(); + + virtual bool isConnected() const; + + virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); + + virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); + + virtual void renderScene(); + + virtual void physicsDebugDraw(int debugDrawFlags); + + virtual void setGuiHelper(struct GUIHelperInterface* guiHelper); + +}; + + +#endif //PHYSICS_CLIENT_UDP_H + diff --git a/examples/SharedMemory/PhysicsClientUDP_C_API.cpp b/examples/SharedMemory/PhysicsClientUDP_C_API.cpp new file mode 100644 index 000000000..f48fdedb8 --- /dev/null +++ b/examples/SharedMemory/PhysicsClientUDP_C_API.cpp @@ -0,0 +1,21 @@ + +#include "PhysicsClientUDP_C_API.h" +#include "PhysicsClientUDP.h" +#include "PhysicsDirect.h" +#include + +//think more about naming. The b3ConnectPhysicsLoopback +b3PhysicsClientHandle b3ConnectPhysicsUDP(const char* hostName, int port) +{ + + UdpNetworkedPhysicsProcessor* udp = new UdpNetworkedPhysicsProcessor(hostName, port); + + PhysicsDirect* direct = new PhysicsDirect(udp); + + bool connected = direct->connect(); + printf("direct!\n"); + return (b3PhysicsClientHandle)direct; +} + + + diff --git a/examples/SharedMemory/PhysicsClientUDP_C_API.h b/examples/SharedMemory/PhysicsClientUDP_C_API.h new file mode 100644 index 000000000..fdb97bcab --- /dev/null +++ b/examples/SharedMemory/PhysicsClientUDP_C_API.h @@ -0,0 +1,19 @@ +#ifndef PHYSICS_CLIENT_UDP_C_API_H +#define PHYSICS_CLIENT_UDP_C_API_H + +#include "PhysicsClientC_API.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + ///send physics commands using UDP networking + b3PhysicsClientHandle b3ConnectPhysicsUDP(const char* hostName, int port); + + +#ifdef __cplusplus +} +#endif + +#endif //PHYSICS_CLIENT_UDP_C_API_H diff --git a/examples/SharedMemory/PhysicsCommandProcessorInterface.h b/examples/SharedMemory/PhysicsCommandProcessorInterface.h new file mode 100644 index 000000000..39b5f36d5 --- /dev/null +++ b/examples/SharedMemory/PhysicsCommandProcessorInterface.h @@ -0,0 +1,27 @@ +#ifndef PHYSICS_COMMAND_PROCESSOR_INTERFACE_H +#define PHYSICS_COMMAND_PROCESSOR_INTERFACE_H + +class PhysicsCommandProcessorInterface +{ + +public: + virtual ~PhysicsCommandProcessorInterface() {} + + virtual bool connect()=0; + + virtual void disconnect() = 0; + + virtual bool isConnected() const = 0; + + virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) = 0; + + virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) = 0; + + virtual void renderScene() = 0; + virtual void physicsDebugDraw(int debugDrawFlags) = 0; + virtual void setGuiHelper(struct GUIHelperInterface* guiHelper) = 0; + + +}; + +#endif //PHYSICS_COMMAND_PROCESSOR_INTERFACE_H diff --git a/examples/SharedMemory/PhysicsDirect.cpp b/examples/SharedMemory/PhysicsDirect.cpp index 65c1beb13..8b21eeaa3 100644 --- a/examples/SharedMemory/PhysicsDirect.cpp +++ b/examples/SharedMemory/PhysicsDirect.cpp @@ -3,7 +3,9 @@ #include "PhysicsClientSharedMemory.h" #include "../CommonInterfaces/CommonGUIHelperInterface.h" #include "SharedMemoryCommands.h" -#include "PhysicsServerCommandProcessor.h" +#include "PhysicsCommandProcessorInterface.h" + + #include "LinearMath/btHashMap.h" #include "LinearMath/btAlignedObjectArray.h" #include "../../Extras/Serialize/BulletFileLoader/btBulletFile.h" @@ -44,26 +46,34 @@ struct PhysicsDirectInternalData btAlignedObjectArray m_cachedVisualShapes; - PhysicsServerCommandProcessor* m_commandProcessor; + PhysicsCommandProcessorInterface* m_commandProcessor; + bool m_ownsCommandProcessor; PhysicsDirectInternalData() :m_hasStatus(false), - m_verboseOutput(false) + m_verboseOutput(false), + m_ownsCommandProcessor(false) { } }; -PhysicsDirect::PhysicsDirect() +PhysicsDirect::PhysicsDirect(PhysicsCommandProcessorInterface* physSdk) { m_data = new PhysicsDirectInternalData; - m_data->m_commandProcessor = new PhysicsServerCommandProcessor; - - + m_data->m_commandProcessor = physSdk; + m_data->m_ownsCommandProcessor = false; } PhysicsDirect::~PhysicsDirect() { - delete m_data->m_commandProcessor; + if (m_data->m_commandProcessor->isConnected()) + { + m_data->m_commandProcessor->disconnect(); + } + if (m_data->m_ownsCommandProcessor) + { + delete m_data->m_commandProcessor; + } delete m_data; } @@ -71,23 +81,26 @@ PhysicsDirect::~PhysicsDirect() // return true if connection succesfull, can also check 'isConnected' bool PhysicsDirect::connect() { + bool connected = m_data->m_commandProcessor->connect(); m_data->m_commandProcessor->setGuiHelper(&m_data->m_noGfx); - - return true; + return connected; } // return true if connection succesfull, can also check 'isConnected' bool PhysicsDirect::connect(struct GUIHelperInterface* guiHelper) { + bool connected = m_data->m_commandProcessor->connect(); + m_data->m_commandProcessor->setGuiHelper(guiHelper); - return true; + return connected; } void PhysicsDirect::renderScene() { m_data->m_commandProcessor->renderScene(); } + void PhysicsDirect::debugDraw(int debugDrawMode) { m_data->m_commandProcessor->physicsDebugDraw(debugDrawMode); @@ -96,21 +109,31 @@ void PhysicsDirect::debugDraw(int debugDrawMode) ////todo: rename to 'disconnect' void PhysicsDirect::disconnectSharedMemory() { + m_data->m_commandProcessor->disconnect(); m_data->m_commandProcessor->setGuiHelper(0); } bool PhysicsDirect::isConnected() const { - return true; + return m_data->m_commandProcessor->isConnected(); } // return non-null if there is a status, nullptr otherwise const SharedMemoryStatus* PhysicsDirect::processServerStatus() { + + if (!m_data->m_hasStatus) + { + m_data->m_hasStatus = m_data->m_commandProcessor->receiveStatus(m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + } + SharedMemoryStatus* stat = 0; if (m_data->m_hasStatus) { stat = &m_data->m_serverStatus; + + postProcessStatus(m_data->m_serverStatus); + m_data->m_hasStatus = false; } return stat; @@ -136,7 +159,19 @@ bool PhysicsDirect::processDebugLines(const struct SharedMemoryCommand& orgComma { bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + + int timeout = 1024 * 1024 * 1024; + while ((!hasStatus) && (timeout-- > 0)) + { + const SharedMemoryStatus* stat = processServerStatus(); + if (stat) + { + hasStatus = true; + } + } + m_data->m_hasStatus = hasStatus; + if (hasStatus) { btAssert(m_data->m_serverStatus.m_type == CMD_DEBUG_LINES_COMPLETED); @@ -184,6 +219,8 @@ bool PhysicsDirect::processDebugLines(const struct SharedMemoryCommand& orgComma if (serverCmd.m_sendDebugLinesArgs.m_numRemainingDebugLines > 0) { + m_data->m_hasStatus = false; + command.m_type = CMD_REQUEST_DEBUG_LINES; command.m_requestDebugLinesArguments.m_startingLineIndex = serverCmd.m_sendDebugLinesArgs.m_numDebugLines + @@ -204,6 +241,17 @@ bool PhysicsDirect::processVisualShapeData(const struct SharedMemoryCommand& org do { bool hasStatus = m_data->m_commandProcessor->processCommand(command, m_data->m_serverStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + + int timeout = 1024 * 1024 * 1024; + while ((!hasStatus) && (timeout-- > 0)) + { + const SharedMemoryStatus* stat = processServerStatus(); + if (stat) + { + hasStatus = true; + } + } + m_data->m_hasStatus = hasStatus; if (hasStatus) { @@ -223,6 +271,8 @@ bool PhysicsDirect::processVisualShapeData(const struct SharedMemoryCommand& org if (serverCmd.m_sendVisualShapeArgs.m_numRemainingVisualShapes >0 && serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied) { + m_data->m_hasStatus = false; + command.m_type = CMD_REQUEST_VISUAL_SHAPE_INFO; command.m_requestVisualShapeDataArguments.m_startingVisualShapeIndex = serverCmd.m_sendVisualShapeArgs.m_startingVisualShapeIndex + serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied; command.m_requestVisualShapeDataArguments.m_bodyUniqueId = serverCmd.m_sendVisualShapeArgs.m_bodyUniqueId; @@ -243,7 +293,19 @@ bool PhysicsDirect::processContactPointData(const struct SharedMemoryCommand& or do { bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - m_data->m_hasStatus = hasStatus; + + int timeout = 1024 * 1024 * 1024; + while ((!hasStatus) && (timeout-- > 0)) + { + const SharedMemoryStatus* stat = processServerStatus(); + if (stat) + { + hasStatus = true; + } + } + + + m_data->m_hasStatus = hasStatus; if (hasStatus) { if (m_data->m_verboseOutput) @@ -264,7 +326,10 @@ bool PhysicsDirect::processContactPointData(const struct SharedMemoryCommand& or if (serverCmd.m_sendContactPointArgs.m_numRemainingContactPoints>0 && serverCmd.m_sendContactPointArgs.m_numContactPointsCopied) { - command.m_type = CMD_REQUEST_CONTACT_POINT_INFORMATION; + + m_data->m_hasStatus = false; + + command.m_type = CMD_REQUEST_CONTACT_POINT_INFORMATION; command.m_requestContactPointArguments.m_startingContactPointIndex = serverCmd.m_sendContactPointArgs.m_startingContactPointIndex+serverCmd.m_sendContactPointArgs.m_numContactPointsCopied; command.m_requestContactPointArguments.m_objectAIndexFilter = -1; command.m_requestContactPointArguments.m_objectBIndexFilter = -1; @@ -289,6 +354,18 @@ bool PhysicsDirect::processCamera(const struct SharedMemoryCommand& orgCommand) { bool hasStatus = m_data->m_commandProcessor->processCommand(command,m_data->m_serverStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + + int timeout = 1024 * 1024 * 1024; + while ((!hasStatus) && (timeout-- > 0)) + { + const SharedMemoryStatus* stat = processServerStatus(); + if (stat) + { + hasStatus = true; + } + } + + m_data->m_hasStatus = hasStatus; if (hasStatus) { @@ -340,6 +417,7 @@ bool PhysicsDirect::processCamera(const struct SharedMemoryCommand& orgCommand) if (serverCmd.m_sendPixelDataArguments.m_numRemainingPixels > 0 && serverCmd.m_sendPixelDataArguments.m_numPixelsCopied) { + m_data->m_hasStatus = false; // continue requesting remaining pixels command.m_type = CMD_REQUEST_CAMERA_IMAGE_DATA; @@ -365,7 +443,7 @@ void PhysicsDirect::processBodyJointInfo(int bodyUniqueId, const SharedMemorySta { bParse::btBulletFile bf( &m_data->m_bulletStreamDataServerToClient[0], - serverCmd.m_dataStreamArguments.m_streamChunkLength); + serverCmd.m_numDataStreamBytes); bf.setFileDNAisMemoryDNA(); bf.parse(false); @@ -402,6 +480,87 @@ void PhysicsDirect::processBodyJointInfo(int bodyUniqueId, const SharedMemorySta } } +void PhysicsDirect::postProcessStatus(const struct SharedMemoryStatus& serverCmd) +{ + switch (serverCmd.m_type) + { + case CMD_RESET_SIMULATION_COMPLETED: + { + m_data->m_debugLinesFrom.clear(); + m_data->m_debugLinesTo.clear(); + m_data->m_debugLinesColor.clear(); + for (int i = 0; im_bodyJointMap.size(); i++) + { + BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap.getAtIndex(i); + if (bodyJointsPtr && *bodyJointsPtr) + { + BodyJointInfoCache2* bodyJoints = *bodyJointsPtr; + for (int j = 0; jm_jointInfo.size(); j++) { + if (bodyJoints->m_jointInfo[j].m_jointName) + { + free(bodyJoints->m_jointInfo[j].m_jointName); + } + if (bodyJoints->m_jointInfo[j].m_linkName) + { + free(bodyJoints->m_jointInfo[j].m_linkName); + } + } + delete (*bodyJointsPtr); + } + } + m_data->m_bodyJointMap.clear(); + + break; + } + case CMD_SDF_LOADING_COMPLETED: + { + //we'll stream further info from the physics server + //so serverCmd will be invalid, make a copy + + + int numBodies = serverCmd.m_sdfLoadedArgs.m_numBodies; + for (int i = 0; im_commandProcessor->processCommand(infoRequestCommand, infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + + + int timeout = 1024 * 1024 * 1024; + while ((!hasStatus) && (timeout-- > 0)) + { + hasStatus = m_data->m_commandProcessor->receiveStatus(infoStatus, &m_data->m_bulletStreamDataServerToClient[0], SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + } + + if (hasStatus) + { + processBodyJointInfo(bodyUniqueId, infoStatus); + } + } + break; + } + case CMD_URDF_LOADING_COMPLETED: + { + + if (serverCmd.m_numDataStreamBytes > 0) + { + int bodyIndex = serverCmd.m_dataStreamArguments.m_bodyUniqueId; + processBodyJointInfo(bodyIndex, serverCmd); + } + break; + } + + default: + { + // b3Error("Unknown server status type"); + } + }; + + +} bool PhysicsDirect::submitClientCommand(const struct SharedMemoryCommand& command) { if (command.m_type==CMD_REQUEST_DEBUG_LINES) @@ -427,78 +586,7 @@ bool PhysicsDirect::submitClientCommand(const struct SharedMemoryCommand& comman m_data->m_hasStatus = hasStatus; if (hasStatus) { - const SharedMemoryStatus& serverCmd = m_data->m_serverStatus; - - switch (m_data->m_serverStatus.m_type) - { - case CMD_RESET_SIMULATION_COMPLETED: - { - m_data->m_debugLinesFrom.clear(); - m_data->m_debugLinesTo.clear(); - m_data->m_debugLinesColor.clear(); - for (int i=0;im_bodyJointMap.size();i++) - { - BodyJointInfoCache2** bodyJointsPtr = m_data->m_bodyJointMap.getAtIndex(i); - if (bodyJointsPtr && *bodyJointsPtr) - { - BodyJointInfoCache2* bodyJoints = *bodyJointsPtr; - for (int j=0;jm_jointInfo.size();j++) { - if (bodyJoints->m_jointInfo[j].m_jointName) - { - free(bodyJoints->m_jointInfo[j].m_jointName); - } - if (bodyJoints->m_jointInfo[j].m_linkName) - { - free(bodyJoints->m_jointInfo[j].m_linkName); - } - } - delete (*bodyJointsPtr); - } - } - m_data->m_bodyJointMap.clear(); - - break; - } - case CMD_SDF_LOADING_COMPLETED: - { - //we'll stream further info from the physics server - //so serverCmd will be invalid, make a copy - - - int numBodies = serverCmd.m_sdfLoadedArgs.m_numBodies; - for (int i=0;im_commandProcessor->processCommand(infoRequestCommand,infoStatus,&m_data->m_bulletStreamDataServerToClient[0],SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); - if (hasStatus) - { - processBodyJointInfo(bodyUniqueId, infoStatus); - } - } - break; - } - case CMD_URDF_LOADING_COMPLETED: - { - - if (serverCmd.m_dataStreamArguments.m_streamChunkLength > 0) - { - int bodyIndex = serverCmd.m_dataStreamArguments.m_bodyUniqueId; - processBodyJointInfo(bodyIndex,serverCmd); - } - break; - } - - default: - { - // b3Error("Unknown server status type"); - } - }; - - + postProcessStatus(m_data->m_serverStatus); } return hasStatus; } @@ -549,7 +637,7 @@ bool PhysicsDirect::getJointInfo(int bodyIndex, int jointIndex, struct b3JointIn if (bodyJointsPtr && *bodyJointsPtr) { BodyJointInfoCache2* bodyJoints = *bodyJointsPtr; - if (jointIndex < bodyJoints->m_jointInfo.size()) + if ((jointIndex >=0) && (jointIndex < bodyJoints->m_jointInfo.size())) { info = bodyJoints->m_jointInfo[jointIndex]; return true; diff --git a/examples/SharedMemory/PhysicsDirect.h b/examples/SharedMemory/PhysicsDirect.h index 2252da3c3..968f8f560 100644 --- a/examples/SharedMemory/PhysicsDirect.h +++ b/examples/SharedMemory/PhysicsDirect.h @@ -7,9 +7,6 @@ #include "PhysicsClient.h" #include "LinearMath/btVector3.h" -///todo: the PhysicsClient API was designed with shared memory in mind, -///now it become more general we need to move out the shared memory specifics away -///for example naming [disconnectSharedMemory -> disconnect] [ move setSharedMemoryKey to shared memory specific subclass ] ///PhysicsDirect executes the commands directly, without transporting them or having a separate server executing commands class PhysicsDirect : public PhysicsClient { @@ -27,9 +24,11 @@ protected: void processBodyJointInfo(int bodyUniqueId, const struct SharedMemoryStatus& serverCmd); + void postProcessStatus(const struct SharedMemoryStatus& serverCmd); + public: - PhysicsDirect(); + PhysicsDirect(class PhysicsCommandProcessorInterface* physSdk); virtual ~PhysicsDirect(); diff --git a/examples/SharedMemory/PhysicsDirectC_API.cpp b/examples/SharedMemory/PhysicsDirectC_API.cpp index e5e73b203..61ceef26f 100644 --- a/examples/SharedMemory/PhysicsDirectC_API.cpp +++ b/examples/SharedMemory/PhysicsDirectC_API.cpp @@ -2,13 +2,21 @@ #include "PhysicsDirect.h" +#include "PhysicsServerCommandProcessor.h" + //think more about naming. The b3ConnectPhysicsLoopback b3PhysicsClientHandle b3ConnectPhysicsDirect() { - PhysicsDirect* direct = new PhysicsDirect(); + PhysicsServerCommandProcessor* sdk = new PhysicsServerCommandProcessor; + + PhysicsDirect* direct = new PhysicsDirect(sdk); bool connected = direct->connect(); return (b3PhysicsClientHandle )direct; } + + +// + diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp index 667179239..278f0b7ee 100644 --- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp +++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp @@ -1187,6 +1187,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm //catch uninitialized cases serverStatusOut.m_type = CMD_INVALID_STATUS; + serverStatusOut.m_numDataStreamBytes = 0; + serverStatusOut.m_dataStream = 0; //consume the command switch (clientCmd.m_type) @@ -1244,7 +1246,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm } //9 floats per line: 3 floats for 'from', 3 floats for 'to' and 3 floats for 'color' - int maxNumLines = bufferSizeInBytes/(sizeof(float)*9)-1; + int bytesPerLine = (sizeof(float) * 9); + int maxNumLines = bufferSizeInBytes/bytesPerLine-1; if (startingLineIndex >m_data->m_remoteDebugDrawer->m_lines2.size()) { b3Warning("m_startingLineIndex exceeds total number of debug lines"); @@ -1277,7 +1280,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm } serverStatusOut.m_type = CMD_DEBUG_LINES_COMPLETED; - + serverStatusOut.m_numDataStreamBytes = numLines * bytesPerLine; serverStatusOut.m_sendDebugLinesArgs.m_numDebugLines = numLines; serverStatusOut.m_sendDebugLinesArgs.m_startingLineIndex = startingLineIndex; serverStatusOut.m_sendDebugLinesArgs.m_numRemainingDebugLines = m_data->m_remoteDebugDrawer->m_lines2.size()-(startingLineIndex+numLines); @@ -1327,6 +1330,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm float* depthBuffer = (float*)(bufferServerToClient+numRequestedPixels*4); int* segmentationMaskBuffer = (int*)(bufferServerToClient+numRequestedPixels*8); + serverStatusOut.m_numDataStreamBytes = numRequestedPixels * totalBytesPerPixel; + if ((clientCmd.m_updateFlags & ER_BULLET_HARDWARE_OPENGL)!=0) { m_data->m_guiHelper->copyCameraImageData(clientCmd.m_requestPixelDataArguments.m_viewMatrix, @@ -1368,6 +1373,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm } serverStatusOut.m_type = CMD_CAMERA_IMAGE_COMPLETED; + serverStatusOut.m_sendPixelDataArguments.m_numPixelsCopied = numPixelsCopied; serverStatusOut.m_sendPixelDataArguments.m_numRemainingPixels = numRemainingPixels - numPixelsCopied; serverStatusOut.m_sendPixelDataArguments.m_startingPixelIndex = startPixelIndex; @@ -1386,7 +1392,8 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm serverStatusOut.m_type = CMD_BODY_INFO_COMPLETED; serverStatusOut.m_dataStreamArguments.m_bodyUniqueId = sdfInfoArgs.m_bodyUniqueId; - serverStatusOut.m_dataStreamArguments.m_streamChunkLength = streamSizeInBytes; + serverStatusOut.m_numDataStreamBytes = streamSizeInBytes; + hasStatus = true; break; } @@ -1606,11 +1613,11 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm m_data->m_guiHelper->autogenerateGraphicsObjects(this->m_data->m_dynamicsWorld); serverStatusOut.m_type = CMD_URDF_LOADING_COMPLETED; - serverStatusOut.m_dataStreamArguments.m_streamChunkLength = 0; + if (m_data->m_urdfLinkNameMapper.size()) { - serverStatusOut.m_dataStreamArguments.m_streamChunkLength = m_data->m_urdfLinkNameMapper.at(m_data->m_urdfLinkNameMapper.size()-1)->m_memSerializer->getCurrentBufferSize(); + serverStatusOut.m_numDataStreamBytes = m_data->m_urdfLinkNameMapper.at(m_data->m_urdfLinkNameMapper.size()-1)->m_memSerializer->getCurrentBufferSize(); } serverStatusOut.m_dataStreamArguments.m_bodyUniqueId = bodyUniqueId; hasStatus = true; @@ -2583,7 +2590,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm serverCmd.m_sendContactPointArgs.m_startingContactPointIndex = clientCmd.m_requestContactPointArguments.m_startingContactPointIndex; serverCmd.m_sendContactPointArgs.m_numRemainingContactPoints = numContactPoints - clientCmd.m_requestContactPointArguments.m_startingContactPointIndex - serverCmd.m_sendContactPointArgs.m_numContactPointsCopied; - + serverCmd.m_numDataStreamBytes = totalBytesPerContact * serverCmd.m_sendContactPointArgs.m_numContactPointsCopied; serverCmd.m_type = CMD_CONTACT_POINT_INFORMATION_COMPLETED; //CMD_CONTACT_POINT_INFORMATION_FAILED, hasStatus = true; break; @@ -3006,7 +3013,7 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied = 1; serverCmd.m_sendVisualShapeArgs.m_startingVisualShapeIndex = clientCmd.m_requestVisualShapeDataArguments.m_startingVisualShapeIndex; serverCmd.m_sendVisualShapeArgs.m_bodyUniqueId = clientCmd.m_requestVisualShapeDataArguments.m_bodyUniqueId; - + serverCmd.m_numDataStreamBytes = sizeof(b3VisualShapeData)*serverCmd.m_sendVisualShapeArgs.m_numVisualShapesCopied; serverCmd.m_type =CMD_VISUAL_SHAPE_INFO_COMPLETED; hasStatus = true; break; diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.h b/examples/SharedMemory/PhysicsServerCommandProcessor.h index 2814d11dd..e271cdff6 100644 --- a/examples/SharedMemory/PhysicsServerCommandProcessor.h +++ b/examples/SharedMemory/PhysicsServerCommandProcessor.h @@ -3,6 +3,8 @@ #include "LinearMath/btVector3.h" +#include "PhysicsCommandProcessorInterface.h" + struct SharedMemLines { btVector3 m_from; @@ -10,8 +12,10 @@ struct SharedMemLines btVector3 m_color; }; + + ///todo: naming. Perhaps PhysicsSdkCommandprocessor? -class PhysicsServerCommandProcessor +class PhysicsServerCommandProcessor : public PhysicsCommandProcessorInterface { struct PhysicsServerCommandProcessorInternalData* m_data; @@ -22,15 +26,15 @@ class PhysicsServerCommandProcessor protected: - - bool loadSdf(const char* fileName, char* bufferServerToClient, int bufferSizeInBytes, bool useMultiBody); + + bool loadSdf(const char* fileName, char* bufferServerToClient, int bufferSizeInBytes, bool useMultiBody); bool loadUrdf(const char* fileName, const class btVector3& pos, const class btQuaternion& orn, - bool useMultiBody, bool useFixedBase, int* bodyUniqueIdPtr, char* bufferServerToClient, int bufferSizeInBytes); + bool useMultiBody, bool useFixedBase, int* bodyUniqueIdPtr, char* bufferServerToClient, int bufferSizeInBytes); bool supportsJointMotor(class btMultiBody* body, int linkIndex); - + int createBodyInfoStream(int bodyUniqueId, char* bufferServerToClient, int bufferSizeInBytes); void deleteCachedInverseDynamicsBodies(); @@ -39,12 +43,30 @@ public: virtual ~PhysicsServerCommandProcessor(); void createJointMotors(class btMultiBody* body); - + virtual void createEmptyDynamicsWorld(); virtual void deleteDynamicsWorld(); - - virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes ); + virtual bool connect() + { + return true; + }; + + virtual void disconnect() {} + + virtual bool isConnected() const + { + return true; + } + + + + virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); + + virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) + { + return false; + }; virtual void renderScene(); virtual void physicsDebugDraw(int debugDrawFlags); diff --git a/examples/SharedMemory/SharedMemoryCommandProcessor.cpp b/examples/SharedMemory/SharedMemoryCommandProcessor.cpp new file mode 100644 index 000000000..406b9ae4f --- /dev/null +++ b/examples/SharedMemory/SharedMemoryCommandProcessor.cpp @@ -0,0 +1,216 @@ +#include "SharedMemoryCommandProcessor.h" + +#include "PosixSharedMemory.h" +#include "Win32SharedMemory.h" +#include "Bullet3Common/b3Logging.h" +#include "Bullet3Common/b3Scalar.h" + +#include "SharedMemoryBlock.h" + + +struct SharedMemoryCommandProcessorInternalData +{ + int m_sharedMemoryKey; + bool m_isConnected; + SharedMemoryInterface* m_sharedMemory; + bool m_ownsSharedMemory; + bool m_verboseOutput; + bool m_waitingForServer; + SharedMemoryStatus m_lastServerStatus; + SharedMemoryBlock* m_testBlock1; + + + SharedMemoryCommandProcessorInternalData() + :m_sharedMemoryKey(SHARED_MEMORY_KEY), + m_isConnected(false), + m_sharedMemory(0), + m_ownsSharedMemory(false), + m_verboseOutput(false), + m_waitingForServer(false), + m_testBlock1(0) + { + + } +}; + +SharedMemoryCommandProcessor::SharedMemoryCommandProcessor() +{ + m_data = new SharedMemoryCommandProcessorInternalData; + m_data->m_sharedMemoryKey = SHARED_MEMORY_KEY; +#ifdef _WIN32 + m_data->m_sharedMemory = new Win32SharedMemoryClient(); +#else + m_data->m_sharedMemory = new PosixSharedMemory(); +#endif + m_data->m_ownsSharedMemory = true; + + +} + +SharedMemoryCommandProcessor::~SharedMemoryCommandProcessor() +{ + if (m_data->m_isConnected) + { + disconnect(); + } + if (m_data->m_ownsSharedMemory) + { + delete m_data->m_sharedMemory; + } + delete m_data; + +} + +bool SharedMemoryCommandProcessor::connect() +{ + + if (m_data->m_isConnected) + return true; + + bool allowCreation = false; + m_data->m_testBlock1 = (SharedMemoryBlock*)m_data->m_sharedMemory->allocateSharedMemory( + m_data->m_sharedMemoryKey, SHARED_MEMORY_SIZE, allowCreation); + + if (m_data->m_testBlock1) { + if (m_data->m_testBlock1->m_magicId != SHARED_MEMORY_MAGIC_NUMBER) { + b3Error("Error: please start server before client\n"); + m_data->m_sharedMemory->releaseSharedMemory(m_data->m_sharedMemoryKey, + SHARED_MEMORY_SIZE); + m_data->m_testBlock1 = 0; + return false; + } + else { + if (m_data->m_verboseOutput) { + b3Printf("Connected to existing shared memory, status OK.\n"); + } + m_data->m_isConnected = true; + } + } + else { + b3Error("Cannot connect to shared memory"); + return false; + } + return true; + +} + +void SharedMemoryCommandProcessor::disconnect() +{ + if (m_data->m_isConnected && m_data->m_sharedMemory) + { + m_data->m_sharedMemory->releaseSharedMemory(m_data->m_sharedMemoryKey, SHARED_MEMORY_SIZE); + } + m_data->m_isConnected = false; + +} + +bool SharedMemoryCommandProcessor::isConnected() const +{ + return m_data->m_isConnected; +} + + +bool SharedMemoryCommandProcessor::processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) +{ + if (!m_data->m_waitingForServer) { + if (&m_data->m_testBlock1->m_clientCommands[0] != &clientCmd) { + m_data->m_testBlock1->m_clientCommands[0] = clientCmd; + } + m_data->m_testBlock1->m_numClientCommands++; + m_data->m_waitingForServer = true; + } + + return false; +} + +bool SharedMemoryCommandProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes) +{ + SharedMemoryStatus* stat = 0; + + m_data->m_lastServerStatus.m_dataStream = 0; + m_data->m_lastServerStatus.m_numDataStreamBytes = 0; + + if (!m_data->m_testBlock1) + { + //m_data->m_lastServerStatus.m_type = CMD_SHARED_MEMORY_NOT_INITIALIZED; + //return &m_data->m_lastServerStatus; + //serverStatusOut = m_data->m_lastServerStatus; + return false; + } + + if (!m_data->m_waitingForServer) { + return false; + } + + if (m_data->m_testBlock1->m_magicId != SHARED_MEMORY_MAGIC_NUMBER) + { + //m_data->m_lastServerStatus.m_type = CMD_SHARED_MEMORY_NOT_INITIALIZED; + //return &m_data->m_lastServerStatus; + return false; + } + + if (m_data->m_testBlock1->m_numServerCommands > + m_data->m_testBlock1->m_numProcessedServerCommands) + { + b3Assert(m_data->m_testBlock1->m_numServerCommands == + m_data->m_testBlock1->m_numProcessedServerCommands + 1); + + const SharedMemoryStatus& serverCmd = m_data->m_testBlock1->m_serverCommands[0]; + m_data->m_lastServerStatus = serverCmd; + m_data->m_lastServerStatus.m_dataStream = m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor; + + for (int i = 0; i < m_data->m_lastServerStatus.m_numDataStreamBytes; i++) + { + bufferServerToClient[i] = m_data->m_testBlock1->m_bulletStreamDataServerToClientRefactor[i]; + } + + m_data->m_testBlock1->m_numProcessedServerCommands++; + // we don't have more than 1 command outstanding (in total, either server or client) + b3Assert(m_data->m_testBlock1->m_numProcessedServerCommands == + m_data->m_testBlock1->m_numServerCommands); + + if (m_data->m_testBlock1->m_numServerCommands == + m_data->m_testBlock1->m_numProcessedServerCommands) { + m_data->m_waitingForServer = false; + } + else { + m_data->m_waitingForServer = true; + } + + serverStatusOut = m_data->m_lastServerStatus; + + return true; + } + return false; +} + +void SharedMemoryCommandProcessor::renderScene() +{ +} + +void SharedMemoryCommandProcessor::physicsDebugDraw(int debugDrawFlags) +{ +} + +void SharedMemoryCommandProcessor::setGuiHelper(struct GUIHelperInterface* guiHelper) +{ +} + +void SharedMemoryCommandProcessor::setSharedMemoryInterface(class SharedMemoryInterface* sharedMem) +{ + if (m_data->m_sharedMemory && m_data->m_ownsSharedMemory) + { + delete m_data->m_sharedMemory; + } + m_data->m_ownsSharedMemory = false; + m_data->m_sharedMemory = sharedMem; + +} + + +void SharedMemoryCommandProcessor::setSharedMemoryKey(int key) +{ + m_data->m_sharedMemoryKey = key; +} + + diff --git a/examples/SharedMemory/SharedMemoryCommandProcessor.h b/examples/SharedMemory/SharedMemoryCommandProcessor.h new file mode 100644 index 000000000..bec9e614f --- /dev/null +++ b/examples/SharedMemory/SharedMemoryCommandProcessor.h @@ -0,0 +1,37 @@ +#ifndef SHARED_MEMORY_COMMAND_PROCESSOR_H +#define SHARED_MEMORY_COMMAND_PROCESSOR_H + +#include "PhysicsCommandProcessorInterface.h" + +class SharedMemoryCommandProcessor : public PhysicsCommandProcessorInterface +{ + + struct SharedMemoryCommandProcessorInternalData* m_data; + +public: + SharedMemoryCommandProcessor(); + + virtual ~SharedMemoryCommandProcessor(); + + virtual bool connect(); + + virtual void disconnect(); + + virtual bool isConnected() const; + + virtual bool processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); + + virtual bool receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes); + + virtual void renderScene(); + virtual void physicsDebugDraw(int debugDrawFlags); + virtual void setGuiHelper(struct GUIHelperInterface* guiHelper); + + void setSharedMemoryInterface(class SharedMemoryInterface* sharedMem); + void setSharedMemoryKey(int key); + + +}; + +#endif //SHARED_MEMORY_COMMAND_PROCESSOR_H + diff --git a/examples/SharedMemory/SharedMemoryCommands.h b/examples/SharedMemory/SharedMemoryCommands.h index 0b7f325f8..3d58789bc 100644 --- a/examples/SharedMemory/SharedMemoryCommands.h +++ b/examples/SharedMemory/SharedMemoryCommands.h @@ -90,7 +90,6 @@ struct UrdfArgs struct BulletDataStreamArgs { char m_bulletFileName[MAX_FILENAME_LENGTH]; - int m_streamChunkLength; int m_bodyUniqueId; }; @@ -508,6 +507,10 @@ struct SharedMemoryStatus smUint64_t m_timeStamp; int m_sequenceNumber; + //m_streamBytes is only for internal purposes + int m_numDataStreamBytes; + char* m_dataStream; + union { struct BulletDataStreamArgs m_dataStreamArguments; diff --git a/examples/SharedMemory/premake4.lua b/examples/SharedMemory/premake4.lua index 2215cfbe0..2bbf3b569 100644 --- a/examples/SharedMemory/premake4.lua +++ b/examples/SharedMemory/premake4.lua @@ -42,6 +42,14 @@ myfiles = "PhysicsLoopBack.h", "PhysicsLoopBackC_API.cpp", "PhysicsLoopBackC_API.h", + "PhysicsClientSharedMemory_C_API.cpp", + "PhysicsClientSharedMemory_C_API.h", + "PhysicsClientSharedMemory2_C_API.cpp", + "PhysicsClientSharedMemory2_C_API.h", + "PhysicsClientSharedMemory2.cpp", + "PhysicsClientSharedMemory2.h", + "SharedMemoryCommandProcessor.cpp", + "SharedMemoryCommandProcessor.h", "PhysicsServerCommandProcessor.cpp", "PhysicsServerCommandProcessor.h", "TinyRendererVisualShapeConverter.cpp", @@ -288,4 +296,7 @@ if os.is("Windows") then end -end \ No newline at end of file +end + + +include "udp" diff --git a/examples/SharedMemory/udp/main.cpp b/examples/SharedMemory/udp/main.cpp new file mode 100644 index 000000000..d653b34fd --- /dev/null +++ b/examples/SharedMemory/udp/main.cpp @@ -0,0 +1,187 @@ +/* server.cpp */ +#include +#include +#include "SharedMemoryCommandProcessor.h" +#include "SharedMemoryCommands.h" +#include "Bullet3Common/b3AlignedObjectArray.h" +#include "PhysicsServerCommandProcessor.h" + +void MySerializeInt(unsigned int sz, unsigned char* output) +{ + unsigned int tmp = sz; + output[0] = tmp & 255; + tmp = tmp >> 8; + output[1] = tmp & 255; + tmp = tmp >> 8; + output[2] = tmp & 255; + tmp = tmp >> 8; + output[3] = tmp & 255; +} + + + +int main(int argc, char *argv[]) +{ + unsigned char buf[4]; + + + SharedMemoryCommandProcessor* sm = new SharedMemoryCommandProcessor; + +// PhysicsDirect* sm = new PhysicsDirect(sdk); + + //PhysicsClientSharedMemory* sm = new PhysicsClientSharedMemory(); + + bool isPhysicsClientConnected = sm->connect(); + + if (isPhysicsClientConnected) + { + + ENetAddress address; + ENetHost *server; + ENetEvent event; + int serviceResult; + + puts("Starting server"); + + if (enet_initialize() != 0) + { + puts("Error initialising enet"); + exit(EXIT_FAILURE); + } + + + /* Bind the server to the default localhost. */ + /* A specific host address can be specified by */ + /* enet_address_set_host (& address, "x.x.x.x"); */ + address.host = ENET_HOST_ANY; + /* Bind the server to port 1234. */ + address.port = 1234; + + server = enet_host_create(&address, + 32, /* number of clients */ + 2, /* number of channels */ + 0, /* Any incoming bandwith */ + 0); /* Any outgoing bandwith */ + + if (server == NULL) + { + puts("Could not create server host"); + exit(EXIT_FAILURE); + } + + + while (true) + { + serviceResult = 1; + + /* Keep doing host_service until no events are left */ + while (serviceResult > 0) + { + /* Wait up to 1000 milliseconds for an event. */ + serviceResult = enet_host_service(server, &event, 0); + if (serviceResult > 0) + { + + switch (event.type) + { + case ENET_EVENT_TYPE_CONNECT: + printf("A new client connected from %x:%u.\n", + event.peer->address.host, + event.peer->address.port); + + /* Store any relevant client information here. */ + event.peer->data = (void*)"Client information"; + + break; + + case ENET_EVENT_TYPE_RECEIVE: + printf("A packet of length %u containing '%s' was " + "received from %s on channel %u.\n", + event.packet->dataLength, + event.packet->data, + event.peer->data, + event.channelID); + + if (event.packet->dataLength == sizeof(SharedMemoryCommand)) + { + SharedMemoryCommand* cmdPtr = (SharedMemoryCommand*)event.packet->data; + SharedMemoryStatus serverStatus; + b3AlignedObjectArray buffer; + buffer.resize(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); + + bool hasStatus = sm->processCommand(*cmdPtr,serverStatus, &buffer[0], buffer.size()); + + int timeout = 1024 * 1024 * 1024; + while ((!hasStatus) && (timeout-- > 0)) + { + hasStatus = sm->receiveStatus(serverStatus, &buffer[0], buffer.size()); + + } + printf("buffer.size = %d\n", buffer.size()); + printf("serverStatus.m_numDataStreamBytes = %d\n", serverStatus.m_numDataStreamBytes); + if (hasStatus) + { + //create packetData with [int packetSizeInBytes, status, streamBytes) + unsigned char* statBytes = (unsigned char*)&serverStatus; + b3AlignedObjectArray packetData; + packetData.resize(4 + sizeof(SharedMemoryStatus) + serverStatus.m_numDataStreamBytes); + int sz = packetData.size(); + int curPos = 0; + + MySerializeInt(sz, &packetData[curPos]); + curPos += 4; + for (int i = 0; i < sizeof(SharedMemoryStatus); i++) + { + packetData[i + curPos] = statBytes[i]; + } + curPos += sizeof(SharedMemoryStatus); + + for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++) + { + packetData[i + curPos] = serverStatus.m_dataStream[i]; + } + + ENetPacket *packet = enet_packet_create(&packetData[0], packetData.size() , ENET_PACKET_FLAG_RELIABLE); + //enet_peer_send(peer, 0, packet); + + enet_host_broadcast(server, 0, packet); + } + } + else + { + printf("received packet with unknown contents\n"); + } + + + /* Tell all clients about this message */ + //enet_host_broadcast(server, 0, event.packet); + + break; + + case ENET_EVENT_TYPE_DISCONNECT: + printf("%s disconnected.\n", event.peer->data); + + /* Reset the peer's client information. */ + + event.peer->data = NULL; + + break; + } + } + else if (serviceResult > 0) + { + puts("Error with servicing the server"); + exit(EXIT_FAILURE); + } + } + + } + + enet_host_destroy(server); + enet_deinitialize(); + } + delete sm; + + return 0; + +} diff --git a/examples/SharedMemory/udp/premake4.lua b/examples/SharedMemory/udp/premake4.lua new file mode 100644 index 000000000..852dfc638 --- /dev/null +++ b/examples/SharedMemory/udp/premake4.lua @@ -0,0 +1,46 @@ + +project ("App_PhysicsServerUDP") + + language "C++" + + kind "ConsoleApp" + + includedirs {"../../ThirdPartyLibs/enet/include","../../../src",".."} + + if os.is("Windows") then + defines { "WIN32" } + + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + end + if os.is("MacOSX") then + end + + + links { + "enet", + "BulletFileLoader", + "Bullet3Common", + "LinearMath" + } + + files { + "main.cpp", + "../PhysicsClient.cpp", + "../PhysicsClient.h", + "../PhysicsDirect.cpp", + "../PhysicsDirect.h", + "../PhysicsCommandProcessorInterface.h", + "../SharedMemoryCommandProcessor.cpp", + "../SharedMemoryCommandProcessor.h", + "../PhysicsClientC_API.cpp", + "../PhysicsClientC_API.h", + "../Win32SharedMemory.cpp", + "../Win32SharedMemory.h", + "../PosixSharedMemory.cpp", + "../PosixSharedMemory.h", + "../../Utils/b3ResourcePath.cpp", + "../../Utils/b3ResourcePath.h", + } + diff --git a/examples/StandaloneMain/hellovr_opengl_main.cpp b/examples/StandaloneMain/hellovr_opengl_main.cpp index 89b8cfe29..52b1574f3 100644 --- a/examples/StandaloneMain/hellovr_opengl_main.cpp +++ b/examples/StandaloneMain/hellovr_opengl_main.cpp @@ -844,13 +844,13 @@ void CMainApplication::RenderFrame() // happen right before and after the vsync causing all kinds of jittering issues. This glFinish() // appears to clear that up. Temporary fix while I try to get nvidia to investigate this problem. // 1/29/2014 mikesart - glFinish(); + //glFinish(); } // SwapWindow { B3_PROFILE("m_app->swapBuffer"); - m_app->swapBuffer(); +// m_app->swapBuffer(); //SDL_GL_SwapWindow( m_pWindow ); } diff --git a/examples/ThirdPartyLibs/enet/premake4.lua b/examples/ThirdPartyLibs/enet/premake4.lua index 522db3431..05390e766 100644 --- a/examples/ThirdPartyLibs/enet/premake4.lua +++ b/examples/ThirdPartyLibs/enet/premake4.lua @@ -14,8 +14,7 @@ files{"unix.c"} end - targetdir "../../../lib" - + includedirs { ".","include" } diff --git a/examples/pybullet/CMakeLists.txt b/examples/pybullet/CMakeLists.txt index dbac56750..ccde6a85e 100644 --- a/examples/pybullet/CMakeLists.txt +++ b/examples/pybullet/CMakeLists.txt @@ -3,6 +3,7 @@ INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/examples ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs + ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/enet/include ${PYTHON_INCLUDE_DIRS} ) IF(BUILD_PYBULLET_NUMPY) @@ -16,7 +17,7 @@ SET(pybullet_SRCS ../../examples/SharedMemory/IKTrajectoryHelper.cpp ../../examples/SharedMemory/IKTrajectoryHelper.h ../../examples/ExampleBrowser/InProcessExampleBrowser.cpp - ../../examples/SharedMemory/TinyRendererVisualShapeConverter.cpp + ../../examples/SharedMemory/TinyRendererVisualShapeConverter.cpp ../../examples/SharedMemory/TinyRendererVisualShapeConverter.h ../../examples/OpenGLWindow/SimpleCamera.cpp ../../examples/OpenGLWindow/SimpleCamera.h @@ -42,6 +43,9 @@ SET(pybullet_SRCS ../../examples/SharedMemory/PhysicsServerCommandProcessor.h ../../examples/SharedMemory/PhysicsClientSharedMemory.cpp ../../examples/SharedMemory/PhysicsClientSharedMemory.h + ../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp + ../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h + ../../examples/SharedMemory/PhysicsClientC_API.cpp ../../examples/SharedMemory/PhysicsClientC_API.h ../../examples/SharedMemory/Win32SharedMemory.cpp @@ -69,20 +73,55 @@ SET(pybullet_SRCS ../../examples/MultiThreading/b3PosixThreadSupport.cpp ../../examples/MultiThreading/b3Win32ThreadSupport.cpp ../../examples/MultiThreading/b3ThreadSupportInterface.cpp + ) IF(WIN32) -LINK_LIBRARIES( + LINK_LIBRARIES( ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) - + IF(BUILD_PYBULLET_ENET) + ADD_DEFINITIONS(-DWIN32 -DBT_ENABLE_ENET) + ENDIF(BUILD_PYBULLET_ENET) ENDIF(WIN32) -ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS}) + +IF(BUILD_PYBULLET_ENET) + ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS} + ../../examples/SharedMemory/PhysicsClientUDP.cpp + ../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp + ../../examples/SharedMemory/PhysicsClientUDP.h + ../../examples/SharedMemory/PhysicsClientUDP_C_API.h + ../../examples/ThirdPartyLibs/enet/win32.c + ../../examples/ThirdPartyLibs/enet/unix.c + ../../examples/ThirdPartyLibs/enet/callbacks.c + ../../examples/ThirdPartyLibs/enet/compress.c + ../../examples/ThirdPartyLibs/enet/host.c + ../../examples/ThirdPartyLibs/enet/list.c + ../../examples/ThirdPartyLibs/enet/packet.c + ../../examples/ThirdPartyLibs/enet/peer.c + ../../examples/ThirdPartyLibs/enet/protocol.c + ) +ELSE(BUILD_PYBULLET_ENET) + ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS}) +ENDIF(BUILD_PYBULLET_ENET) SET_TARGET_PROPERTIES(pybullet PROPERTIES VERSION ${BULLET_VERSION}) SET_TARGET_PROPERTIES(pybullet PROPERTIES SOVERSION ${BULLET_VERSION}) - -TARGET_LINK_LIBRARIES(pybullet BulletExampleBrowserLib BulletFileLoader BulletWorldImporter BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen BussIK Bullet3Common ${PYTHON_LIBRARIES}) +SET_TARGET_PROPERTIES(pybullet PROPERTIES DEBUG_POSTFIX "_d") + + +IF(WIN32) + IF(BUILD_PYBULLET_ENET) + TARGET_LINK_LIBRARIES(pybullet ws2_32 ) + ENDIF(BUILD_PYBULLET_ENET) + + SET_TARGET_PROPERTIES(pybullet PROPERTIES SUFFIX ".pyd" ) +ENDIF(WIN32) + + + + +TARGET_LINK_LIBRARIES(pybullet ws2_32 BulletExampleBrowserLib BulletFileLoader BulletWorldImporter BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen BussIK Bullet3Common ${PYTHON_LIBRARIES}) diff --git a/examples/pybullet/premake4.lua b/examples/pybullet/premake4.lua index 6f684a331..86ed39611 100644 --- a/examples/pybullet/premake4.lua +++ b/examples/pybullet/premake4.lua @@ -33,12 +33,37 @@ project ("pybullet") } end +if not _OPTIONS["no-enet"] then + + includedirs {"../../examples/ThirdPartyLibs/enet/include"} + + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + end + if os.is("MacOSX") then + end + + links {"enet"} + + files { + "../../examples/SharedMemory/PhysicsClientUDP.cpp", + "../../examples/SharedMemory/PhysicsClientUDP.h", + "../../examples/SharedMemory/PhysicsClientUDP_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientUDP_C_API.h", + } + defines {"BT_ENABLE_ENET"} + end + + files { "pybullet.c", "../../examples/SharedMemory/IKTrajectoryHelper.cpp", "../../examples/SharedMemory/IKTrajectoryHelper.h", "../../examples/ExampleBrowser/InProcessExampleBrowser.cpp", - "../../examples/SharedMemory/TinyRendererVisualShapeConverter.cpp", + "../../examples/SharedMemory/TinyRendererVisualShapeConverter.cpp", "../../examples/SharedMemory/TinyRendererVisualShapeConverter.h", "../../examples/OpenGLWindow/SimpleCamera.cpp", "../../examples/OpenGLWindow/SimpleCamera.h", @@ -64,6 +89,8 @@ project ("pybullet") "../../examples/SharedMemory/PhysicsServerCommandProcessor.h", "../../examples/SharedMemory/PhysicsClientSharedMemory.cpp", "../../examples/SharedMemory/PhysicsClientSharedMemory.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h", "../../examples/SharedMemory/PhysicsClientC_API.cpp", "../../examples/SharedMemory/PhysicsClientC_API.h", "../../examples/SharedMemory/Win32SharedMemory.cpp", diff --git a/examples/pybullet/pybullet.c b/examples/pybullet/pybullet.c index 744340f1e..394ddc6a3 100644 --- a/examples/pybullet/pybullet.c +++ b/examples/pybullet/pybullet.c @@ -1,7 +1,9 @@ #include "../SharedMemory/PhysicsClientC_API.h" #include "../SharedMemory/PhysicsDirectC_API.h" #include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h" - +#ifdef BT_ENABLE_ENET +#include "../SharedMemory/PhysicsClientUDP_C_API.h" +#endif //BT_ENABLE_ENET #ifdef __APPLE__ #include @@ -22,6 +24,7 @@ enum eCONNECT_METHOD { eCONNECT_GUI = 1, eCONNECT_DIRECT = 2, eCONNECT_SHARED_MEMORY = 3, + eCONNECT_UDP = 4, }; static PyObject* SpamError; @@ -60,8 +63,8 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args) { int method = eCONNECT_GUI; if (!PyArg_ParseTuple(args, "i", &method)) { PyErr_SetString(SpamError, - "connectPhysicsServer expected argument eCONNECT_GUI, " - "eCONNECT_DIRECT or eCONNECT_SHARED_MEMORY"); + "connectPhysicsServer expected argument GUI, " + "DIRECT, SHARED_MEMORY or UDP"); return NULL; } @@ -85,6 +88,18 @@ static PyObject* pybullet_connectPhysicsServer(PyObject* self, PyObject* args) { sm = b3ConnectSharedMemory(SHARED_MEMORY_KEY); break; } + case eCONNECT_UDP: + { +#ifdef BT_ENABLE_ENET + + sm = b3ConnectPhysicsUDP("localhost", 1234); +#else + PyErr_SetString(SpamError, "UDP is not enabled in this pybullet build"); + return NULL; +#endif //BT_ENABLE_ENET + + break; + } default: { PyErr_SetString(SpamError, "connectPhysicsServer unexpected argument"); @@ -2401,6 +2416,8 @@ initpybullet(void) eCONNECT_SHARED_MEMORY); // user read PyModule_AddIntConstant(m, "DIRECT", eCONNECT_DIRECT); // user read PyModule_AddIntConstant(m, "GUI", eCONNECT_GUI); // user read + PyModule_AddIntConstant(m, "UDP", eCONNECT_UDP); // user read + PyModule_AddIntConstant(m, "TORQUE_CONTROL", CONTROL_MODE_TORQUE); PyModule_AddIntConstant(m, "VELOCITY_CONTROL", diff --git a/test/SharedMemory/CMakeLists.txt b/test/SharedMemory/CMakeLists.txt index 8ece789cc..52297594c 100644 --- a/test/SharedMemory/CMakeLists.txt +++ b/test/SharedMemory/CMakeLists.txt @@ -41,7 +41,10 @@ ENDIF() ../../examples/SharedMemory/PhysicsServerCommandProcessor.h ../../examples/SharedMemory/PhysicsClientSharedMemory.cpp ../../examples/SharedMemory/PhysicsClientSharedMemory.h - ../../examples/SharedMemory/PhysicsClientC_API.cpp + ../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp + ../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h + + ../../examples/SharedMemory/PhysicsClientC_API.cpp ../../examples/SharedMemory/PhysicsClientC_API.h ../../examples/SharedMemory/PhysicsLoopBack.cpp ../../examples/SharedMemory/PhysicsLoopBack.h diff --git a/test/SharedMemory/premake4.lua b/test/SharedMemory/premake4.lua index 1974ba471..ca48cfea0 100644 --- a/test/SharedMemory/premake4.lua +++ b/test/SharedMemory/premake4.lua @@ -17,6 +17,8 @@ project ("Test_SharedMemoryPhysicsClient") "../../examples/SharedMemory/PhysicsClient.h", "../../examples/SharedMemory/PhysicsClientSharedMemory.cpp", "../../examples/SharedMemory/PhysicsClientSharedMemory.h", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.cpp", + "../../examples/SharedMemory/PhysicsClientSharedMemory_C_API.h", "../../examples/SharedMemory/PhysicsClientC_API.cpp", "../../examples/SharedMemory/PhysicsClientC_API.h", "../../examples/SharedMemory/Win32SharedMemory.cpp", diff --git a/test/SharedMemory/test.c b/test/SharedMemory/test.c index c366ab3a5..a1a6591d8 100644 --- a/test/SharedMemory/test.c +++ b/test/SharedMemory/test.c @@ -3,6 +3,10 @@ #include "SharedMemory/PhysicsClientC_API.h" #endif //PHYSICS_SHARED_MEMORY +#ifdef PHYSICS_UDP +#include "SharedMemory/PhysicsClientUDP_C_API.h" +#endif//PHYSICS_UDP + #ifdef PHYSICS_LOOP_BACK #include "SharedMemory/PhysicsLoopBackC_API.h" #endif //PHYSICS_LOOP_BACK @@ -224,7 +228,7 @@ void testSharedMemory(b3PhysicsClientHandle sm) #endif } ///perform some simulation steps for testing - for ( i=0;i<100;i++) + for ( i=0;i<10000;i++) { b3SharedMemoryStatusHandle statusHandle; int statusType; @@ -319,11 +323,17 @@ int main(int argc, char* argv[]) b3PhysicsClientHandle sm = b3CreateInProcessPhysicsServerAndConnect(argc,argv); #endif //__APPLE__ #endif + #ifdef PHYSICS_SHARED_MEMORY b3PhysicsClientHandle sm = b3ConnectSharedMemory(SHARED_MEMORY_KEY); #endif //PHYSICS_SHARED_MEMORY +#ifdef PHYSICS_UDP + b3PhysicsClientHandle sm = b3ConnectPhysicsUDP("localhost",1234); +#endif //PHYSICS_UDP + testSharedMemory(sm); } #endif + diff --git a/test/enet/chat/client/main.cpp b/test/enet/chat/client/main.cpp new file mode 100644 index 000000000..59565f464 --- /dev/null +++ b/test/enet/chat/client/main.cpp @@ -0,0 +1,165 @@ + +/* client.cpp */ +#include +#include +#include + + +int main(int argc, char* argv[]) { + ENetHost *client; + ENetAddress address; + ENetPeer *peer; + ENetEvent event; + char message[1024]; + int serviceResult; + + puts("Starting client"); + + if (enet_initialize() != 0) { + fprintf(stderr, "Error initialising enet"); + exit(EXIT_FAILURE); + + } + + client = enet_host_create(NULL, /* create a client host */ + 1, /* number of clients */ + 2, /* number of channels */ + 57600 / 8, /* incoming bandwith */ + 14400 / 8); /* outgoing bandwith */ + + if (client == NULL) { + fprintf(stderr, "Could not create client host"); + exit(EXIT_FAILURE); + + } + + + enet_address_set_host(&address, "localhost"); + address.port = 1234; + + peer = enet_host_connect(client, + &address, /* address to connect to */ + 2, /* number of channels */ + 0); /* user data supplied to + the receiving host */ + + if (peer == NULL) { + fprintf(stderr, "No available peers for initiating an ENet " + "connection.\n"); + exit(EXIT_FAILURE); + + } + + + /* Try to connect to server within 5 seconds */ + if (enet_host_service(client, &event, 5000) > 0 && + event.type == ENET_EVENT_TYPE_CONNECT) + { + puts("Connection to server succeeded."); + } + else + { + /* Either the 5 seconds are up or a disconnect event was */ + /* received. Reset the peer in the event the 5 seconds */ + /* had run out without any significant event. */ + enet_peer_reset(peer); + + fprintf(stderr, "Connection to server failed."); + exit(EXIT_FAILURE); + } + + while (true) + { + serviceResult = 1; + + /* Keep doing host_service until no events are left */ + while (serviceResult > 0) + { + serviceResult = enet_host_service(client, &event, 0); + + if (serviceResult > 0) + { + switch (event.type) + { + case ENET_EVENT_TYPE_CONNECT: + printf("A new client connected from %x:%u.\n", + event.peer->address.host, + event.peer->address.port); + + event.peer->data = (void*)"New User"; + break; + + case ENET_EVENT_TYPE_RECEIVE: + printf("A packet of length %u containing '%s' was " + "received from %s on channel %u.\n", + event.packet->dataLength, + event.packet->data, + event.peer->data, + event.channelID); + + /* Clean up the packet now that we're done using it. + > */ + enet_packet_destroy(event.packet); + + break; + + case ENET_EVENT_TYPE_DISCONNECT: + printf("%s disconected.\n", event.peer->data); + + break; + } + } + else if (serviceResult > 0) + { + puts("Error with servicing the client"); + exit(EXIT_FAILURE); + } + + } + + + printf("Say> "); + gets_s(message, 1024); + + if (strcmp(message, "exit") == 0 || + strcmp(message, "quit") == 0) { + break; + + } + + if (strlen(message) > 0) { + ENetPacket *packet = enet_packet_create(message, strlen + (message) + 1, ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(peer, 0, packet); + + } + + } + + enet_peer_disconnect(peer, 0); + + /* Allow up to 3 seconds for the disconnect to succeed */ + /* and drop any packets received packets */ + while (enet_host_service(client, &event, 3000) > 0) + { + + switch (event.type) + { + case ENET_EVENT_TYPE_RECEIVE: + enet_packet_destroy(event.packet); + break; + + case ENET_EVENT_TYPE_DISCONNECT: + puts("Disconnection succeeded."); + break; + } + } + + + enet_host_destroy(client); + enet_deinitialize(); + + return 0; + + +} diff --git a/test/enet/client/premake4.lua b/test/enet/chat/client/premake4.lua similarity index 70% rename from test/enet/client/premake4.lua rename to test/enet/chat/client/premake4.lua index 2a2327f24..24a71d6df 100644 --- a/test/enet/client/premake4.lua +++ b/test/enet/chat/client/premake4.lua @@ -1,12 +1,12 @@ -project ("Test_enet_client") +project ("Test_enet_chat_client") language "C++" kind "ConsoleApp" - includedirs {"../../../examples/ThirdPartyLibs/enet/include"} + includedirs {"../../../../examples/ThirdPartyLibs/enet/include"} if os.is("Windows") then defines { "WIN32" } diff --git a/test/enet/chat/server/main.cpp b/test/enet/chat/server/main.cpp new file mode 100644 index 000000000..cc15bd6a6 --- /dev/null +++ b/test/enet/chat/server/main.cpp @@ -0,0 +1,103 @@ +/* server.cpp */ +#include +#include + +int main(int argc, char *argv[]) +{ + ENetAddress address; + ENetHost *server; + ENetEvent event; + int serviceResult; + + puts("Starting server"); + + if (enet_initialize() != 0) + { + puts("Error initialising enet"); + exit(EXIT_FAILURE); + } + + + /* Bind the server to the default localhost. */ + /* A specific host address can be specified by */ + /* enet_address_set_host (& address, "x.x.x.x"); */ + address.host = ENET_HOST_ANY; + /* Bind the server to port 1234. */ + address.port = 1234; + + server = enet_host_create(&address, + 32, /* number of clients */ + 2, /* number of channels */ + 0, /* Any incoming bandwith */ + 0); /* Any outgoing bandwith */ + + if (server == NULL) + { + puts("Could not create server host"); + exit(EXIT_FAILURE); + } + + + while (true) + { + serviceResult = 1; + + /* Keep doing host_service until no events are left */ + while (serviceResult > 0) + { + /* Wait up to 1000 milliseconds for an event. */ + serviceResult = enet_host_service(server, &event, 1000); + + if (serviceResult > 0) + { + + switch (event.type) + { + case ENET_EVENT_TYPE_CONNECT: + printf("A new client connected from %x:%u.\n", + event.peer->address.host, + event.peer->address.port); + + /* Store any relevant client information here. */ + event.peer->data = (void*)"Client information"; + + break; + + case ENET_EVENT_TYPE_RECEIVE: + printf("A packet of length %u containing '%s' was " + "received from %s on channel %u.\n", + event.packet->dataLength, + event.packet->data, + event.peer->data, + event.channelID); + + /* Tell all clients about this message */ + enet_host_broadcast(server, 0, event.packet); + + break; + + case ENET_EVENT_TYPE_DISCONNECT: + printf("%s disconected.\n", event.peer->data); + + /* Reset the peer's client information. */ + + event.peer->data = NULL; + + break; + } + } + else if (serviceResult > 0) + { + puts("Error with servicing the server"); + exit(EXIT_FAILURE); + } + } + + } + + enet_host_destroy(server); + enet_deinitialize(); + + return 0; + +} diff --git a/test/enet/server/premake4.lua b/test/enet/chat/server/premake4.lua similarity index 70% rename from test/enet/server/premake4.lua rename to test/enet/chat/server/premake4.lua index 50f1c9b16..2069c2f01 100644 --- a/test/enet/server/premake4.lua +++ b/test/enet/chat/server/premake4.lua @@ -1,12 +1,12 @@ -project ("Test_enet_server") +project ("Test_enet_chat_server") language "C++" kind "ConsoleApp" - includedirs {"../../../examples/ThirdPartyLibs/enet/include"} + includedirs {"../../../../examples/ThirdPartyLibs/enet/include"} if os.is("Windows") then defines { "WIN32" } diff --git a/test/enet/client/main.cpp b/test/enet/nat_punchthrough/client/main.cpp similarity index 100% rename from test/enet/client/main.cpp rename to test/enet/nat_punchthrough/client/main.cpp diff --git a/test/enet/nat_punchthrough/client/premake4.lua b/test/enet/nat_punchthrough/client/premake4.lua new file mode 100644 index 000000000..feabb3429 --- /dev/null +++ b/test/enet/nat_punchthrough/client/premake4.lua @@ -0,0 +1,25 @@ + + +project ("Test_enet_nat_punchthrough_client") + + language "C++" + + kind "ConsoleApp" + + includedirs {"../../../../examples/ThirdPartyLibs/enet/include"} + + if os.is("Windows") then + defines { "WIN32" } + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + end + if os.is("MacOSX") then + end + + links {"enet"} + + files { + "main.cpp", + } + diff --git a/test/enet/server/main.cpp b/test/enet/nat_punchthrough/server/main.cpp similarity index 100% rename from test/enet/server/main.cpp rename to test/enet/nat_punchthrough/server/main.cpp diff --git a/test/enet/nat_punchthrough/server/premake4.lua b/test/enet/nat_punchthrough/server/premake4.lua new file mode 100644 index 000000000..2d8f4b7a8 --- /dev/null +++ b/test/enet/nat_punchthrough/server/premake4.lua @@ -0,0 +1,26 @@ + + +project ("Test_enet_nat_punchthrough_server") + + language "C++" + + kind "ConsoleApp" + + includedirs {"../../../../examples/ThirdPartyLibs/enet/include"} + + if os.is("Windows") then + defines { "WIN32" } + + links {"Ws2_32","Winmm"} + end + if os.is("Linux") then + end + if os.is("MacOSX") then + end + + links {"enet"} + + files { + "main.cpp", + } +