diff --git a/examples/CommonInterfaces/CommonGUIHelperInterface.h b/examples/CommonInterfaces/CommonGUIHelperInterface.h index 8e220faef..493b9e123 100644 --- a/examples/CommonInterfaces/CommonGUIHelperInterface.h +++ b/examples/CommonInterfaces/CommonGUIHelperInterface.h @@ -85,6 +85,9 @@ struct GUIHelperInterface virtual void removeAllUserDebugItems( ){}; virtual void setVisualizerFlagCallback(VisualizerFlagCallback callback){} + //empty name stops dumping video + virtual void dumpFramesToVideo(const char* mp4FileName) {}; + }; diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index b7cf1fd06..127ab11f5 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -191,6 +191,8 @@ SET(BulletExampleBrowser_SRCS ../SharedMemory/PhysicsLoopBackC_API.h ../SharedMemory/PhysicsServerCommandProcessor.cpp ../SharedMemory/PhysicsServerCommandProcessor.h + ../SharedMemory/SharedMemoryCommands.h + ../SharedMemory/SharedMemoryPublic.h ../BasicDemo/BasicExample.cpp ../BasicDemo/BasicExample.h ../InverseDynamics/InverseDynamicsExample.cpp diff --git a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp index 368cd67cc..df2a83021 100644 --- a/examples/ExampleBrowser/OpenGLExampleBrowser.cpp +++ b/examples/ExampleBrowser/OpenGLExampleBrowser.cpp @@ -371,6 +371,7 @@ void OpenGLExampleBrowserVisualizerFlagCallback(int flag, bool enable) if (flag == COV_ENABLE_GUI) { renderGui = enable; + renderGrid = enable; } if (flag == COV_ENABLE_WIREFRAME) @@ -868,8 +869,8 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[]) } - int width = 1024; - int height=768; + int width = 1280; + int height=640; #ifndef NO_OPENGL3 SimpleOpenGL3App* simpleApp=0; sUseOpenGL2 =args.CheckCmdLineFlag("opengl2"); diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.cpp b/examples/ExampleBrowser/OpenGLGuiHelper.cpp index 2107c8bb3..b65eaea44 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.cpp +++ b/examples/ExampleBrowser/OpenGLGuiHelper.cpp @@ -568,3 +568,10 @@ struct CommonGraphicsApp* OpenGLGuiHelper::getAppInterface() return m_data->m_glApp; } +void OpenGLGuiHelper::dumpFramesToVideo(const char* mp4FileName) +{ + if (m_data->m_glApp) + { + m_data->m_glApp->dumpFramesToVideo(mp4FileName); + } +} \ No newline at end of file diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.h b/examples/ExampleBrowser/OpenGLGuiHelper.h index 9448b5eef..0e91f0f3b 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.h +++ b/examples/ExampleBrowser/OpenGLGuiHelper.h @@ -85,6 +85,8 @@ struct OpenGLGuiHelper : public GUIHelperInterface virtual void setVisualizerFlagCallback(VisualizerFlagCallback callback); + virtual void dumpFramesToVideo(const char* mp4FileName); + }; #endif //OPENGL_GUI_HELPER_H diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index 0c44e93bb..f6a7df31f 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -88,6 +88,8 @@ project "App_BulletExampleBrowser" "../SharedMemory/PhysicsServerCommandProcessor.h", "../SharedMemory/TinyRendererVisualShapeConverter.cpp", "../SharedMemory/TinyRendererVisualShapeConverter.h", + "../SharedMemory/SharedMemoryCommands.h", + "../SharedMemory/SharedMemoryPublic.h", "../MultiThreading/MultiThreadingExample.cpp", "../MultiThreading/b3PosixThreadSupport.cpp", "../MultiThreading/b3Win32ThreadSupport.cpp", diff --git a/examples/OpenGLWindow/SimpleOpenGL3App.cpp b/examples/OpenGLWindow/SimpleOpenGL3App.cpp index 212d80a6f..f7e37688a 100644 --- a/examples/OpenGLWindow/SimpleOpenGL3App.cpp +++ b/examples/OpenGLWindow/SimpleOpenGL3App.cpp @@ -774,16 +774,18 @@ void SimpleOpenGL3App::swapBuffer() m_data->m_frameDumpPngFileName = 0; } } - m_window->endRendering(); - m_window->startRendering(); + m_window->endRendering(); + m_window->startRendering(); } // see also http://blog.mmacklin.com/2013/06/11/real-time-video-capture-with-ffmpeg/ void SimpleOpenGL3App::dumpFramesToVideo(const char* mp4FileName) { - int width = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenWidth(); - int height = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenHeight(); - char cmd[8192]; + if (mp4FileName) + { + int width = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenWidth(); + int height = (int)m_window->getRetinaScale()*m_instancingRenderer->getScreenHeight(); + char cmd[8192]; #ifdef _WIN32 sprintf(cmd, "ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %dx%d -i - " @@ -803,15 +805,25 @@ void SimpleOpenGL3App::dumpFramesToVideo(const char* mp4FileName) // sprintf(cmd,"ffmpeg -r 60 -f rawvideo -pix_fmt rgba -s %dx%d -i - " // "-threads 0 -preset fast -y -crf 21 -vf vflip %s",width,height,mp4FileName); - if (m_data->m_ffmpegFile) - { - pclose(m_data->m_ffmpegFile); - } - if (mp4FileName) - { - m_data->m_ffmpegFile = popen(cmd, "w"); + if (m_data->m_ffmpegFile) + { + pclose(m_data->m_ffmpegFile); + } + if (mp4FileName) + { + m_data->m_ffmpegFile = popen(cmd, "w"); - m_data->m_frameDumpPngFileName = mp4FileName; + m_data->m_frameDumpPngFileName = mp4FileName; + } + } else + { + if (m_data->m_ffmpegFile) + { + fflush(m_data->m_ffmpegFile); + pclose(m_data->m_ffmpegFile); + m_data->m_frameDumpPngFileName = 0; + } + m_data->m_ffmpegFile = 0; } } void SimpleOpenGL3App::dumpNextFrameToPng(const char* filename) diff --git a/examples/RobotSimulator/RobotSimulatorMain.cpp b/examples/RobotSimulator/RobotSimulatorMain.cpp index 77b6bf583..7ab3f3e70 100644 --- a/examples/RobotSimulator/RobotSimulatorMain.cpp +++ b/examples/RobotSimulator/RobotSimulatorMain.cpp @@ -16,7 +16,7 @@ int main(int argc, char* argv[]) //sim->connect(eCONNECT_UDP, "localhost", 1234); sim->configureDebugVisualizer( COV_ENABLE_GUI, 0); // sim->configureDebugVisualizer( COV_ENABLE_SHADOWS, 0);//COV_ENABLE_WIREFRAME - + sim->setTimeOut(10); //syncBodies is only needed when connecting to an existing physics server that has already some bodies sim->syncBodies(); b3Scalar fixedTimeStep = 1./240.; @@ -59,7 +59,9 @@ int main(int argc, char* argv[]) } #endif sim->setRealTimeSimulation(false); - + int vidLogId = -1; + int minitaurLogId = -1; + while (sim->canSubmitCommand()) { b3KeyboardEventsData keyEvents; @@ -67,14 +69,48 @@ int main(int argc, char* argv[]) if (keyEvents.m_numKeyboardEvents) { - printf("num key events = %d]\n", keyEvents.m_numKeyboardEvents); + //printf("num key events = %d]\n", keyEvents.m_numKeyboardEvents); //m_keyState is a flag combination of eButtonIsDown,eButtonTriggered, eButtonReleased for (int i=0;istartStateLogging(STATE_LOGGING_VIDEO_MP4,"video.mp4"); + } + else + { + sim->stopStateLogging(vidLogId); + vidLogId=-1; + } + } + } + + if (keyEvents.m_keyboardEvents[i].m_keyCode=='m') + { + if ( minitaurLogId<0 && keyEvents.m_keyboardEvents[i].m_keyState&eButtonTriggered) + { + minitaurLogId = sim->startStateLogging(STATE_LOGGING_MINITAUR,"simlog.bin"); + } + if (minitaurLogId>=0 && keyEvents.m_keyboardEvents[i].m_keyState&eButtonReleased) + { + sim->stopStateLogging(minitaurLogId); + minitaurLogId=-1; + } + } + + + //printf("keyEvent[%d].m_keyCode = %d, state = %d\n", i,keyEvents.m_keyboardEvents[i].m_keyCode,keyEvents.m_keyboardEvents[i].m_keyState); } } sim->stepSimulation(); + static double yaw=0; + double distance = 10.5+9 * b3Sin(yaw); + yaw+=0.008; + sim->resetDebugVisualizerCamera(distance,yaw,20,b3MakeVector3(0,0,0.1)); b3Clock::usleep(1000.*1000.*fixedTimeStep); } diff --git a/examples/RobotSimulator/b3RobotSimulatorClientAPI.cpp b/examples/RobotSimulator/b3RobotSimulatorClientAPI.cpp index 4c95006d2..8b2834a2f 100644 --- a/examples/RobotSimulator/b3RobotSimulatorClientAPI.cpp +++ b/examples/RobotSimulator/b3RobotSimulatorClientAPI.cpp @@ -134,6 +134,18 @@ bool b3RobotSimulatorClientAPI::isConnected() const return (m_data->m_physicsClientHandle != 0); } +void b3RobotSimulatorClientAPI::setTimeOut(double timeOutInSec) +{ + if (!isConnected()) + { + b3Warning("Not connected"); + return; + } + b3SetTimeOut(m_data->m_physicsClientHandle,timeOutInSec); + +} + + void b3RobotSimulatorClientAPI::disconnect() { if (!isConnected()) @@ -853,3 +865,18 @@ void b3RobotSimulatorClientAPI::stopStateLogging(int stateLoggerUniqueId) b3StateLoggingStop(commandHandle, stateLoggerUniqueId); statusHandle = b3SubmitClientCommandAndWaitStatus(m_data->m_physicsClientHandle, commandHandle); } + +void b3RobotSimulatorClientAPI::resetDebugVisualizerCamera(double cameraDistance, double cameraPitch, double cameraYaw, const b3Vector3& targetPos) +{ + b3SharedMemoryCommandHandle commandHandle = b3InitConfigureOpenGLVisualizer(m_data->m_physicsClientHandle); + if (commandHandle) + { + if ((cameraDistance >= 0)) + { + b3Vector3FloatData camTargetPos; + targetPos.serializeFloat(camTargetPos); + b3ConfigureOpenGLVisualizerSetViewMatrix(commandHandle, cameraDistance, cameraPitch, cameraYaw, camTargetPos.m_floats); + } + b3SubmitClientCommandAndWaitStatus(m_data->m_physicsClientHandle, commandHandle); + } +} diff --git a/examples/RobotSimulator/b3RobotSimulatorClientAPI.h b/examples/RobotSimulator/b3RobotSimulatorClientAPI.h index 9fe1b8c50..659d84502 100644 --- a/examples/RobotSimulator/b3RobotSimulatorClientAPI.h +++ b/examples/RobotSimulator/b3RobotSimulatorClientAPI.h @@ -130,6 +130,8 @@ public: bool isConnected() const; + void setTimeOut(double timeOutInSec); + void syncBodies(); void resetSimulation(); @@ -181,8 +183,9 @@ public: bool getLinkState(int bodyUniqueId, int linkIndex, b3LinkState* linkState); void configureDebugVisualizer(enum b3ConfigureDebugVisualizerEnum flag, int enable); + void resetDebugVisualizerCamera(double cameraDistance, double cameraPitch, double cameraYaw, const b3Vector3& targetPos); - int startStateLogging(b3StateLoggingType loggingType, const std::string& fileName, const b3AlignedObjectArray& objectUniqueIds, int maxLogDof = -1); + int startStateLogging(b3StateLoggingType loggingType, const std::string& fileName, const b3AlignedObjectArray& objectUniqueIds=b3AlignedObjectArray(), int maxLogDof = -1); void stopStateLogging(int stateLoggerUniqueId); void getVREvents(b3VREventsData* vrEventsData); diff --git a/examples/SharedMemory/CMakeLists.txt b/examples/SharedMemory/CMakeLists.txt index b282c09cb..d2754f8c5 100644 --- a/examples/SharedMemory/CMakeLists.txt +++ b/examples/SharedMemory/CMakeLists.txt @@ -38,6 +38,8 @@ SET(SharedMemory_SRCS PhysicsServerCommandProcessor.h TinyRendererVisualShapeConverter.cpp TinyRendererVisualShapeConverter.h + SharedMemoryCommands.h + SharedMemoryPublic.h ../TinyRenderer/geometry.cpp ../TinyRenderer/model.cpp ../TinyRenderer/tgaimage.cpp diff --git a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp index 85fb1dd7a..c5a48efaa 100644 --- a/examples/SharedMemory/PhysicsServerCommandProcessor.cpp +++ b/examples/SharedMemory/PhysicsServerCommandProcessor.cpp @@ -438,6 +438,31 @@ struct InternalStateLogger }; +struct VideoMP4Loggger : public InternalStateLogger +{ + + struct GUIHelperInterface* m_guiHelper; + std::string m_fileName; + VideoMP4Loggger(int loggerUid,const char* fileName,GUIHelperInterface* guiHelper) + :m_guiHelper(guiHelper) + { + m_fileName = fileName; + m_loggingUniqueId = loggerUid; + m_loggingType = STATE_LOGGING_VIDEO_MP4; + m_guiHelper->dumpFramesToVideo(fileName); + } + + virtual void stop() + { + m_guiHelper->dumpFramesToVideo(0); + } + virtual void logState(btScalar timeStamp) + { + //dumping video frames happens in another thread + //we could add some overlay of timestamp here, if needed/wanted + } +}; + struct MinitaurStateLogger : public InternalStateLogger { int m_loggingTimeStamp; @@ -1797,6 +1822,17 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm if (clientCmd.m_updateFlags & STATE_LOGGING_START_LOG) { + if (clientCmd.m_stateLoggingArguments.m_logType == STATE_LOGGING_VIDEO_MP4) + { + if (clientCmd.m_stateLoggingArguments.m_fileName) + { + int loggerUid = m_data->m_stateLoggersUniqueId++; + VideoMP4Loggger* logger = new VideoMP4Loggger(loggerUid,clientCmd.m_stateLoggingArguments.m_fileName,this->m_data->m_guiHelper); + m_data->m_stateLoggers.push_back(logger); + serverStatusOut.m_type = CMD_STATE_LOGGING_START_COMPLETED; + serverStatusOut.m_stateLoggingResultArgs.m_loggingUniqueId = loggerUid; + } + } if (clientCmd.m_stateLoggingArguments.m_logType == STATE_LOGGING_MINITAUR) { diff --git a/examples/SharedMemory/PhysicsServerExample.cpp b/examples/SharedMemory/PhysicsServerExample.cpp index dc3390c4e..970b209d3 100644 --- a/examples/SharedMemory/PhysicsServerExample.cpp +++ b/examples/SharedMemory/PhysicsServerExample.cpp @@ -179,8 +179,10 @@ enum MultiThreadedGUIHelperCommunicationEnums eGUIUserDebugAddParameter, eGUIUserDebugRemoveItem, eGUIUserDebugRemoveAllItems, + eGUIDumpFramesToVideo, }; + #include //#include "BulletMultiThreaded/PlatformDefinitions.h" @@ -489,7 +491,7 @@ void MotionThreadFunc(void* userPtr,void* lsMemory) args->m_cs->unlock(); } - + args->m_physicsServerPtr->disconnectSharedMemory(true); //do nothing } @@ -959,6 +961,16 @@ public: } + const char* m_mp4FileName; + virtual void dumpFramesToVideo(const char* mp4FileName) + { + m_cs->lock(); + m_mp4FileName = mp4FileName; + m_cs->setSharedParam(1, eGUIDumpFramesToVideo); + workerThreadWait(); + m_mp4FileName = 0; + } + }; @@ -1614,6 +1626,14 @@ void PhysicsServerExample::updateGraphics() m_multiThreadedHelper->mainThreadRelease(); break; } + + case eGUIDumpFramesToVideo: + { + m_multiThreadedHelper->m_childGuiHelper->dumpFramesToVideo(m_multiThreadedHelper->m_mp4FileName); + m_multiThreadedHelper->mainThreadRelease(); + break; + } + case eGUIHelperIdle: { break; diff --git a/examples/SharedMemory/PhysicsServerSharedMemory.cpp b/examples/SharedMemory/PhysicsServerSharedMemory.cpp index 182187885..70d173784 100644 --- a/examples/SharedMemory/PhysicsServerSharedMemory.cpp +++ b/examples/SharedMemory/PhysicsServerSharedMemory.cpp @@ -188,6 +188,8 @@ bool PhysicsServerSharedMemory::connectSharedMemory( struct GUIHelperInterface* void PhysicsServerSharedMemory::disconnectSharedMemory(bool deInitializeSharedMemory) { + m_data->m_commandProcessor->deleteDynamicsWorld(); + m_data->m_commandProcessor->setGuiHelper(0); if (m_data->m_verboseOutput) diff --git a/examples/SharedMemory/SharedMemoryPublic.h b/examples/SharedMemory/SharedMemoryPublic.h index 73760a130..6421a37e0 100644 --- a/examples/SharedMemory/SharedMemoryPublic.h +++ b/examples/SharedMemory/SharedMemoryPublic.h @@ -330,7 +330,8 @@ enum b3StateLoggingType STATE_LOGGING_MINITAUR = 0, STATE_LOGGING_GENERIC_ROBOT = 1, STATE_LOGGING_VR_CONTROLLERS = 2, - STATE_LOGGING_COMMANDS = 3, + STATE_LOGGING_VIDEO_MP4 = 3, + STATE_LOGGING_COMMANDS = 4, }; diff --git a/examples/pybullet/premake4.lua b/examples/pybullet/premake4.lua index d424ef209..7892d3da2 100644 --- a/examples/pybullet/premake4.lua +++ b/examples/pybullet/premake4.lua @@ -125,6 +125,8 @@ if not _OPTIONS["no-enet"] then "../../examples/SharedMemory/Win32SharedMemory.h", "../../examples/SharedMemory/PosixSharedMemory.cpp", "../../examples/SharedMemory/PosixSharedMemory.h", + "../../examples/SharedMemory/SharedMemoryCommands.h", + "../../examples/SharedMemory/SharedMemoryPublic.h", "../../examples/Utils/b3ResourcePath.cpp", "../../examples/Utils/b3ResourcePath.h", "../../examples/Utils/RobotLoggingUtil.cpp",