From Ulrich Hertlien, improved osgsequence example

This commit is contained in:
Robert Osfield
2004-11-15 12:03:33 +00:00
parent 4094c3f058
commit 76c970da5d

View File

@@ -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 <osgText/Text>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Projection>
#include <osg/Sequence>
#include <osg/MatrixTransform>
@@ -9,86 +22,182 @@
#include <osgProducer/Viewer>
//
// 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<osg::Sequence*>* 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<osg::Sequence*>* _seq;
osg::ref_ptr<osg::Sequence> _seq;
};
osg::Sequence* generateSeq(osg::Sequence::LoopMode mode,
float speed, int nreps,
std::vector<osg::Node*>& 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<osg::Node*> 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<osg::Sequence*> 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();