From Jeremy Moles, new event handler to record the camera path. A few small tweaks by Robert Osfield to make it more consistent with the old osgProducer::Viewer behavior.

This commit is contained in:
Robert Osfield
2007-06-01 10:39:27 +00:00
parent 9b1426e47e
commit 5a80e4bfdc
3 changed files with 128 additions and 0 deletions

View File

@@ -117,6 +117,9 @@ int main(int argc, char** argv)
// add the help handler
viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
// add the camera path handler
viewer.addEventHandler(new osgViewer::AnimationPathHandler);
while (arguments.read("--SingleThreaded")) viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
while (arguments.read("--CullDrawThreadPerContext")) viewer.setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
while (arguments.read("--DrawThreadPerContext")) viewer.setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);

View File

@@ -14,6 +14,7 @@
#ifndef OSGVIEWER_VIEWEREVENTHANDLER
#define OSGVIEWER_VIEWEREVENTHANDLER 1
#include <osg/AnimationPath>
#include <osgGA/GUIEventHandler>
#include <osgViewer/GraphicsWindow>
@@ -102,6 +103,36 @@ protected:
bool _done;
};
/**
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?
*/
class AnimationPathHandler : public osgGA::GUIEventHandler
{
public:
AnimationPathHandler();
virtual void getUsage(osg::ApplicationUsage &usage) const;
bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);
protected:
bool _currentlyRecording;
double _interval;
double _delta;
osg::Timer_t _animStartTime;
osg::Timer_t _lastFrameTime;
osg::ref_ptr<osg::AnimationPath> _animPath;
};
}
#endif

View File

@@ -11,6 +11,7 @@
* OpenSceneGraph Public License for more details.
*/
#include <fstream>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
@@ -342,4 +343,97 @@ bool ThreadingHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIAction
return false;
}
AnimationPathHandler::AnimationPathHandler():
_currentlyRecording(false),
_delta(0.0f),
_lastFrameTime(osg::Timer::instance()->tick()),
_animStartTime(0)
{
_animPath = new osg::AnimationPath();
const char* str = getenv("OSG_CAMERA_ANIMATION_FPS");
if(str) _interval = 1.0f / atof(str);
else _interval = 1.0f / 25.0f;
}
void AnimationPathHandler::getUsage(osg::ApplicationUsage &usage) const
{
usage.addKeyboardMouseBinding("z", "Toggle camera path recording.");
}
bool AnimationPathHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if (viewer == NULL)
{
return false;
}
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYUP):
{
if (ea.getKey() == 'z')
{
// The user has requested to BEGIN recording.
if (!_currentlyRecording)
{
_currentlyRecording = true;
_animStartTime = osg::Timer::instance()->tick();
osg::notify(osg::NOTICE)<<"Recording camera path."<<std::endl;
}
// THe user has requested to STOP recording, write the file!
else
{
_currentlyRecording = false;
_delta = 0.0f;
// 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;
_animPath->write(out);
out.close();
}
return true;
}
break;
}
case(osgGA::GUIEventAdapter::FRAME):
{
// Calculate our current delta (difference) in time between the last frame and
// current frame, regardless of whether we actually store a ControlPoint...
osg::Timer_t time = osg::Timer::instance()->tick();
double delta = osg::Timer::instance()->delta_s(_lastFrameTime, time);
_lastFrameTime = time;
// If our internal _delta is finally large enough to warrant a ControlPoint
// insertion, do so now. Be sure and reset the internal _delta, so we can start
// calculating when the next insert should happen.
if (_currentlyRecording && _delta >= _interval)
{
const osg::Matrixd& m = viewer->getCamera()->getInverseViewMatrix();
_animPath->insert(osg::Timer::instance()->delta_s(_animStartTime, time), osg::AnimationPath::ControlPoint(m.getTrans(), m.getRotate()));
_delta = 0.0f;
}
else _delta += delta;
break;
}
default:
break;
}
return false;
}
}