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:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user