From 76c970da5d14d84b836efd4f6cd36a07ad2ff7a4 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 Nov 2004 12:03:33 +0000 Subject: [PATCH] From Ulrich Hertlien, improved osgsequence example --- examples/osgsequence/osgsequence.cpp | 287 +++++++++++++++++---------- 1 file changed, 185 insertions(+), 102 deletions(-) diff --git a/examples/osgsequence/osgsequence.cpp b/examples/osgsequence/osgsequence.cpp index a2f6ad200..26e0841b0 100644 --- a/examples/osgsequence/osgsequence.cpp +++ b/examples/osgsequence/osgsequence.cpp @@ -1,6 +1,19 @@ // -*-c++-*- +/* + * This application is open source and may be redistributed and/or modified + * freely and without restriction, both in commericial and non commericial + * applications,as long as this copyright notice is maintained. + * + * This application 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. +*/ + +#include +#include #include +#include #include #include @@ -9,86 +22,182 @@ #include -// -// A simple demo demonstrating usage of osg::Sequence. -// +// create text drawable at 'pos' +osg::Geode* createText(const std::string& str, const osg::Vec3& pos) +{ + // text drawable + osgText::Text* text = new osgText::Text; + text->setFont(std::string("fonts/arial.ttf")); + text->setPosition(pos); + text->setText(str); -// simple event handler to start/stop sequences -class MyEventHandler : public osgGA::GUIEventHandler { + // geode + osg::Geode* geode = new osg::Geode; + geode->addDrawable(text); + + return geode; +} + +osg::Node* createTextGroup(const char** text) +{ + osg::Group* group = new osg::Group; + + osg::Vec3 pos(120.0f, 800.0f, 0.0f); + const osg::Vec3 delta(0.0f, -60.0f, 0.0f); + + // header + const char** t = text; + group->addChild(createText(*t++, pos)); + pos += delta; + + // remainder of text under sequence + osg::Sequence* seq = new osg::Sequence; + group->addChild(seq); + while (*t) { + seq->addChild(createText(*t++, pos)); + seq->setTime(seq->getNumChildren()-1, 2.0f); + pos += delta; + } + + // loop through all children + seq->setInterval(osg::Sequence::LOOP, 0,-1); + + // real-time playback, repeat indefinitively + seq->setDuration(1.0f, -1); + + // must be started explicitly + seq->setMode(osg::Sequence::START); + + return group; +} + +osg::Node* createHUD(osg::Node* node) +{ + // absolute transform + osg::MatrixTransform* modelview_abs = new osg::MatrixTransform; + modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF); + modelview_abs->setMatrix(osg::Matrix::identity()); + modelview_abs->addChild(node); + + // 2D projection node + osg::Projection* projection = new osg::Projection; + projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); + projection->addChild(modelview_abs); + + // turn off lighting and depth test + osg::StateSet* state = modelview_abs->getOrCreateStateSet(); + state->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + + return projection; +} + +osg::Node* createScaledNode(osg::Node* node, float targetScale) +{ + // create scale matrix + osg::MatrixTransform* transform = new osg::MatrixTransform; + + const osg::BoundingSphere& bsphere = node->getBound(); + float scale = targetScale / bsphere._radius; + transform->setMatrix(osg::Matrix::scale(scale,scale,scale)); + transform->setDataVariance(osg::Object::STATIC); + transform->addChild(node); + + // rescale normals + osg::StateSet* state = transform->getOrCreateStateSet(); + state->setMode(GL_NORMALIZE, osg::StateAttribute::ON); + + return transform; +} + +osg::Sequence* createSequence(osg::ArgumentParser& arguments) +{ + // assumes any remaining parameters are models + osg::Sequence* seq = new osg::Sequence; + for (int i = 1; i < arguments.argc(); ++i) + { + // load model + osg::Node* node = osgDB::readNodeFile(arguments[i]); + if (!node) { + continue; + } + seq->addChild(createScaledNode(node, 100.0f)); + seq->setTime(seq->getNumChildren()-1, 1.0f); + } + + // loop through all children + seq->setInterval(osg::Sequence::LOOP, 0,-1); + + // real-time playback, repeat indefinitively + seq->setDuration(1.0f, -1); + + return seq; +} + +// event handler to control sequence +class SequenceEventHandler : public osgGA::GUIEventHandler +{ public: - /// Constructor. - MyEventHandler(std::vector* seq) + SequenceEventHandler(osg::Sequence* seq) { _seq = seq; } - /// Handle events. + // handle keydown events virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&) { - bool handled = false; - - if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) - { - const char keys[] = "!@#$%^&*()"; - for (unsigned int i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) { - if (i < _seq->size() && ea.getKey() == keys[i]) + if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) { + switch (ea.getKey()) { + case 'S': { - // toggle sequence - osg::Sequence* seq = (*_seq)[i]; - osg::Sequence::SequenceMode mode = seq->getMode(); - switch (mode) { - case osg::Sequence::START: - seq->setMode(osg::Sequence::PAUSE); - break; - case osg::Sequence::STOP: - seq->setMode(osg::Sequence::START); - break; - case osg::Sequence::PAUSE: - seq->setMode(osg::Sequence::RESUME); - break; - default: - break; + osg::Sequence::SequenceMode mode = _seq->getMode(); + if (mode == osg::Sequence::STOP) { + mode = osg::Sequence::START; + std::cerr << "Start" << std::endl; } - std::cerr << "Toggled sequence " << i << std::endl; - handled = true; + else if (mode == osg::Sequence::PAUSE) { + mode = osg::Sequence::RESUME; + std::cerr << "Resume" << std::endl; + } + else { + mode = osg::Sequence::PAUSE; + std::cerr << "Pause" << std::endl; + } + _seq->setMode(mode); } + break; + case 'L': + { + osg::Sequence::LoopMode mode; + int begin, end; + _seq->getInterval(mode, begin, end); + if (mode == osg::Sequence::LOOP) { + mode = osg::Sequence::SWING; + std::cerr << "Swing" << std::endl; + } + else { + mode = osg::Sequence::LOOP; + std::cerr << "Loop" << std::endl; + } + _seq->setInterval(mode, begin, end); + } + break; + default: + break; } } - return handled; + return false; } - /// accept visits. + // accept visits virtual void accept(osgGA::GUIEventHandlerVisitor&) {} private: - std::vector* _seq; + osg::ref_ptr _seq; }; -osg::Sequence* generateSeq(osg::Sequence::LoopMode mode, - float speed, int nreps, - std::vector& model) -{ - osg::Sequence* seqNode = new osg::Sequence; - - // add children, show each child for 1.0 seconds - for (unsigned int i = 0; i < model.size(); i++) { - seqNode->addChild(model[i]); - seqNode->setTime(i, 1.0f); - } - - // interval - seqNode->setInterval(mode, 0, -1); - - // speed-up factor and number of repeats for entire sequence - seqNode->setDuration(speed, nreps); - - // stopped - seqNode->setMode(osg::Sequence::STOP); - - return seqNode; -} int main( int argc, char **argv ) { @@ -132,58 +241,32 @@ int main( int argc, char **argv ) return 1; } - // assumes any remaining parameters are models - std::vector model; - for (int i = 1; i < arguments.argc(); i++) - { - std::cerr << "Loading " << arguments[i] << std::endl; - osg::Node* node = osgDB::readNodeFile(arguments[i]); - if (node) - model.push_back(node); - } - if (model.empty()) { - return -1; - } - // root osg::Group* rootNode = new osg::Group; - // create sequences - std::vector seq; - - const osg::Sequence::LoopMode mode[] = { osg::Sequence::LOOP, - osg::Sequence::SWING, - osg::Sequence::LOOP }; - const float speed[] = { 0.5f, 1.0f, 1.5f }; - const int nreps[] = { -1, 5, 1 }; - - float x = 0.0f; - for (unsigned int j = 0; j < (sizeof(speed) / sizeof(speed[0])); j++) { - osg::Sequence* seqNode = generateSeq(mode[j], speed[j], nreps[j], - model); - if (!seqNode) - continue; - seq.push_back(seqNode); - - // position sequence - osg::Matrix matrix; - matrix.makeTranslate(x, 0.0, 0.0); - - osg::MatrixTransform* xform = new osg::MatrixTransform; - xform->setMatrix(matrix); - xform->addChild(seqNode); - - rootNode->addChild(xform); - - x += seqNode->getBound()._radius * 1.5f; - } + // create info display + const char* text[] = { + "osg::Sequence Mini-Howto", + "- can be used for simple flip-book-style animation", + "- is subclassed from osg::Switch", + "- assigns a display duration to each child", + "- can loop or swing through an interval of it's children", + "- can repeat the interval a number of times or indefinitively", + "- press 'Shift-S' to start/pause/resume", + "- press 'Shift-L' to toggle loop/swing mode", + NULL + }; + rootNode->addChild(createHUD(createTextGroup(text))); + // add sequence of models from command line + osg::Sequence* seq = createSequence(arguments); + rootNode->addChild(seq); // add model to viewer. viewer.setSceneData(rootNode); - // register additional event handler - viewer.getEventHandlerList().push_front(new MyEventHandler(&seq)); + // add event handler to control sequence + viewer.getEventHandlerList().push_front(new SequenceEventHandler(seq)); // create the windows and run the threads. viewer.realize();