From Jeremy Moles & Robert Osfield, Added support for playback of animation paths using 'Z' key

This commit is contained in:
Robert Osfield
2007-06-13 20:34:16 +00:00
parent a64dc27595
commit 21033536a7
2 changed files with 75 additions and 18 deletions

View File

@@ -17,6 +17,7 @@
#include <osg/AnimationPath>
#include <osgText/Text>
#include <osgGA/GUIEventHandler>
#include <osgGA/AnimationPathManipulator>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/Viewer>
@@ -218,17 +219,14 @@ protected:
Event handler allowing the user to record the animation "path" of a camera. In it's current
implementation, this handler cannot guarantee the final view matrix is correct; it is
conceivable that the matrix may be one frame off. Eh--not a big deal! :)
TODO: Find the good filename.
TODO: Write as we go, not when it's all done.
TODO: Create osgviewer on-screen indication that animation is taking place.
TODO: Explore multi-cameras thing.
TODO: Investigate crash if non-focused camera?
TODO: Write the file as we go, not when it's all done.
TODO: Create an osgviewer on-screen indication that animation is taking place.
*/
class OSGVIEWER_EXPORT RecordCameraPathHandler : public osgGA::GUIEventHandler
{
public:
RecordCameraPathHandler();
RecordCameraPathHandler(const std::string &filename = "saved_animation.path");
virtual void getUsage(osg::ApplicationUsage &usage) const;
@@ -236,12 +234,16 @@ public:
protected:
bool _currentlyRecording;
double _interval;
double _delta;
osg::Timer_t _animStartTime;
osg::Timer_t _lastFrameTime;
osg::ref_ptr<osg::AnimationPath> _animPath;
std::string _filename;
bool _currentlyRecording;
bool _currentlyPlaying;
double _interval;
double _delta;
osg::Timer_t _animStartTime;
osg::Timer_t _lastFrameTime;
osg::ref_ptr<osg::AnimationPath> _animPath;
osg::ref_ptr<osgGA::AnimationPathManipulator> _animPathManipulator;
osg::ref_ptr<osgGA::MatrixManipulator> _oldManipulator;
};
}

View File

@@ -343,17 +343,19 @@ bool ThreadingHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIAction
return false;
}
RecordCameraPathHandler::RecordCameraPathHandler():
RecordCameraPathHandler::RecordCameraPathHandler(const std::string& filename):
_filename(filename),
_currentlyRecording(false),
_currentlyPlaying(false),
_delta(0.0f),
_lastFrameTime(osg::Timer::instance()->tick()),
_animStartTime(0)
{
_animPath = new osg::AnimationPath();
const char* str = getenv("OSG_CAMERA_ANIMATION_FPS");
const char* str = getenv("OSG_RECORD_CAMERA_PATH_FPS");
if(str) _interval = 1.0f / atof(str);
if (str) _interval = 1.0f / atof(str);
else _interval = 1.0f / 25.0f;
}
@@ -361,6 +363,7 @@ RecordCameraPathHandler::RecordCameraPathHandler():
void RecordCameraPathHandler::getUsage(osg::ApplicationUsage &usage) const
{
usage.addKeyboardMouseBinding("z", "Toggle camera path recording.");
usage.addKeyboardMouseBinding("Z", "Load local camera path recording.");
}
bool RecordCameraPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
@@ -376,6 +379,7 @@ bool RecordCameraPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GU
{
case(osgGA::GUIEventAdapter::KEYUP):
{
// The user has requested to toggle recording.
if (ea.getKey() == 'z')
{
// The user has requested to BEGIN recording.
@@ -383,6 +387,7 @@ bool RecordCameraPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GU
{
_currentlyRecording = true;
_animStartTime = osg::Timer::instance()->tick();
_animPath->clear();
osg::notify(osg::NOTICE)<<"Recording camera path."<<std::endl;
}
@@ -395,9 +400,8 @@ bool RecordCameraPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GU
// In the future this will need to be written continuously, rather
// than all at once.
std::string filename("saved_animation.path");
std::ofstream out(filename.c_str());
osg::notify(osg::NOTICE)<<"Writing camera file: "<<filename<<std::endl;
std::ofstream out(_filename.c_str());
osg::notify(osg::NOTICE)<<"Writing camera file: "<<_filename<<std::endl;
_animPath->write(out);
out.close();
}
@@ -405,6 +409,57 @@ bool RecordCameraPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GU
return true;
}
// The user has requested to toggle playback. You'll notice in the code below that
// we take over the current manipulator; it was originally recommended that we
// check for a KeySwitchManipulator, create one if not present, and then add this
// to either the newly created one or the existing one. However, the code do that was
// EXTREMELY dirty, so I opted for a simpler solution. At a later date, someone may
// want to implement the original recomendation (which is in a mailing list reply
// from June 1st by Robert in a thread called "osgviewer Camera Animation (preliminary)".
else if (ea.getKey() == 'Z')
{
if (_currentlyRecording)
{
_currentlyRecording = false;
_delta = 0.0f;
// In the future this will need to be written continuously, rather
// than all at once.
std::ofstream out(_filename.c_str());
osg::notify(osg::NOTICE)<<"Writing camera file: "<<_filename<<std::endl;
_animPath->write(out);
out.close();
}
// The user has requested to BEGIN playback.
if (!_currentlyPlaying)
{
_animPathManipulator = new osgGA::AnimationPathManipulator(_animPath.get());
_animPathManipulator->home(ea,aa);
// If we succesfully found our _filename file, set it and keep a copy
// around of the original MatrixManipulator to restore later.
if (_animPathManipulator.valid() && _animPathManipulator->valid())
{
_oldManipulator = viewer->getCameraManipulator();
viewer->setCameraManipulator(_animPathManipulator.get());
_currentlyPlaying = true;
}
}
// The user has requested to STOP playback.
else
{
// Restore the old manipulator if necessary and stop playback.
if(_oldManipulator.valid()) viewer->setCameraManipulator(_oldManipulator.get());
_currentlyPlaying = false;
_oldManipulator = 0;
}
return true;
}
break;
}
case(osgGA::GUIEventAdapter::FRAME):