Show
Ignore:
Timestamp:
11/15/04 13:03:33 (10 years ago)
Author:
robert
Message:

From Ulrich Hertlien, improved osgsequence example

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgsequence/osgsequence.cpp

    r1844 r3630  
    11// -*-c++-*- 
    22 
     3/* 
     4 * This application is open source and may be redistributed and/or modified    
     5 * freely and without restriction, both in commericial and non commericial 
     6 * applications,as long as this copyright notice is maintained. 
     7 *  
     8 * This application is distributed in the hope that it will be useful, 
     9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
     10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
     11*/ 
     12 
     13#include <osgText/Text> 
     14#include <osg/Geode> 
    315#include <osg/Group> 
     16#include <osg/Projection> 
    417#include <osg/Sequence> 
    518#include <osg/MatrixTransform> 
     
    1023 
    1124 
    12 // 
    13 // A simple demo demonstrating usage of osg::Sequence. 
    14 // 
    15  
    16 // simple event handler to start/stop sequences 
    17 class MyEventHandler : public osgGA::GUIEventHandler { 
     25// create text drawable at 'pos' 
     26osg::Geode* createText(const std::string& str, const osg::Vec3& pos) 
     27{ 
     28    // text drawable 
     29    osgText::Text* text = new osgText::Text; 
     30    text->setFont(std::string("fonts/arial.ttf")); 
     31    text->setPosition(pos); 
     32    text->setText(str); 
     33 
     34    // geode 
     35    osg::Geode* geode = new osg::Geode; 
     36    geode->addDrawable(text); 
     37 
     38    return geode; 
     39} 
     40 
     41osg::Node* createTextGroup(const char** text) 
     42{ 
     43    osg::Group* group = new osg::Group; 
     44 
     45    osg::Vec3 pos(120.0f, 800.0f, 0.0f); 
     46    const osg::Vec3 delta(0.0f, -60.0f, 0.0f); 
     47 
     48    // header 
     49    const char** t = text; 
     50    group->addChild(createText(*t++, pos)); 
     51    pos += delta; 
     52 
     53    // remainder of text under sequence 
     54    osg::Sequence* seq = new osg::Sequence; 
     55    group->addChild(seq); 
     56    while (*t) { 
     57        seq->addChild(createText(*t++, pos)); 
     58        seq->setTime(seq->getNumChildren()-1, 2.0f); 
     59        pos += delta; 
     60    } 
     61 
     62    // loop through all children 
     63    seq->setInterval(osg::Sequence::LOOP, 0,-1); 
     64 
     65    // real-time playback, repeat indefinitively 
     66    seq->setDuration(1.0f, -1); 
     67 
     68    // must be started explicitly 
     69    seq->setMode(osg::Sequence::START); 
     70 
     71    return group; 
     72} 
     73 
     74osg::Node* createHUD(osg::Node* node) 
     75{ 
     76    // absolute transform 
     77    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform; 
     78    modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF); 
     79    modelview_abs->setMatrix(osg::Matrix::identity()); 
     80    modelview_abs->addChild(node); 
     81 
     82    // 2D projection node 
     83    osg::Projection* projection = new osg::Projection; 
     84    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); 
     85    projection->addChild(modelview_abs); 
     86 
     87    // turn off lighting and depth test 
     88    osg::StateSet* state = modelview_abs->getOrCreateStateSet(); 
     89    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF); 
     90    state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); 
     91 
     92    return projection; 
     93} 
     94 
     95osg::Node* createScaledNode(osg::Node* node, float targetScale) 
     96{ 
     97    // create scale matrix 
     98    osg::MatrixTransform* transform = new osg::MatrixTransform; 
     99 
     100    const osg::BoundingSphere& bsphere = node->getBound(); 
     101    float scale = targetScale / bsphere._radius; 
     102    transform->setMatrix(osg::Matrix::scale(scale,scale,scale)); 
     103    transform->setDataVariance(osg::Object::STATIC); 
     104    transform->addChild(node); 
     105 
     106    // rescale normals 
     107    osg::StateSet* state = transform->getOrCreateStateSet(); 
     108    state->setMode(GL_NORMALIZE, osg::StateAttribute::ON); 
     109 
     110    return transform; 
     111} 
     112 
     113osg::Sequence* createSequence(osg::ArgumentParser& arguments) 
     114{ 
     115    // assumes any remaining parameters are models 
     116    osg::Sequence* seq = new osg::Sequence; 
     117    for (int i = 1; i < arguments.argc(); ++i) 
     118    { 
     119        // load model 
     120        osg::Node* node = osgDB::readNodeFile(arguments[i]); 
     121        if (!node) { 
     122            continue; 
     123        } 
     124        seq->addChild(createScaledNode(node, 100.0f)); 
     125        seq->setTime(seq->getNumChildren()-1, 1.0f); 
     126    } 
     127 
     128    // loop through all children 
     129    seq->setInterval(osg::Sequence::LOOP, 0,-1); 
     130 
     131    // real-time playback, repeat indefinitively 
     132    seq->setDuration(1.0f, -1); 
     133 
     134    return seq; 
     135} 
     136 
     137// event handler to control sequence 
     138class SequenceEventHandler : public osgGA::GUIEventHandler 
     139{ 
    18140public: 
    19     /// Constructor. 
    20     MyEventHandler(std::vector<osg::Sequence*>* seq)  
     141    SequenceEventHandler(osg::Sequence* seq) 
    21142    { 
    22143        _seq = seq; 
    23144    } 
    24145 
    25     /// Handle events. 
     146    // handle keydown events 
    26147    virtual bool handle(const osgGA::GUIEventAdapter& ea, 
    27148                        osgGA::GUIActionAdapter&) 
    28149    { 
    29         bool handled = false; 
    30  
    31         if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) 
    32         { 
    33             const char keys[] = "!@#$%^&*()"; 
    34             for (unsigned int i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) { 
    35                 if (i < _seq->size() && ea.getKey() == keys[i]) 
     150        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) { 
     151            switch (ea.getKey()) { 
     152            case 'S': 
    36153                { 
    37                     // toggle sequence 
    38                     osg::Sequence* seq = (*_seq)[i]; 
    39                     osg::Sequence::SequenceMode mode = seq->getMode(); 
    40                     switch (mode) { 
    41                     case osg::Sequence::START: 
    42                         seq->setMode(osg::Sequence::PAUSE); 
    43                         break; 
    44                     case osg::Sequence::STOP: 
    45                         seq->setMode(osg::Sequence::START); 
    46                         break; 
    47                     case osg::Sequence::PAUSE: 
    48                         seq->setMode(osg::Sequence::RESUME); 
    49                         break; 
    50                     default: 
    51                         break; 
    52                     } 
    53                     std::cerr << "Toggled sequence " << i << std::endl; 
    54                     handled = true; 
     154                    osg::Sequence::SequenceMode mode = _seq->getMode(); 
     155                    if (mode == osg::Sequence::STOP) { 
     156                        mode = osg::Sequence::START; 
     157                        std::cerr << "Start" << std::endl; 
     158                    } 
     159                    else if (mode == osg::Sequence::PAUSE) { 
     160                        mode = osg::Sequence::RESUME; 
     161                        std::cerr << "Resume" << std::endl; 
     162                    } 
     163                    else { 
     164                        mode = osg::Sequence::PAUSE; 
     165                        std::cerr << "Pause" << std::endl; 
     166                    } 
     167                    _seq->setMode(mode); 
    55168                } 
     169                break; 
     170            case 'L': 
     171                { 
     172                    osg::Sequence::LoopMode mode; 
     173                    int begin, end; 
     174                    _seq->getInterval(mode, begin, end); 
     175                    if (mode == osg::Sequence::LOOP) { 
     176                        mode = osg::Sequence::SWING; 
     177                        std::cerr << "Swing" << std::endl; 
     178                    } 
     179                    else { 
     180                        mode = osg::Sequence::LOOP; 
     181                        std::cerr << "Loop" << std::endl; 
     182                    } 
     183                    _seq->setInterval(mode, begin, end); 
     184                } 
     185                break; 
     186            default: 
     187                break; 
    56188            } 
    57189        } 
    58190 
    59         return handled; 
    60     } 
    61  
    62     /// accept visits. 
     191        return false; 
     192    } 
     193 
     194    // accept visits 
    63195    virtual void accept(osgGA::GUIEventHandlerVisitor&) {} 
    64196 
    65197private: 
    66     std::vector<osg::Sequence*>* _seq; 
     198    osg::ref_ptr<osg::Sequence> _seq; 
    67199}; 
    68200 
    69 osg::Sequence* generateSeq(osg::Sequence::LoopMode mode, 
    70                            float speed, int nreps, 
    71                            std::vector<osg::Node*>& model) 
    72 { 
    73     osg::Sequence* seqNode = new osg::Sequence; 
    74  
    75     // add children, show each child for 1.0 seconds 
    76     for (unsigned int i = 0; i < model.size(); i++) { 
    77         seqNode->addChild(model[i]); 
    78         seqNode->setTime(i, 1.0f); 
    79     } 
    80  
    81     // interval 
    82     seqNode->setInterval(mode, 0, -1); 
    83  
    84     // speed-up factor and number of repeats for entire sequence 
    85     seqNode->setDuration(speed, nreps); 
    86  
    87     // stopped 
    88     seqNode->setMode(osg::Sequence::STOP); 
    89  
    90     return seqNode; 
    91 } 
    92201 
    93202int main( int argc, char **argv ) 
     
    133242    } 
    134243     
    135     // assumes any remaining parameters are models 
    136     std::vector<osg::Node*> model; 
    137     for (int i = 1; i < arguments.argc(); i++) 
    138     { 
    139         std::cerr << "Loading " << arguments[i] << std::endl; 
    140         osg::Node* node = osgDB::readNodeFile(arguments[i]); 
    141         if (node) 
    142             model.push_back(node); 
    143     } 
    144     if (model.empty()) { 
    145         return -1; 
    146     } 
    147  
    148244    // root 
    149245    osg::Group* rootNode = new osg::Group; 
    150246 
    151     // create sequences 
    152     std::vector<osg::Sequence*> seq; 
    153  
    154     const osg::Sequence::LoopMode mode[] = { osg::Sequence::LOOP, 
    155                                              osg::Sequence::SWING, 
    156                                              osg::Sequence::LOOP }; 
    157     const float speed[] = { 0.5f, 1.0f, 1.5f }; 
    158     const int nreps[] = { -1, 5, 1 }; 
    159  
    160     float x = 0.0f; 
    161     for (unsigned int j = 0; j < (sizeof(speed) / sizeof(speed[0])); j++) { 
    162         osg::Sequence* seqNode = generateSeq(mode[j], speed[j], nreps[j], 
    163                                              model); 
    164         if (!seqNode) 
    165             continue; 
    166         seq.push_back(seqNode); 
    167  
    168         // position sequence 
    169         osg::Matrix matrix; 
    170         matrix.makeTranslate(x, 0.0, 0.0); 
    171  
    172         osg::MatrixTransform* xform = new osg::MatrixTransform; 
    173         xform->setMatrix(matrix); 
    174         xform->addChild(seqNode); 
    175  
    176         rootNode->addChild(xform); 
    177  
    178         x += seqNode->getBound()._radius * 1.5f; 
    179     } 
    180  
     247    // create info display 
     248    const char* text[] = { 
     249        "osg::Sequence Mini-Howto", 
     250        "- can be used for simple flip-book-style animation", 
     251        "- is subclassed from osg::Switch", 
     252        "- assigns a display duration to each child", 
     253        "- can loop or swing through an interval of it's children", 
     254        "- can repeat the interval a number of times or indefinitively", 
     255        "- press 'Shift-S' to start/pause/resume", 
     256        "- press 'Shift-L' to toggle loop/swing mode", 
     257        NULL 
     258    }; 
     259    rootNode->addChild(createHUD(createTextGroup(text))); 
     260 
     261    // add sequence of models from command line 
     262    osg::Sequence* seq = createSequence(arguments); 
     263    rootNode->addChild(seq); 
    181264 
    182265    // add model to viewer. 
    183266    viewer.setSceneData(rootNode); 
    184267 
    185     // register additional event handler 
    186     viewer.getEventHandlerList().push_front(new MyEventHandler(&seq)); 
     268    // add event handler to control sequence 
     269    viewer.getEventHandlerList().push_front(new SequenceEventHandler(seq)); 
    187270 
    188271    // create the windows and run the threads.