Commit 4cca9263 authored by Nicolas Van der Noot's avatar Nicolas Van der Noot

mbsyscopy updated

parent 54a54d61
......@@ -64,10 +64,13 @@ function(mbsysc_specific_flags) # flag for lib_mbsysC only (not set by project)
cmake_dependent_option(FLAG_VISU "Enable 3D visualization (need Java or OpenGL)" ON "FLAG_REAL_TIME" OFF)
# use the Java library to display in real-time the animation
cmake_dependent_option(FLAG_JAVA "Enable 3D visualization (need Java)" ON "FLAG_VISU" OFF)
cmake_dependent_option(FLAG_JAVA "Enable 3D visualization (need Java)" OFF "FLAG_VISU" OFF)
# use the OpenGL library to display in real-time the animation
cmake_dependent_option(FLAG_OPEN_GL "Enable 3D visualization (need OpenGL)" OFF "FLAG_VISU" OFF)
cmake_dependent_option(FLAG_OPEN_GL "Enable 3D visualization (need OpenGL)" ON "FLAG_VISU" OFF)
# enable frame capture to record screenshot of the simulation
cmake_dependent_option(FLAG_FRAME_CAPTURE "Enable frame capture (need OpenGL)" OFF "FLAG_OPEN_GL" OFF)
endfunction()
......@@ -248,5 +251,10 @@ function(definitions)
set(LIB_MBSYSC_DEFINITIONS ${LIB_MBSYSC_DEFINITIONS} -DOPEN_GL)
endif( )
if(FLAG_FRAME_CAPTURE)
add_definitions( -DFRAME_CAPTURE )
set(LIB_MBSYSC_DEFINITIONS ${LIB_MBSYSC_DEFINITIONS} -DFRAME_CAPTURE)
endif( )
set(LIB_MBSYSC_DEFINITIONS ${LIB_MBSYSC_DEFINITIONS} PARENT_SCOPE)
endfunction()
# vim: ts=2 sw=2
# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC)
#
# Once done this will define
# FFMPEG_FOUND - System has the all required components.
# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers.
# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components.
# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components.
#
# For each of the components it will additionally set.
# - AVCODEC
# - AVDEVICE
# - AVFORMAT
# - AVFILTER
# - AVUTIL
# - POSTPROC
# - SWSCALE
# the following variables will be defined
# <component>_FOUND - System has <component>
# <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers
# <component>_LIBRARIES - Link these to use <component>
# <component>_DEFINITIONS - Compiler switches required for using <component>
# <component>_VERSION - The components version
#
# Copyright (c) 2006, Matthias Kretz, <kretz@kde.org>
# Copyright (c) 2008, Alexander Neundorf, <neundorf@kde.org>
# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(FindPackageHandleStandardArgs)
# The default components were taken from a survey over other FindFFMPEG.cmake files
if (NOT FFmpeg_FIND_COMPONENTS)
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL)
endif ()
#
### Macro: set_component_found
#
# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present.
#
macro(set_component_found _component )
if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)
# message(STATUS " - ${_component} found.")
set(${_component}_FOUND TRUE)
else ()
# message(STATUS " - ${_component} not found.")
endif ()
endmacro()
#
### Macro: find_component
#
# Checks for the given component by invoking pkgconfig and then looking up the libraries and
# include directories.
#
macro(find_component _component _pkgconfig _library _header)
if (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(PC_${_component} ${_pkgconfig})
endif ()
endif (NOT WIN32)
find_path(${_component}_INCLUDE_DIRS ${_header}
HINTS
${PC_LIB${_component}_INCLUDEDIR}
${PC_LIB${_component}_INCLUDE_DIRS}
PATH_SUFFIXES
ffmpeg
)
find_library(${_component}_LIBRARIES NAMES ${_library}
HINTS
${PC_LIB${_component}_LIBDIR}
${PC_LIB${_component}_LIBRARY_DIRS}
)
set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.")
set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.")
set_component_found(${_component})
mark_as_advanced(
${_component}_INCLUDE_DIRS
${_component}_LIBRARIES
${_component}_DEFINITIONS
${_component}_VERSION)
endmacro()
# Check for cached results. If there are skip the costly part.
if (NOT FFMPEG_LIBRARIES)
# Check for all possible component.
find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h)
find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h)
find_component(AVUTIL libavutil avutil libavutil/avutil.h)
find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h)
find_component(SWSCALE libswscale swscale libswscale/swscale.h)
find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
foreach (_component ${FFmpeg_FIND_COMPONENTS})
if (${_component}_FOUND)
# message(STATUS "Required component ${_component} present.")
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES})
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})
list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})
else ()
# message(STATUS "Required component ${_component} missing.")
endif ()
endforeach ()
# Build the include path with duplicates removed.
if (FFMPEG_INCLUDE_DIRS)
list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
endif ()
# cache the vars.
set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE)
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE)
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE)
mark_as_advanced(FFMPEG_INCLUDE_DIRS
FFMPEG_LIBRARIES
FFMPEG_DEFINITIONS)
endif ()
# Now set the noncached _FOUND vars for the components.
foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE)
set_component_found(${_component})
endforeach ()
# Compile the list of required vars
set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
foreach (_component ${FFmpeg_FIND_COMPONENTS})
list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS)
endforeach ()
# Give a nice error message if some of the required vars are missing.
find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS})
/*
* author: Nicolas Van der Noot
* date: March 15 2015
* author: Nicolas Van der Noot, Olivier Lantsoght
* date: September 26 2017
*
* Get absolute paths to the source project root (first CMakeLists.txt),
* to the binaries and to Robotran installation folder.
......@@ -9,5 +9,13 @@
*/
#define PROJECT_SOURCE_DIR "@PROJECT_SOURCE_DIR@"
#define PROJECT_BINARY_DIR "@PROJECT_BINARY_DIR@"
#define BUILD_PATH "@BUILD_PATH@"
#define BUILD_PATH_REL "@BUILD_PATH_REL@"
#ifdef UNIX
#define BUILD_PATH "@BUILD_PATH@"
#else
#ifdef _DEBUG
#define BUILD_PATH "@BUILD_PATH@/Debug"
#else
#define BUILD_PATH "@BUILD_PATH@/Release"
#endif
#endif
\ No newline at end of file
This diff is collapsed.
# distutils: language = c++
# distutils: sources = CyScreenCapture.cpp
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
from libcpp.string cimport string
cimport numpy as np
np.import_array() # initialize C API to call PyArray_SimpleNewFromData
#cdef public api tonumpyarray(double* data, long long size) with gil:
# if not (data and size >= 0): raise ValueError
# cdef np.npy_intp dims = size
# #NOTE: it doesn't take ownership of `data`. You must free `data` yourself
# return np.PyArray_SimpleNewFromData(1, &dims, np.NPY_DOUBLE, <void*>data)
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
from libcpp.vector cimport vector
cdef extern from "ScreenCapture.hh":
cdef enum CaptureFormat:
PPM
PNG
MPEG
OPEN_CV
cdef cppclass ScreenCapture:
ScreenCapture(int, int, int, int, int)
void AddMbs(string, string)
void AddCapture(string, CaptureFormat, int, bool)
void UpdateMbs(double)
void Capture()
void Record(double, double)
cdef class CyScreenCapture:
cdef ScreenCapture *thisptr
def __cinit__(self, width=1280, height=720, shader_flag=1, multi_samp=1, fps=25):
self.thisptr = new ScreenCapture(width, height, shader_flag, multi_samp, fps)
def __dealloc__(self):
del self.thisptr
def AddMbs(self, mbsfile, animfile):
self.thisptr.AddMbs(mbsfile, animfile)
def AddCapture(self, outputname, capture_format, vp_id, multisample_enable):
self.thisptr.AddCapture(outputname, capture_format, vp_id, multisample_enable)
def Record(self, speed_factor, end_time=10.):
self.thisptr.Record(speed_factor, end_time)
/*!
* \author Timothée Habra & Nicolas Docquier
* \file ScreenCapture.cc
* \brief ScreenCapture class
*/
#include "ScreenCapture.hh"
#include <iostream>
#include <stdio.h>
#include "OglOffscreenVpRenderer.hh"
#include "MbsWorldOgl.hh"
#include "PpmFrameCapture.hh"
#include "PngFrameCapture.hh"
#include "MpegFrameCapture.hh"
#include "OpenCvFrameCapture.hh"
/*! \brief constructor
*
* Create a ScreenCapture object and keep a reference to the
* given MbsWorld3D object
*
* \param[in] w3d the MbsWorld3D from wich to get the images
* \param[in] the desired frame rate for outputting images
*/
ScreenCapture::ScreenCapture(OpenGLMbs::MbsWorld3D* w3d, int fps){
flag_own_world_3d = false;
world_3d = w3d;
this->fps = fps;
}
/*! \brief constructor
*
* Create a ScreenCapture object and create a MbsWorld3D object
* using the given arguments.
*
* \param[in] width screen width along the X axis (in pixels)
* \param[in] height screen height along the Y axis (in pixels)
* \param[in] shader_flag flag to choose the type of shade(r
* \param[in] multi_samp number of samples to use for multisampling
* \param[in] the desired frame rate for outputting images
*/
ScreenCapture::ScreenCapture(int width, int height, int shader_flag, int multi_samp, int fps){
flag_own_world_3d = true;
world_3d = new OpenGLMbs::MbsWorldOgl(width, height, shader_flag, multi_samp);;
this->fps = fps;
}
/*! \brief destructor
*
* Clean the memory associated to this object. This normally generate
* the output mpeg files when setting a MPEG ScreenCapture.
*
* If a world_3D was allocated by the constructor, it will free the associated
* memory.
*/
ScreenCapture::~ScreenCapture(){
for(std::vector<OpenGLMbs::AnimReader*>::iterator it = anim_readers.begin() ; it !=anim_readers.end() ; ++it){
delete *it;
}
for(std::vector<double*>::iterator it2 = joint_vec.begin() ; it2 !=joint_vec.end() ; ++it2){
free(*it2);
}
if(flag_own_world_3d) delete world_3d;
}
/*! \brief Add a *.mbs file to this ScreenCapture with the associated
* animfil. It can be called several times to add several
* models to the images (including the possibility to add
* several *./mbs files with different *.anim file).
*
* \param[in] mbsfile the path to the *.mbs file to load
* \param[in] animfile the path to the *.anim file containing the time
* history of the joints for the animation
*
*/
void ScreenCapture::AddMbs(std::string mbsfile, std::string animfile){
// retrieve the id of the new mbs
int new_mbs_id = world_3d->GetNbMbs();
// load the mbs file and add it to the world 3D
world_3d->AddMbs(mbsfile.c_str());
// load the associated anim file
OpenGLMbs::AnimReader* ar = new OpenGLMbs::AnimReader(animfile.c_str());
anim_readers.push_back(ar);
// store the number of joint for this mbs
int nb_joint = world_3d->GetNbJoints(new_mbs_id);
nb_joints_vec.push_back(nb_joint);
// initialize a double array to copy value when retrieving from anim file
double* joints = (double*) malloc(nb_joint*sizeof(double));
joint_vec.push_back(joints);
}
/*! \brief Specify a capture, i.e. a viewpoint to be rendered and the way to output
* corresponding images. Several capture may be added to the same
* ScreenCapture object, for instance for recording images from sveral vieapoints
*
* \param[in] outputname the path and name of output file(s). It will be extended with the
* file extension corresponding to the selected format (see f parameter)
* \param[in] f the way to output image of the world 3D:
* - PPM: output images to several *.ppm files (an incremented number is appended to the filename)
* - PNG: output images to several *.png files (an incremented number is appended to the filename)
* - MPEG: output images to a *.mpeg movie
* - OPEN_CV: output images to an openCV frame (no file produced)
* \param[in] vp_id the id of the viewpoint to be used for computing images (first viewpoint is 0)
* \param[in] multisample_enable a flag to specify wether to use anti-aliasing (i.e. multisampling)
*
*/
void ScreenCapture::AddCapture(std::string outputname, CaptureFormat f, int vp_id, bool multisample_enable){
switch(f){
case PPM:// no lib required
break;
case PNG:
#ifndef FRAME_CAPTURE_PNG
std::cerr << "To capture to png, option FLAG_FRAME_CAPTURE_PNG must be enabled in cmake" << std::endl;
exit(0);
#endif
break;
case MPEG:
#ifndef FRAME_CAPTURE_MPEG
std::cerr << "To capture to mpeg, option FLAG_FRAME_CAPTURE_MPEG must be enabled in cmake" << std::endl;
exit(0);
#endif
break;
case OPEN_CV:
#ifndef FRAME_CAPTURE_OPENCV
std::cerr << "To capture to openCV, option FLAG_FRAME_CAPTURE_OPENCV must be enabled in cmake" << std::endl;
exit(0);
#endif
break;
default:
std::cerr << "ScreenCapture::AddCapture: unsuported format" << std::endl;
exit(0);
}
OpenGLMbs::OglOffscreenVpRenderer* renderer;
// create a renderer on the required viewpoint
if(f==OPEN_CV){
renderer = new OpenGLMbs::OglOffscreenVpRenderer(world_3d, world_3d->GetView(vp_id), GL_BGR, multisample_enable);
}
else{
renderer = new OpenGLMbs::OglOffscreenVpRenderer(world_3d, world_3d->GetView(vp_id), GL_RGB, multisample_enable);
}
world_3d->AddViewPointRenderer(renderer);
OpenGLMbs::MbsFrameCapture* fc;
switch(f){
case PPM:
fc = new OpenGLMbs::PpmFrameCapture(renderer, outputname);
break;
case PNG:
#ifdef FRAME_CAPTURE_PNG
fc = new OpenGLMbs::PngFrameCapture(renderer, outputname);
#endif
break;
case MPEG:
#ifdef FRAME_CAPTURE_MPEG
fc = new OpenGLMbs::MpegFrameCapture(renderer, outputname, fps);
#endif
break;
case OPEN_CV:
#ifdef FRAME_CAPTURE_OPENCV
fc = new OpenGLMbs::OpenCvFrameCapture(renderer, outputname);
#endif
break;
}
captures.push_back(fc);
}
/*! \brief Update the state of the MBS models associated to the current ScreenCapture
* (to be exact: the MBS models associated to the current MbsWorld3D of this
* ScreenCapture) on the basis of the given time. The given time is used to
* compute the joint value of each MBS from the corresponding anim file
* (using AnimReader utility functions).
*
*
* \param[in] time the time to which the joint must be updated
*/
void ScreenCapture::UpdateMbs(double time){
for(int mbs_id=0 ; mbs_id<nb_joints_vec.size() ; mbs_id++){
// fill Q values by reading the anim
anim_readers[mbs_id]->FillQ(time, nb_joints_vec[mbs_id], joint_vec[mbs_id]);
// update joints
world_3d->UpdateJoints(mbs_id, nb_joints_vec[mbs_id], joint_vec[mbs_id]);
}
// update the window
world_3d->Update();
}
/*! \brief Capture the current state of the World3D associated to this ScreenCapture
*
*/
void ScreenCapture::Capture(){
for(std::vector<OpenGLMbs::MbsFrameCapture*>::iterator cap = captures.begin() ; cap !=captures.end() ; ++cap){
(*cap)->Capture();
}
}
/*! \brief Record several images of the world3D for each capture set using
* AddCapture method and output to files depending on the chosen
* output format.
* The time between 2 images is computed as the ratio between
* the specifief speed_factor and the frame rate given to the
* constructor.
* Images are computed until the user close the main window
* or when the time reach the specified end time
*
* \param[in] speed_factor the speed factor for the animation:
* - speed_factor=1: normal speed ("realtime")
* - speed_factor>1: accelerate the animation
* - 0<speed_factor<1: slow down the animation
* \param[in] end_time the end time of the animation
*
*/
void ScreenCapture::Record(double speed_factor, double end_time){
double dt = speed_factor/fps;
double time = 0.;
// loop
do
{
// update the timing
time += dt;
UpdateMbs(time);
Capture();
}
while( world_3d->CheckClose() && time<=end_time );
std::cout<<"Stop recording at time=" << time<<"s. " <<std::endl;
}
/*!
* \author Timothée Habra & Nicolas Docquier
* \file ScreenCapture.hh
* \brief ScreenCapture class
*/
#ifndef _SCREEN_CAPTURE_HH_
#define _SCREEN_CAPTURE_HH_
#include <string>
#include <vector>
#include "MbsWorld3D.hh"
#include "AnimReader.hh"
#include "FrameCapture.hh"
enum CaptureFormat {PPM, PNG, MPEG, OPEN_CV};
/*! \brief ScreenCapture class defines a utility object that help to capture
* the 3D view from one or several viewpoint and output image to various
* supports.
* It can compute the image from the on screen viewpoint or from
* viewpoint that are not shown to the screen.
* The supported output format are the following (see CaptureFormat):
* - PPM: output images to several ppm files
* - PNG: output images to several png files
* - MPEG: output images to a mpeg movie
* - OPEN_CV: output images to an openCV frame
*/
class ScreenCapture{
public:
ScreenCapture(OpenGLMbs::MbsWorld3D* w3d, int fps=25);
ScreenCapture(int width = 1280, int height = 720,
int shader_flag=LIGHTS_NO_SPEC_SHADER, int multi_samp=4,
int fps=25);
~ScreenCapture();
void AddMbs(std::string mbsfile, std::string animfile);
void AddCapture(std::string outputname, CaptureFormat f, int vp_id, bool multisample_enable=false);
void UpdateMbs(double time);
void Capture();
void Record(double speed_factor=1., double end_time = DBL_MAX);
private:
/// frame rate for mpeg output
int fps;
std::vector<OpenGLMbs::AnimReader*> anim_readers;
std::vector<int> nb_joints_vec;
std::vector<double*> joint_vec;
/// a vector storing the desired captures
std::vector<OpenGLMbs::MbsFrameCapture*> captures;
/// the MbsWorld3D object from which to render images
OpenGLMbs::MbsWorld3D *world_3d;
/// flag to know wether the object initialized its own MbsWorld3D object (useful for freeing memory)
bool flag_own_world_3d;
};
#endif //_SCREEN_CAPTURE_HH_
/*!
* \author Timothée Habra, Nicolas Docquier
* \file main.cc
* \brief file with the main function
*/
#include "MbsWorld3D.hh"
#include "MbsWorldOgl.hh"
#include "cmake_config.h"
#include "AnimReader.hh"
#include "shader_multisample.hh"
#include <iostream>
#include "OglWorldRenderer.hh"
#include "OglViewPointRenderer.hh"
#include "OglOffscreenVpRenderer.hh"
#include "ScreenCapture.hh"
// function prototype for manual loading
void manual_mbs_load(OpenGLMbs::MbsWorld3D *world_3d);
#define NB_JOINTS 5 ///< number of joints
#define MBS_ID 0 ///< ID of the .mbs model added (first: 0, second: 1, third: 2...)
/*! \brief main function
*/
int main(int argc, char **argv)
{
int shader_flag, multi_samp;
// get the shader flag and the mutlisampling option from .mbs file
OpenGLMbs::shader_multisample(PROJECT_SOURCE_DIR"/../../../ExampleProjects/PendulumSpringC/dataR/PendulumSpringC_obj.mbs", shader_flag, multi_samp);
int W, H; // image width, height [pixels]
W = 1280;
H = 720;
int fps = 50; // desired frame rate
double speed_factor = 1.; // speed factor to play the video
// main window for 3D world
OpenGLMbs::MbsWorldOgl world_3d(W, H, shader_flag, multi_samp);
// Create the ScreenCapture object
ScreenCapture sc(&world_3d, fps);
// Add a 1st mbs in the animation
sc.AddMbs(PROJECT_SOURCE_DIR"/../../../ExampleProjects/PendulumSpringC/dataR/PendulumSpringC_obj.mbs",
PROJECT_SOURCE_DIR"/../../../ExampleProjects/PendulumSpringC/animationR/dirdyn_q.anim");
// Add a 2nd mbs in the animation
// sc.AddMbs(PROJECT_SOURCE_DIR"/../../../ExampleProjects/MultiplePendulum/dataR/MultiplePendulum.mbs",
// PROJECT_SOURCE_DIR"/../../../ExampleProjects/MultiplePendulum/animationR/dirdyn_q.anim");
// sc.AddCapture("ppm_test",PPM, 1, true);
// sc.AddCapture("png_test",PNG, 1, true);
sc.AddCapture("./mpeg_test",MPEG, 0, true);
sc.AddCapture("opencv_test",OPEN_CV, 2, true);
world_3d.SetBackgroundColor(glm::vec3(1.0, 0.85, 0.30));
// switch between 2 registration mode
bool auto_record_loop = true;
// produce the animation using the regulated record loop of ScreenCapture class
if(auto_record_loop){
sc.Record(speed_factor);
}
else {
// produce the animation using a custom loop
// loop512