Commit f12bfc23 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum

[PATCH] - patched in several changesets from LineAO branch for screen...

[PATCH] - patched in several changesets from LineAO branch for screen capturing and animation stuff.
parent 5ad32632
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include "WRealtimeTimer.h"
WRealtimeTimer::WRealtimeTimer():
WTimer(),
m_timer( osg::Timer() )
{
// initialize
}
WRealtimeTimer::~WRealtimeTimer()
{
// cleanup
}
void WRealtimeTimer::reset()
{
m_timer.setStartTick();
}
double WRealtimeTimer::elapsed() const
{
return m_timer.time_m() / 1000.0;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WREALTIMETIMER_H
#define WREALTIMETIMER_H
#include <boost/shared_ptr.hpp>
#include <osg/Timer>
#include "WTimer.h"
#include "WExportCommon.h"
/**
* Realtime timing. Internally, this uses an osg::Timer.
*/
class OWCOMMON_EXPORT WRealtimeTimer: public WTimer
{
public:
/**
* Convenience typedef for a shared_ptr
*/
typedef boost::shared_ptr< WRealtimeTimer > SPtr;
/**
* Convenience typedef for a const shared_ptr.
*/
typedef boost::shared_ptr< const WRealtimeTimer > ConstSPtr;
/**
* Constructs a realtime animation timer.
*/
WRealtimeTimer();
/**
* Destructor.
*/
virtual ~WRealtimeTimer();
/**
* Resets the start-tick.
*/
virtual void reset();
/**
* Returns the elapsed time since the last reset in seconds with milliseconds precision.
*
* \return elapsed time in seconds with millisecond precision.
*/
virtual double elapsed() const;
private:
/**
* The osg timer is used here.
*/
osg::Timer m_timer;
};
#endif // WREALTIMETIMER_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include "WTimer.h"
WTimer::WTimer()
{
// initialize
}
WTimer::~WTimer()
{
// cleanup
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WTIMER_H
#define WTIMER_H
#include <boost/shared_ptr.hpp>
#include "WExportCommon.h"
/**
* Base class for timing. Derive from it to write several timers like a frame-timer or realtime-timer.
*/
class OWCOMMON_EXPORT WTimer // NOLINT - no OWCOMMON_EXPORT does not need an virtual destructor.
{
public:
/**
* Convenience typedef for a shared_ptr
*/
typedef boost::shared_ptr< WTimer > SPtr;
/**
* Convenience typedef for a const shared_ptr.
*/
typedef boost::shared_ptr< const WTimer > ConstSPtr;
/**
* Constructs a animation timer.
*/
WTimer();
/**
* Destructor.
*/
virtual ~WTimer();
/**
* Resets the start-tick.
*/
virtual void reset() = 0;
/**
* Returns the elapsed time since the last reset in seconds with milliseconds precision.
*
* \return elapsed time in seconds with millisecond precision.
*/
virtual double elapsed() const = 0;
private:
};
#endif // WTIMER_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <osg/BufferObject>
#include "animation/WGEAnimationFrameTimer.h"
#include "WGEScreenCapture.h"
WGEScreenCapture::WGEScreenCapture():
m_timer( new WGEAnimationFrameTimer() )
{
// initialize
SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
w->get().m_frames = 0;
w->get().m_framesLeft = 0;
}
WGEScreenCapture::~WGEScreenCapture()
{
// cleanup
}
WGEAnimationFrameTimer::ConstSPtr WGEScreenCapture::getFrameTimer() const
{
return m_timer;
}
void WGEScreenCapture::recordStart()
{
record();
}
void WGEScreenCapture::recordStop()
{
record( 0 );
}
void WGEScreenCapture::screenshot()
{
record( 1 );
}
void WGEScreenCapture::record( size_t frames )
{
SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
w->get().m_framesLeft = frames;
}
bool WGEScreenCapture::isRecording()
{
SharedRecordingInformation::ReadTicket r = m_recordingInformation.getReadTicket();
return r->get().m_framesLeft;
}
void WGEScreenCapture::operator()( osg::RenderInfo& renderInfo ) const // NOLINT - osg wants this to be a non-const reference
{
SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
RecordingInformation& frameCounter = w->get();
// is there something to record?
if ( !frameCounter.m_framesLeft )
{
return;
}
// we need the graphics context here.
osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
// get size and color mode
size_t width = 0;
size_t height = 0;
GLenum pixelFormat = GL_RGB;
if (gc->getTraits())
{
width = gc->getTraits()->width;
height = gc->getTraits()->height;
pixelFormat = gc->getTraits()->alpha ? GL_RGBA : GL_RGB;
}
// count frames
frameCounter.m_frames++;
frameCounter.m_framesLeft--;
// read back buffer
glReadBuffer( GL_BACK );
// The following code uses PBO to grab the framebuffer. This sometimes causes errors. I am not sure why. glReadPixels
// osg::ref_ptr< osg::Image > imagePBO = new osg::Image();
// osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions( gc->getState()->getContextID(), true );
// imagePBO->allocateImage( width, height, 1, pixelFormat, GL_UNSIGNED_BYTE );
// if (m_pbo==0)
// {
// std::cout << "CREATE" << std::endl;
// ext->glGenBuffers( 1, &m_pbo );
// ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
// ext->glBufferData( GL_PIXEL_PACK_BUFFER_ARB, imagePBO->getTotalSizeInBytes(), 0, GL_STREAM_READ );
// }
// else
// {
// std::cout << "BIND" << std::endl;
// ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
// }
// std::cout << "READ" << std::endl;
// glReadPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE, 0 );
// std::cout << "MAP" << std::endl;
// GLubyte* src = static_cast< GLubyte* >( ext->glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB ) );
// if(src)
// {
// std::cout << "COPY" << std::endl;
// memcpy( imagePBO->data(), src, imagePBO->getTotalSizeInBytes() );
// ext->glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
//}
//
// std::cout << "RESTORE" << std::endl;
// ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
// create image and read pixels into it
osg::ref_ptr< osg::Image > image = new osg::Image();
image->readPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE );
// another frame.
m_timer->tick();
// someone wants this image
handleImage( frameCounter.m_framesLeft, frameCounter.m_frames, image );
}
WCondition::ConstSPtr WGEScreenCapture::getRecordCondition() const
{
return m_recordingInformation.getChangeCondition();
}
WGEScreenCapture::SharedRecordingInformation::ReadTicket WGEScreenCapture::getRecordingInformation() const
{
return m_recordingInformation.getReadTicket();
}
void WGEScreenCapture::resetFrameCounter()
{
SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
w->get().m_frames = 0;
m_timer->reset();
}
void WGEScreenCapture::handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const
{
m_signalHandleImage( framesLeft, totalFrames, image );
}
boost::signals2::connection WGEScreenCapture::subscribeSignal( HandleImageCallbackType callback )
{
return m_signalHandleImage.connect( callback );
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WGESCREENCAPTURE_H
#define WGESCREENCAPTURE_H
#include <limits>
#include <boost/signals2.hpp>
#include <boost/function.hpp>
#include <osg/Camera>
#include <osg/Image>
#include <osg/RenderInfo>
#include "../common/WSharedObject.h"
#include "../common/WCondition.h"
#include "animation/WGEAnimationFrameTimer.h"
#include "WExportWGE.h"
/**
* This class is a screen recorder. It records the frame buffer to files on a per-frame-basis. This class is NOT thread-safe due to performance
* reasons. You should not distribute the instance among multiple threads. It can be applied to <b>ONE</b> camera only by setting it as
* finalDrawCallback (osg::Camera::setFinalDrawCallback). Each camera can only use ONE final draw callback.
*
* This class is abstract. Derive your own class and handle image writing.
*
* \note This class does NOT write the images to disk. Set a callback for this.
*
* \ingroup GE
*/
class WGE_EXPORT WGEScreenCapture: public osg::Camera::DrawCallback
{
public:
/**
* Keeps track of several frame-counts.
*/
typedef struct
{
size_t m_frames; //!< current number of frames.
size_t m_framesLeft; //!< the frames to take until stop.
}
RecordingInformation;
/**
* The shared access type to the FrameCounting struct.
*/
typedef WSharedObject< RecordingInformation > SharedRecordingInformation;
/**
* Convenience typedef
*/
typedef osg::ref_ptr< WGEScreenCapture > RefPtr;
/**
* Convenience typedef
*/
typedef osg::ref_ptr< const WGEScreenCapture > ConstRefPtr;
/**
* This callback signature is needed to subscribe to the handleImage signal.
*/
typedef boost::function< void( size_t, size_t, osg::ref_ptr< osg::Image > ) > HandleImageCallbackType;
/**
* Creates a screen capture callback.
*/
WGEScreenCapture();
/**
* Destructor. Cleans up.
*/
virtual ~WGEScreenCapture();
/**
* Starts recording. If it already is running, nothing happens.
*/
void recordStart();
/**
* Stops recording. If not recording, nothing happens.
*/
void recordStop();
/**
* Checks if there are frames left for recording.
*
* \return true if yes.
*/
bool isRecording();
/**
* Makes a screenshot with the <b>next</b> frame. This is a shortcut for record( 1 ).
*/
void screenshot();
/**
* Resets the frame-counter to 0.
*/
void resetFrameCounter();
/**
* The draw callback operator. Gets called by OSG in draw traversal.
*
* \param renderInfo the OSG renderinfo
*/
virtual void operator()( osg::RenderInfo& renderInfo ) const; // NOLINT - osg wants this to be a non-const reference
/**
* The condition returned here is actually the change condition of the frame counter. This can be used to update GUI or something as it
* contains frame-counts, recording information and so on (updated per frame).
*
* \return the condition
*/
WCondition::ConstSPtr getRecordCondition() const;
/**
* Returns the current recording information. Release the lock after you grabbed the info you need.
*
* \return the info struct - read ticket
*/
SharedRecordingInformation::ReadTicket getRecordingInformation() const;
/**
* Returns a timer getting ticked on each recorded frame. This can then be used for animations for example.
*
* \return the timer.
*/
WGEAnimationFrameTimer::ConstSPtr getFrameTimer() const;
/**
* Subscribes a specified function to the new-image-signal. This gets emitted every time a new image was grabbed.
*
* \param callback the callback
*
* \return the connection.
*/
boost::signals2::connection subscribeSignal( HandleImageCallbackType callback );
protected:
/**
* The function handles new images. Implement it.
*
* \param framesLeft how much frames to come
* \param totalFrames the total number of frames until now
* \param image the image
*/
virtual void handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const;
/**
* Starts recording. If already recording, it continues recording.
*
* \param frames the number of frames to record. 0 means stop, 1 is a single screenshot.
*/
void record( size_t frames = std::numeric_limits< size_t >::max() );
private:
/**
* Counts the frames to take.
*/
SharedRecordingInformation m_recordingInformation;
/**
* The frame timer. Ticket on each recorded frame.
*/
WGEAnimationFrameTimer::SPtr m_timer;
/**
* The type of the signal for handleSignal.
*/
typedef boost::signals2::signal< void( size_t, size_t, osg::ref_ptr< osg::Image > ) > HandleImageSignalType;
/**
* The signal emitted on every new grabbed image.
*/
HandleImageSignalType m_signalHandleImage;
};
#endif // WGESCREENCAPTURE_H
......@@ -55,7 +55,9 @@ WGEViewer::WGEViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int
: WGEGraphicsWindow( wdata, x, y, width, height ),
boost::enable_shared_from_this< WGEViewer >(),
m_name( name ),
m_rendered( WBoolFlag::SPtr( new WBoolFlag( new WConditionOneShot(), false ) ) )
m_rendered( WBoolFlag::SPtr( new WBoolFlag( new WConditionOneShot(), false ) ) ),
m_screenCapture( new WGEScreenCapture() ),
m_inAnimationMode( false )
{
try
{
......@@ -69,6 +71,7 @@ WGEViewer::WGEViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int
m_View->setCamera( new WGECamera( width, height, projectionMode ) );
m_queryCallback = new QueryCallback( m_View->getCamera(), m_rendered );
m_View->getCamera()->setInitialDrawCallback( m_queryCallback );
m_View->getCamera()->setFinalDrawCallback( m_screenCapture );
#ifndef __APPLE__
m_View->getCamera()->setGraphicsContext( m_GraphicsContext.get() );
......@@ -128,8 +131,10 @@ WGEViewer::getView()
void WGEViewer::setCameraManipulator( osg::ref_ptr<osgGA::MatrixManipulator> manipulator )