mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-13 13:20:07 +00:00
expose video capture as logging command in b3RobotSimulatorClientAPI (C++) and pybullet (use STATE_LOGGING_VIDEO_MP4)
This commit is contained in:
parent
b7b46b12d3
commit
59d16b2c42
@ -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) {};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -85,6 +85,8 @@ struct OpenGLGuiHelper : public GUIHelperInterface
|
||||
|
||||
virtual void setVisualizerFlagCallback(VisualizerFlagCallback callback);
|
||||
|
||||
virtual void dumpFramesToVideo(const char* mp4FileName);
|
||||
|
||||
};
|
||||
|
||||
#endif //OPENGL_GUI_HELPER_H
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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;i<keyEvents.m_numKeyboardEvents;i++)
|
||||
{
|
||||
printf("keyEvent[%d].m_keyCode = %d, state = %d\n", i,keyEvents.m_keyboardEvents[i].m_keyCode,keyEvents.m_keyboardEvents[i].m_keyState);
|
||||
if (keyEvents.m_keyboardEvents[i].m_keyCode=='0')
|
||||
{
|
||||
if ( keyEvents.m_keyboardEvents[i].m_keyState&eButtonTriggered)
|
||||
{
|
||||
if (vidLogId < 0)
|
||||
{
|
||||
vidLogId = sim->startStateLogging(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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<int>& objectUniqueIds, int maxLogDof = -1);
|
||||
int startStateLogging(b3StateLoggingType loggingType, const std::string& fileName, const b3AlignedObjectArray<int>& objectUniqueIds=b3AlignedObjectArray<int>(), int maxLogDof = -1);
|
||||
void stopStateLogging(int stateLoggerUniqueId);
|
||||
|
||||
void getVREvents(b3VREventsData* vrEventsData);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -179,8 +179,10 @@ enum MultiThreadedGUIHelperCommunicationEnums
|
||||
eGUIUserDebugAddParameter,
|
||||
eGUIUserDebugRemoveItem,
|
||||
eGUIUserDebugRemoveAllItems,
|
||||
eGUIDumpFramesToVideo,
|
||||
};
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
//#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;
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user