You must implement an object under each AnimationPathCallBack, create and link each with a visitor of osg::Node witch has an AnimationPathCallBack.
 I have already make this job in the cooki3d api the source code will be available as soon as possible (Perhaps Monday).
This class can help you.
 You can make play, stop, pause, forward (with setPosition), backward (with setPosition), resize (with setDuration).

Animation.h
/** -*-c++-*- *************************************************************\
* (Remise à zéro le 24/10/04 et le 23/06/06)
* File:          Animation.h
* Creation date: June 23, 2006 18:26
* Author:        Bertrand Greslier
*                Entreprise Individuelle
* Purpose:       Declaration of class 'Animation'
*
* Copyright 2006, Bertrand Greslier
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
*
\**************************************************************************/
#ifndef _ANIMATION_H
#define _ANIMATION_H

//@START_USER1
#include "MediaEvaluable.h"


#include <osg/Matrixf>
#include <osg/Matrixd>
#include <osg/Quat>
#include <osg/NodeCallback>
#include <osg/AnimationPath>

#include <map>
#include <float.h>


#include "XMLUtil.h "
#include "LoaderGeneric.h"

namespace cooki3d{
//@END_USER1


/[EMAIL PROTECTED]
classe ...
*/

class AFX_EXT_CLASS Animation
    : public MediaEvaluable
{

//@START_USER2
  public :
    typedef map<string,Animation*,less<string > > mapStrAnim;
   
//@END_USER2

//
// Group: ClassBuilder methods
//

private:
    void ConstructorInclude();
    void DestructorInclude();

//
// Group: Media
//

public:
    virtual void setPosition(double sec);
    virtual bool isPlay();
    virtual bool isPause();
    virtual double eval(std::string methode, double args[10], int nbParam);
    double getDebut();
    virtual double getDuration();
    double getFin();
    virtual void pause();
    virtual void play();
    virtual double getPosition();
    virtual void setDuration(double duree);
    virtual void stop();

//
// Group: Modes
//

public:
    std::string getLoopMode();
    void setLoopMode(std::string mode);
    std::string traduireLoopModeFromEnumToString(osg::AnimationPath::LoopMode mode);
    osg::AnimationPath::LoopMode traduireLoopModeFromStringToEnum(std::string mode);

//
// Group: load
//

public:
    void init();
    static bool linkAnimation(osg::Node* n, const std::string& pickName,
                              LoaderGeneric* loader);
    static Evaluable* staticCreate(BD* pBD);
    bool loadXML(const xmlpp::Node* node, LoaderXML* loaderXML);
    virtual void setApc(osg::AnimationPathCallback* pApc);
    static bool checkAllInstances(LoaderGeneric* loader);
    virtual bool check();
    Animation(BD* pBD);
    Animation(Animation& anim);
    virtual ~Animation();

//
// Group: zdata
//

protected:
    osg::AnimationPathCallback* _apc;
    bool _automaticSet;
    std::string _bufferLoopMode;
    int _debut;
    int _fin;
    int _fps;
    std::string _nodeName;
    osg::AnimationPath* _path;
    osg::AnimationPath* _pathInit;

public:
    osg::AnimationPathCallback* getApc() const;
    bool getAutomaticSet() const;
    void setAutomaticSet(bool automaticSet);
    std::string getBufferLoopMode() const;
    int getFps() const;
    void setFps(int fps);
    std::string getNodeName() const;
    void setNodeName(std::string nodeName);

//
// Non-Grouped Members
//

//
// Non-Grouped Methods
//

public:
    virtual bool isAtomic();
};

#endif


#ifdef CB_INLINES
#ifndef _ANIMATION_H_INLINES
#define _ANIMATION_H_INLINES


//
// Group: zdata
//
/[EMAIL PROTECTED]
Returns the value of member '_apc'.
*/
inline osg::AnimationPathCallback* Animation::getApc() const
{//@CODE_1029
    return _apc;
}//@CODE_1029



/[EMAIL PROTECTED]
Returns the value of member '_automaticSet'.
*/
inline bool Animation::getAutomaticSet() const
{//@CODE_4375
    return _automaticSet;
}//@CODE_4375



/[EMAIL PROTECTED]
Set the value of member '_automaticSet' to 'automaticSet'.
*/
inline void Animation::setAutomaticSet(bool automaticSet)
{//@CODE_4376
    _automaticSet = automaticSet;
}//@CODE_4376



/[EMAIL PROTECTED]
Returns the value of member '_bufferLoopMode'.
*/
inline std::string Animation::getBufferLoopMode() const
{//@CODE_3931
    return _bufferLoopMode;
}//@CODE_3931



/[EMAIL PROTECTED]
Returns the value of member '_fps'.
*/
inline int Animation::getFps() const
{//@CODE_1020
    return _fps;
}//@CODE_1020



/[EMAIL PROTECTED]
Set the value of member '_fps' to 'fps'.
*/
inline void Animation::setFps(int fps)
{//@CODE_1021
    _fps = fps;
}//@CODE_1021



/[EMAIL PROTECTED]
Returns the value of member '_nodeName'.
*/
inline std::string Animation::getNodeName() const
{//@CODE_1014
    return _nodeName;
}//@CODE_1014



/[EMAIL PROTECTED]
Set the value of member '_nodeName' to 'nodeName'.
*/
inline void Animation::setNodeName(std::string nodeName)
{//@CODE_1015
    _nodeName = nodeName;
}//@CODE_1015



// End of Group: zdata

//@START_USER3
} //end of namespace cooki3d
//@END_USER3

#endif
#endif


Animation.cpp
/** -*-c++-*- *************************************************************\
* (Remise à zéro le 24/10/04 et le 23/06/06)
* File:          Animation.cpp
* Creation date: June 23, 2006 18:26
* Author:        Bertrand Greslier
*                Entreprise Individuelle
* Purpose:       Declaration of class 'Animation'
*
* Copyright 2006, Bertrand Greslier
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
*
\**************************************************************************/
//@START_USER1
//@END_USER1


// Master include file
#include " CookiMetier.h"


//@START_USER2
#include "Media.h"
#include "BD.h"
#include "Animation.h"
#include "XMLUtil.h"
#include "EnvironnementOSG.h"
//#include "MediaInterface.h"

namespace cooki3d {
//@END_USER2


//
// Group: Media
//
void Animation::setPosition(double sec)
{//@CODE_168
 
  //060621 le reset n'affecte plus _firstTime de la même facon...
  double time = getEnv()->getFrameStamp()->getReferenceTime();

  _apc->setPause(false);
  if (_apc->getAnimationPath() != _path) {
    _apc->setAnimationPath(_path);
    _apc->reset();
    _apc->_firstTime = /*_apc->_firstTime*/time - getDebut();
   
    cout<<"premiere utilisation sur setPosition"<<endl;
   
  }


  CTRACE(this,"setPosition")<<" passage"<<endl;
  _apc->reset();
   
  _apc->_firstTime = time - getDebut() - sec;

  getEnv()->requestRedraw();
  pause();

}//@CODE_168


bool Animation::isPlay()
{//@CODE_302
    
    return (_apc->getAnimationPath()==_path);
}//@CODE_302


bool Animation::isPause()
{//@CODE_303
   return isPlay() && _apc->_pause;
}//@CODE_303


double Animation::eval(std::string methode, double args[10], int nbParam)
{//@CODE_1201
    return Media::eval(methode,args,nbParam);
}//@CODE_1201


double Animation::getDebut()
{//@CODE_203
  //cout<<"GEtperiode="<<_path->getPeriod()<<endl;
  return double( (double(_debut)/_fps) );
}//@CODE_203


double Animation::getDuration()
{//@CODE_169
    return getFin()-getDebut();
}//@CODE_169


double Animation::getFin()
{//@CODE_202
  return double( (double(_fin)/_fps) - 0.00001);
}//@CODE_202


void Animation::pause()
{//@CODE_170
  _apc->setPause(true);
}//@CODE_170


void Animation::play()
{//@CODE_171
  //cout<<"Animation: Salut "<<endl;
 
  assertC( _apc->getAnimationPath() );
 
  if (_apc->getAnimationPath() != _path) {
    _apc->setAnimationPath(_path);
    _apc->reset();
    //060621 le reset n'affecte plus _firstTime de la même facon...
    double time = getEnv()->getFrameStamp()->getReferenceTime();
    _apc->_firstTime = /*_apc->_firstTime*/time - getDebut();
    //_path->setLoopMode(_loopMode);

    CTRACE(this,"play")<<"premiere utilisation"<<endl;
    //init();
  }
 
  //replay
  /*else if ((_loopMode == osg::AnimationPath::NO_LOOPING)  &&
    (_apc->getAnimationTime() > getFin()) && !_apc->_pause) {
    cout<<"_apc->getAnimationTime()"<<_apc->getAnimationTime()<<endl;
    _apc->reset();
    _apc->_firstTime -= getDebut();
    }*/
  
  //A eval
  //si animation non finie, il faut empiler dans le
  //TimerThread une action play avec un timer déclencheur
  //égale au restant de l'animation en cours
 
  _apc->setPause(false);

 
}//@CODE_171


double Animation::getPosition()
{//@CODE_304
  //double value;
  CERR(this,"getPosition")<<"cette méthode n'est pas implémentée"<<endl;
  return 0.0;
    //return value;
}//@CODE_304


void Animation::setDuration(double duree)
{//@CODE_632
 
  double dureeInit = getDuration();
  osg::AnimationPath::TimeControlPointMap& mapp=
    _path->getTimeControlPointMap();
 
  osg::AnimationPath::TimeControlPointMap::iterator it=mapp.begin();
  while (it != mapp.end()) {
    //double * ad= (double*)&(it->first);
    //*ad = it->first * (duree/dureeInit);
    *(const_cast<double*>(&(it->first))) = it->first * (duree/dureeInit);
    it++;
  }
  it--;
  _fin = int(double(_fin) * (duree/dureeInit));
 
}//@CODE_632


void Animation::stop()
{//@CODE_172
  //_apc->reset(); 
   CTRACE(this,"stop")<<endl;
   //_apc->_firstTime -= getDebut();
   //_apc->setPause(true);
   _apc->setAnimationPath(_pathInit);
   _apc->setPause( false ); //060620
}//@CODE_172


// End of Group: Media


//
// Group: Modes
//
std::string Animation::getLoopMode()
{//@CODE_1868
    return traduireLoopModeFromEnumToString(_path->getLoopMode());
}//@CODE_1868


void Animation::setLoopMode(std::string mode)
{//@CODE_208
    _path->setLoopMode(traduireLoopModeFromStringToEnum(mode));
}//@CODE_208


std::string Animation::traduireLoopModeFromEnumToString(osg::AnimationPath::LoopMode mode)
{//@CODE_1862
    switch (mode){
    case osg::AnimationPath::NO_LOOPING:  
        return "NO_LOOPING";
    case osg::AnimationPath::LOOP:   
        return "LOOP";
    case osg::AnimationPath::SWING:
        return "SWING";             
    }
    assertC(0);   
    return NULL;
}//@CODE_1862


osg::AnimationPath::LoopMode Animation::traduireLoopModeFromStringToEnum(std::string mode)
{//@CODE_210
  if (mode == "NO_LOOPING")
    return osg::AnimationPath::LoopMode(osg::AnimationPath::NO_LOOPING);
  if (mode == "LOOP")
    return osg::AnimationPath::LoopMode(osg::AnimationPath::LOOP);
  if (mode == "SWING")
    return osg::AnimationPath::LoopMode(osg::AnimationPath::SWING);
  CTRACEs("Animation::traduireLoopModeFromStringToEnum")
    <<"mode ="<<mode<<endl;
  CTRACEnext<<"mode.length() ="<<mode.length()<<endl;
  assertC(0);
  return osg::AnimationPath::LoopMode(osg::AnimationPath::SWING);//antiwarning
}//@CODE_210


// End of Group: Modes


//
// Group: load
//
void Animation::init()
{//@CODE_212
  _apc->setAnimationPath(_pathInit);
  _apc->reset();
  //060621 le reset n'affecte plus _firstTime de la même facon...
  //_apc->_firstTime = _apc->_firstTime - getDebut();
 
 
  //_path->setLoopMode(_loopMode);
  setLoopMode(_bufferLoopMode);

  CTRACEs("Animation::linkAnimation")<<" init animation "
                     <<getName()<<"( "<<this
                     <<" )"<<endl;
 
}//@CODE_212


bool Animation::linkAnimation(osg::Node* n, const std::string& pickName,
                              LoaderGeneric* loader)
{//@CODE_1196

  //CTRACEs("Animation::linkAnimation")
  //<<"av assert"<<endl;

  assertC(n);
 
  
 
  bool res=false;

  //CTRACEs("Animation::linkAnimation")
  //<<"av getName"<<endl;
  //std::string pickName = n->getName();

  //BUG JVM typeid plante => non probleme antéteur!!
  //CTRACEs("Animation::linkAnimation")
  //<<" passage linkAnimation su le Node "<<pickName
  //<<"("<<typeid(*n).name()<<")"<<endl;
 
 
  //CTRACEs("Animation::linkAnimation")
  //<<"ap getName"<<endl;
 
  if ( n->getUpdateCallback() ){
   
    osg::AnimationPathCallback *apc=dynamic_cast<osg::AnimationPathCallback *>
      (n->getUpdateCallback());
   
    if (apc) {

      BD::EvaluableIterator itMed(loader->getBD());

      CTRACEs("Animation::linkAnimation")<<"search "<<pickName<<"..."<<endl;

      Animation * anim ;
      //for (unsigned int i=0; i<listeM.size (); i++){
      while ( ++itMed ){
    anim=dynamic_cast<Animation *>(itMed.Get());
    //TODO améliorer le ratio qui catastrophique -> registre
    //cout<<" traitement "<<anim<<endl;

    if (anim
        && anim->isAtomic()
        && (anim->getNodeName() == pickName) ) {
     
      if (anim->getApc()){
        CERRs("Animation::linkAnimation")
          <<" APC not NULL for "
          <<anim<<", pickName=\""<<pickName<<"\" "
          <<"instance =\""<<anim->getName()<<"\""
          <<" is already linked !"<<endl;
      }else {
       
        anim->setApc(apc);       
        anim->init();     
        res=true;
      }
     
    }
   
      }

    }
    else {
      CWARNs("Animation::linkAnimation")<<
    "suspect dynamic_cast<osg::AnimationPathCallback *> fail !"<<endl;
    }
   
  }else {
  }
  return res;
 
}//@CODE_1196


Evaluable* Animation::staticCreate(BD* pBD)
{//@CODE_3032
  /*Animation * animLoader = new Animation();
  animLoader->setNameWithoutPrefix( "staticLoader" );
  return animLoader;*/
  return new Animation(pBD);
}//@CODE_3032


bool Animation::loadXML(const xmlpp::Node* node, LoaderXML* loaderXML)
{//@CODE_3051
  //staticLoader 1 animation XML => n animation instance
  //  return Animation::staticLoadXML(node);
 
  XMLUtil xml(node);

     
  setName( xml.getFirstText("nom") );
  _automaticSet = xml.getFirstText("automaticSet") == "true";
  if (! _automaticSet ){
    _debut=atoi(xml.getFirstText("debut").c_str());
    _fin=atoi(xml.getFirstText("fin").c_str());
    _fps=atoi(xml.getFirstText("fps").c_str());
  }
  _bufferLoopMode = xml.getFirstText("mouv");
  setPlayOnStart( xml.getFirstText("playOnStart")=="true");

  if (isAtomic()){
    setNodeName(xml.getFirstText("nodeName"));
    CINFOs<<"XML: new animation \""<<getNodeName()
      <<"\" ("<<getName()<<")"<<endl;
  }

 
 
  return true;

}//@CODE_3051


void Animation::setApc(osg::AnimationPathCallback* pApc)
{//@CODE_3168

  CINFOs<<"Animation link \""<<getNodeName()<<"\"("<<getName()
    <<", "<<this<<") with osg::APC "<<endl;
  //CTRACEs("Animation::linkAnimation")" setApc sur "
  //<<pickName<<endl;

  _apc = pApc;
  //if (_path) delete _path;
  _path=new osg::AnimationPath;
 
  osg::AnimationPath * origin= pApc->getAnimationPath();

  CTRACE(this,"setApc")<<"origin->getFirstTime() = "
               <<origin->getFirstTime()<<endl;
  CTRACE(this,"setApc")<<"origin->getLastTime() = "
               <<origin->getLastTime()<<endl;
 
  if (/*! bInitFromProperties*/ _automaticSet){
    _debut = int( origin->getFirstTime() * _fps );
    _fin = int( origin->getLastTime() * _fps );
  }
 
  //sinon quelques vérifications
  else if ((origin->getFirstTime() > getDebut()) ||
       (origin->getLastTime() < getFin())) {
   
    CTRACE(this,"setApc")<<"Animation path choisi incohérent"<<endl;
    CTRACE(this,"setApc")<<"origin->getFirstTime() = "<<origin->getFirstTime()
               <<endl;     
    CTRACE(this,"setApc")<<"origin->getLastTime()= "<<origin->getLastTime()
               <<endl;
    CTRACE(this,"setApc")<<"getDebut() = "<<getDebut()<<endl;
    CTRACE(this,"setApc")<<"getFin() = "<<getFin()<<endl;
   
   
    CERR(this,"setApc")<<"incoherent parameters => the object "<<getName()
               <<" will be initialized automaticaly from "
               <<"the properties of the apc (AnimationPathCallback)"
               <<" as if \"automaticSet\" have been cheked "
               <<endl;
    setApc( pApc );
    //" va être détruit"<<endl;
    //this->~Animation();
   
    return;
  }
 
  //création du premier et denier point de controle
  osg::AnimationPath::ControlPoint p;
  if (!origin->getInterpolatedControlPoint(getDebut(),p)) assertC(0);
  _path->insert(getDebut(),p);
  if (!origin->getInterpolatedControlPoint(getFin(),p)) assertC(0);
  _path->insert(getFin(),p);
 
  CTRACE(this,"setApc")<<"pour deb,fin ="<<getDebut()
               <<", "<<getFin()<<endl<<endl;
 
  //récuparation des points de controles existant
  osg::AnimationPath::TimeControlPointMap& mapp=
    origin->getTimeControlPointMap();
 
  osg::AnimationPath::TimeControlPointMap::iterator it= mapp.begin();
  while (it != mapp.end()) {
    if ((it->first > getDebut()+0.00001) && (it->first < getFin()-0.00001)) {
      _path->insert(it->first,it->second);
      //cout<<"add time control point ="<<it->first<<endl;
    }
    it++;
  }
 
  //création d'un path à une seule image pour que l'objet soit
  //en place dès le lancement ou lors d'un stop
  _pathInit=new osg::AnimationPath;
  if (!origin->getInterpolatedControlPoint(getDebut(),p)) assertC(0);
  _pathInit->insert(getDebut(),p);
 
 
  //référencement pour indiquer que l'on possère un
  //exemplaire du pointeur et qu'il ne faut pas le
  //détruire
  _path->ref();
  _pathInit->ref();   
 
}//@CODE_3168


bool Animation::checkAllInstances(LoaderGeneric* loader)
{//@CODE_3171

  BD::EvaluableIterator itAnim(loader->getBD());
 
  Animation * anim;

  bool resultOk = true;
  
  while (++itAnim){
   
    anim=dynamic_cast<Animation *>(itAnim.Get());
   
    if (anim && anim->getName() != "staticLoader") {
      resultOk = resultOk && anim->check();
    }

  }
  
  return resultOk;
}//@CODE_3171


/[EMAIL PROTECTED]
Check the integritry of the object
*/
bool Animation::check()
{//@CODE_3172
    bool resultOk = _path != NULL && _pathInit != NULL && _apc != NULL;

    if (!resultOk){
      CERR(this,"check")<<" instance \""<<getName()
            <<"\", node \""<<getNodeName()
            <<"\" is not linked !!"<<endl;
    }
   
    return resultOk;
}//@CODE_3172


/[EMAIL PROTECTED]
Constructor method.
*/
Animation::Animation(BD* pBD) //@INIT_167
  : MediaEvaluable(pBD)
    , _apc(NULL)
    , _automaticSet(true)
    , _bufferLoopMode("NO_LOOPING") 
    , _debut(0)
    , _fin(100)
    , _fps(30)     
    , _nodeName()
    , _path(NULL)  
    , _pathInit(NULL)
  
{//@CODE_167
    ConstructorInclude();
       
    // Put in your own code   
}//@CODE_167


/[EMAIL PROTECTED]
Constructor method.
*/
Animation::Animation(Animation& anim) //@INIT_3982
    : MediaEvaluable(anim.getBD())
      , _apc(/*anim._apc*/NULL)
      , _automaticSet(true) 
      , _bufferLoopMode(anim._bufferLoopMode)
      , _debut(anim._debut)
      , _fin(anim._fin)
      , _fps(anim._fps) 
      , _nodeName(/*anim._nodeName*/"") 
      , _path(anim._path)
      , _pathInit(/*anim._pathInit*/NULL)
       
{//@CODE_3982
    ConstructorInclude();

    // Put in your own code
}//@CODE_3982


/[EMAIL PROTECTED]
Destructor method.
*/
Animation::~Animation()
{//@CODE_162
    DestructorInclude();

    // Put in your own code
}//@CODE_162


// End of Group: load

bool Animation::isAtomic()
{//@CODE_3923

    return true;
}//@CODE_3923


//{{AFX DO NOT EDIT CODE BELOW THIS LINE !!!

/[EMAIL PROTECTED]
Method which must be called first in a constructor.
*/
void Animation::ConstructorInclude()
{
}


/[EMAIL PROTECTED]
Method which must be called first in a destructor.
*/
void Animation::DestructorInclude()
{
}


// Methods for the relation(s) of the class

//}}AFX DO NOT EDIT CODE ABOVE THIS LINE !!!

//@START_USER3
} //end of namespace cooki3d



On 11/2/06, [EMAIL PROTECTED] < [EMAIL PROTECTED]> wrote:
Hi Jae,
 
I did this very same thing.  Actually I wanted mine to not just PAUSE, but to play forward, reversem and scrub with the mouse.  I was reading in an entire scene graph from a file (A .lws, lightwave scene actually), so the AnimationPath stuff was already built in and I did not want to mess with it, or even have to traverse and find the handles for all of the animation paths.
 
What I really wanted to do was be able to set the time myself rather than let the Viewer do it for me.  I personally like using osgProducer::OsgCameraGroup rather than the Viewer.  The Viewer keeps track of a timer and does all of the following stuff under the hood, and I couldn't find out how to modify that easily (maybe there is Robert?).
 
What is happening underneath is that you create an osg::FrameStamp, set its time and frame number to whatever you want, (normally you keep track of a little timer and update it, but this way you can set the time yourself), then create an osgUtil::UpdateVisitor and set its framestamp to the one you just created, then you have the scene graph accept the update visitor.
 
-- Rick
 
 
 
 
 
Hi Jae,
The osg::AnimationPathCallback has code in it for pausing, restarting.
 You attach the AnimationPath to the AnimationPathCallback, then
attach this to the Node you want to animate.
Robert.
 
 
Hi,
Currently I am working on a viewer with scenario feature.
Within the scenario, the user can load a txt file with list of camera position and rotation and the viewer produce a camera path.
This has been achieved by useing the osg::animationPath and osg::Timer.
Now I would like to add start, stop and pause. However I could not find any documentation about stop the animationPath.
Is this possible? If so how?
If it is not possible, is it going to be added in future?
Thank you in advance
Jae

_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/




--
Bertrand Greslier
http://www.cooki3d.org
_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/

Reply via email to