OpenSceneGraph Forum Forum Index OpenSceneGraph Forum
Official forum which mirrors the existent OSG mailing lists. Messages posted here are forwarded to the mailing list and vice versa.
 
   FAQFAQ    SearchSearch    MemberlistMemberlist    RulesRules    UsergroupsUsergroups    RegisterRegister 
 Mail2Forum SettingsMail2Forum Settings  ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
   AlbumAlbum  OpenSceneGraph IRC ChatOpenSceneGraph IRC Chat   SmartFeedSmartFeed 

Get Animation current time


 
Post new topic   Reply to topic    OpenSceneGraph Forum Forum Index -> General
View previous topic :: View next topic  
Author Message
dhhabyc
User


Joined: 17 Nov 2018
Posts: 24

PostPosted: Thu Dec 27, 2018 5:54 pm    Post subject:
Get Animation current time
Reply with quote

Hello,

I have several AnimationPath intances for a number of moving objects. Each object has the same number of ControlPoints on their path.

I need to know if there is a proper way to retrieve the current time of the animation (using a callback, for instance). I need this number in order to display it on another part of the main application (Qt app).

Any pointers will be very much appreciated.

Thank you!

Cheers,
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12321

PostPosted: Fri Dec 28, 2018 1:22 pm    Post subject:
Get Animation current time
Reply with quote

HI Diego,

The OSG uses an osg::FrameStamp for each new frame, this is accessible
from the Viewer and the different traversals like
UpdateVisitor/EventVisitor/CulllVisitor and the draw traversal.
Individual animations like AnimantionPath can have their own local
animation speed that take the FrameStamp's SimulationTime to compute
the local animation time to use.


Robert.

On Thu, 27 Dec 2018 at 18:01, Diego Mancilla <> wrote:
Quote:

Hello,

I have several AnimationPath intances for a number of moving objects. Each object has the same number of ControlPoints on their path.

I need to know if there is a proper way to retrieve the current time of the animation (using a callback, for instance). I need this number in order to display it on another part of the main application (Qt app).

Any pointers will be very much appreciated.

Thank you!

Cheers,

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=75354#75354








------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
dhhabyc
User


Joined: 17 Nov 2018
Posts: 24

PostPosted: Fri Dec 28, 2018 2:15 pm    Post subject:
Reply with quote

Hello Robert,

First of all, thank you for your answer. I'm just starting to use OSG so I'm learning as I go.

So, my issue is a little more complicated (I think).

I have serveral AnimationPath instances. Each one with a AnimationPathCallback derived class attached to it. So, the thing is that I want to retrieve current animation time to the main application, ideally without having to traverse each animated node.

Context:

I have a Qt app with an osg::Viewer embedded (subclassing QOpenGLWidget), so the objective is to handle the "animation timeline" through a QSlider.

So:
1 - Can I, from the osg::FrameStamp instance "reconstruct" the current animation time from the AnimationPath instances or from anywhere else?

2- Besides the "while (!viewer.done())..." loop, is there a way to control the time sampling of the animation? i.e. the times at which the AnimationPath::getInterpolatedControlPoint method is called (from the AnimationPathCallback::update method)?

Thank you again, for your help.

Cheers,
Diego
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12321

PostPosted: Sun Dec 30, 2018 8:49 am    Post subject:
Get Animation current time
Reply with quote

Hi Diego,

On Fri, 28 Dec 2018 at 14:31, Diego Mancilla <> wrote:
Quote:
So:
1 - Can I, from the osg::FrameStamp instance "reconstruct" the current animation time from the AnimationPath instances or from anywhere else?

The FrameStamp is set up in the Viewer::advance(..) method, you can
pass a simulation time as a double into this method() or the slightly
higher level Viewer::frame(..) method that will call advance() and the
frame traversals for you.

You can subclass from Viewer and override advance() is you so wished.

Quote:
2- Besides the "while (!viewer.done())..." loop, is there a way to control the time sampling of the animation? i.e. the times at which the AnimationPath::getInterpolatedControlPoint method is called (from
the AnimationPathCallback::update method)?

The above suggestions is the standard way of doing it. If this
doesn't suit then writing your own AnimationPathCallback might the
thing you want.

Robert.


------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
dhhabyc
User


Joined: 17 Nov 2018
Posts: 24

PostPosted: Fri Jan 04, 2019 3:00 pm    Post subject:
Reply with quote

Hello Robert,

Thank you again for your answer.

Regarding your question "the AnimationPathCallback::update method)?": yes, from the source:

Code:
void AnimationPathCallback::update(osg::Node& node)
{
    AnimationPath::ControlPoint cp;
    if (_animationPath->getInterpolatedControlPoint(getAnimationTime(),cp))
    {
        AnimationPathCallbackVisitor apcv(cp,_pivotPoint,_useInverseMatrix);
        node.accept(apcv);
    }
}



I ended up writing my own AnimationPathCallback for manipulating the animation time though the variables _firstTime, _latestTime and _timeOffset; and exposing AnimationPathCallbackVisitor class to my code in order to force position changes. Maybe my solution is rather far-fetched, but for now it works. Also, I'm using a dummy AnimationPathCallback in order to expose current animation time to Qt.

I have another question rather technical. As per now a have a lot of moving objects. I'm using standard AnimationPath instances for each one of them. Also y have a lot a control points for each one (20k+). So filling the AnimationPaths instances is very slow. Then:

1- Can I using OpenMP or standard Qt threading parallelize the insertion of control points?
2- Are osg classes threadsafe? I mean, can I send the generation (filling) of each AnimationPath on a different thread (and then use the addChild method)?
3- Is there another alternative to improve performance on this matter?


Cheers,
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12321

PostPosted: Fri Jan 04, 2019 4:48 pm    Post subject:
Get Animation current time
Reply with quote

Hi Diego,

On Fri, 4 Jan 2019 at 16:16, Diego Mancilla <> wrote:
Quote:
I have another question rather technical. As per now a have a lot of moving objects. I'm using standard AnimationPath instances for each one of them. Also y have a lot a control points for each one (20k+). So filling the AnimationPaths instances is very slow. Then:

1- Can I using OpenMP or standard Qt threading parallelize the insertion of control points?

Multi-threading adds it's own overhead and complexity, one should
avoid if you can.

Quote:
2- Are osg classes threadsafe? I mean, can I send the generation (filling) of each AnimationPath on a different thread (and then use the addChild method)?

Most low level OSG methods are deliberately not made thread safe as
the overhead and syncronization required would lead to lower
performance. The types of multi-threading the OSG does support are
high level multi-threading, such as for database paging or viewer
level threading.

Quote:
3- Is there another alternative to improve performance on this matter?

The best solution totally depends on the specifics of the problem you
are trying to solve. From the description it sounds like AnimationPath
and AnimationPathCallback won't scale well to handle what you want
from them. There were never designed for massive numbers of control
points, let alone cases where control points are being added
dynamically.

However, the OSG is written to be extensible and customizable so if
the off the shelf features don't do exactly what you want or perform
well for your particular usage model then you can roll your own, and
as the OSG is open source you can learn from the exisiing
implementations to see how they hook into the rest of the OSG, so in
your own implementations you can follow this.

So for you, it may well be best to just write your own
AnimationPath+Callback scheme that provides a good public interface
that suits your needs and an internal implementation that performance
well for you usage case.

It may be even that you'd want to start writing really custom schemes
that involve the shaders as well as high level custom interfaces. For
instance if you have 10's of thousands of objects that are all the
same but all have different positions you can use geometry instancing
and pack the positions into uniform arrays or textures and upack the
positions in the vertex shader and place the objects. This way you
could just update an array of positions once per frame and all the
objects would update. If you had an animation path that had regular
intervals then potentially you encode this into one or more 1D
textures and look up the position, rotation and scale from this
texture.

Robert.


------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
dhhabyc
User


Joined: 17 Nov 2018
Posts: 24

PostPosted: Mon Jan 07, 2019 7:30 pm    Post subject:
Reply with quote

Hello Robert,

Thank you very much for you complete response.

I'm trying to do what you suggest and have my on AnimationPath/AnimationPathCallback classes that handle my data. But I stumble into a problem.

When I subclass AnimationPath and AnimationPathCallback I have no problems. But when I wrote my own classes, from scratch my application crashes.

In order to achieve what I want, I pass a pointer to a custom data container class to my AnimationPath class (I called it MobilesAnimationPath) from my main application. I tried to keep most part of the architecture of AnimationPath, but I eliminate the TimeControlPointMap container. So, now my class generates the control points from the data pointed from custom data pointer class.


So, for instance, my custom Path class looks like this:

Code:
#include "MobileObject.h"
#include <osg/AnimationPath>
#include <osg/Object>

using namespace osg;

class MobilesAnimationPath: public virtual osg::Object
{
public:
   MobilesAnimationPath();
   MobilesAnimationPath(const MobilesAnimationPath &, const osg::CopyOp & copyop = osg::CopyOp::SHALLOW_COPY);
   MobilesAnimationPath(MobileObject & mobile);

   META_Object(osg, MobilesAnimationPath); //Visual Studio complains about this line, but compiles... : "function definition for META_Object not found"

   enum LoopMode
   {
      SWING,
      LOOP,
      NO_LOOPING
   };

   void setLoopMode(LoopMode loopMode);
   LoopMode getLoopMode() const;

   virtual bool getInterpolatedControlPoint(double time, osg::AnimationPath::ControlPoint & cp) const;

   double getFirstTime() const;
   double getLastTime() const;
   double getPeriod() const;

protected:
   ~MobilesAnimationPath(){};

private:
   MobileObject * _mobile;
   LoopMode _loopMode;

};


And the implementation.

Code:
#include "MobilesAnimationPath.h"

MobilesAnimationPath::MobilesAnimationPath()
   :_loopMode(NO_LOOPING)
   ,_mobile(nullptr)
{
}


MobilesAnimationPath::MobilesAnimationPath(const MobilesAnimationPath& ap, const osg::CopyOp& copyop)
   :osg::Object(ap, copyop)
   ,_loopMode(ap._loopMode)
   ,_mobile(ap._mobile)
{
}

MobilesAnimationPath::MobilesAnimationPath(MobileObject & mobile)
   :_loopMode(NO_LOOPING)
{
   _mobile = &mobile;
}

void MobilesAnimationPath::setLoopMode(LoopMode loopMode)
{
   _loopMode = loopMode;
}

MobilesAnimationPath::LoopMode MobilesAnimationPath::getLoopMode() const
{
   return _loopMode;
}

double MobilesAnimationPath::getFirstTime() const
{
   if (_mobile != nullptr)
   {
      if (_mobile->dataLoaded())
      {
         return _mobile->getFirstTime();
      }
   }
   return 0.0;
}

double MobilesAnimationPath::getLastTime() const
{
   if (_mobile != nullptr)
   {
      if (_mobile->dataLoaded())
      {
         return _mobile->getLastTime();
      }
   }
   return 0.0;
}

double MobilesAnimationPath::getPeriod() const
{
   if (_mobile != nullptr)
   {
      if (_mobile->dataLoaded())
      {
         return _mobile->getFirstTime() - _mobile->getLastTime();
      }
   }
   return 0.0;
}

bool MobilesAnimationPath::getInterpolatedControlPoint(double time, osg::AnimationPath::ControlPoint & cp) const
{
   if (_mobile == nullptr) return false;
   if (!_mobile->dataLoaded()) return false;
       
        // at this point _mobile points something thats not nullptr but returns garbage...

   switch (_loopMode)
   {
   case(SWING):
   {
      double modulated_time = (time - getFirstTime()) / (getPeriod()*2.0);
      double fraction_part = modulated_time - floor(modulated_time);
      if (fraction_part > 0.5) fraction_part = 1.0 - fraction_part;

      time = getFirstTime() + (fraction_part*2.0) * getPeriod();
      break;
   }
   case(LOOP):
   {
      double modulated_time = (time - getFirstTime()) / getPeriod();
      double fraction_part = modulated_time - floor(modulated_time);
      time = getFirstTime() + fraction_part * getPeriod();
      break;
   }
   case(NO_LOOPING):
      // no need to modulate the time.
      break;
   }

   //... here I fill the control point through the data on _mobile.

   return true;

   
}


but at the first call to "getInterpolatedControlPoint" the application crashes. Moreover, the _mobile pointer is "corrupted", i.e., when I try to access its data it returns garbage (but it not nullptr). Also the "time" value passed is random (sometimes huge, sometimes negative, etc...)

As I pointed on the code snippet, MSVS complains about my META_Object call, but the code compiles.

Am I missing something?

Cheers,
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12321

PostPosted: Tue Jan 08, 2019 8:18 am    Post subject:
Get Animation current time
Reply with quote

HI Diego,

I can point you in the right direction but I can't sit beside you and
walk through your code in a debugger. When figuring out a crash this
is what is needed.

The only thing I can add is that using raw C pointer is generally a
red flag and one should be very cautious about doing so. The OSG uses
a combination of ref_ptr<> that using ref counting to retain ownership
and observer_ptr<> to hold a pointer where no ownership is intended
(it's a form of weak_ptr<>,) For you app it might be that either
might be appropriate, it's your application I can't make these
judgements for you.

Robert.

On Mon, 7 Jan 2019 at 19:30, Diego Mancilla <> wrote:
Quote:

Hello Robert,

Thank you very much for you complete response.

I'm trying to do what you suggest and have my on AnimationPath/AnimationPathCallback classes that handle my data. But I stumble into a problem.

When I subclass AnimationPath and AnimationPathCallback I have no problems. But when I wrote my own classes, from scratch my application crashes.

In order to achieve what I want, I pass a pointer to a custom data container class to my AnimationPath class (I called it MobilesAnimationPath) from my main application. I tried to keep most part of the architecture of AnimationPath, but I eliminate the TimeControlPointMap container. So, now my class generates the control points from the data pointed from custom data pointer class.


So, for instance, my custom Path class looks like this:


Code:
#include "MobileObject.h"
#include <osg/AnimationPath>
#include <osg/Object>

using namespace osg;

class MobilesAnimationPath: public virtual osg::Object
{
public:
MobilesAnimationPath();
MobilesAnimationPath(const MobilesAnimationPath &, const osg::CopyOp & copyop = osg::CopyOp::SHALLOW_COPY);
MobilesAnimationPath(MobileObject & mobile);

META_Object(osg, MobilesAnimationPath); //Visual Studio complains about this line, but compiles... : "function definition for META_Object not found"

enum LoopMode
{
SWING,
LOOP,
NO_LOOPING
};

void setLoopMode(LoopMode loopMode);
LoopMode getLoopMode() const;

virtual bool getInterpolatedControlPoint(double time, osg::AnimationPath::ControlPoint & cp) const;

double getFirstTime() const;
double getLastTime() const;
double getPeriod() const;

protected:
~MobilesAnimationPath(){};

private:
MobileObject * _mobile;
LoopMode _loopMode;

};



And the implementation.


Code:
#include "MobilesAnimationPath.h"

MobilesAnimationPath::MobilesAnimationPath()
:_loopMode(NO_LOOPING)
,_mobile(nullptr)
{
}


MobilesAnimationPath::MobilesAnimationPath(const MobilesAnimationPath& ap, const osg::CopyOp& copyop)
:osg::Object(ap, copyop)
,_loopMode(ap._loopMode)
,_mobile(ap._mobile)
{
}

MobilesAnimationPath::MobilesAnimationPath(MobileObject & mobile)
:_loopMode(NO_LOOPING)
{
_mobile = &mobile;
}

void MobilesAnimationPath::setLoopMode(LoopMode loopMode)
{
_loopMode = loopMode;
}

MobilesAnimationPath::LoopMode MobilesAnimationPath::getLoopMode() const
{
return _loopMode;
}

double MobilesAnimationPath::getFirstTime() const
{
if (_mobile != nullptr)
{
if (_mobile->dataLoaded())
{
return _mobile->getFirstTime();
}
}
return 0.0;
}

double MobilesAnimationPath::getLastTime() const
{
if (_mobile != nullptr)
{
if (_mobile->dataLoaded())
{
return _mobile->getLastTime();
}
}
return 0.0;
}

double MobilesAnimationPath::getPeriod() const
{
if (_mobile != nullptr)
{
if (_mobile->dataLoaded())
{
return _mobile->getFirstTime() - _mobile->getLastTime();
}
}
return 0.0;
}

bool MobilesAnimationPath::getInterpolatedControlPoint(double time, osg::AnimationPath::ControlPoint & cp) const
{
if (_mobile == nullptr) return false;
if (!_mobile->dataLoaded()) return false;

// at this point _mobile points something thats not nullptr but returns garbage...

switch (_loopMode)
{
case(SWING):
{
double modulated_time = (time - getFirstTime()) / (getPeriod()*2.0);
double fraction_part = modulated_time - floor(modulated_time);
if (fraction_part > 0.5) fraction_part = 1.0 - fraction_part;

time = getFirstTime() + (fraction_part*2.0) * getPeriod();
break;
}
case(LOOP):
{
double modulated_time = (time - getFirstTime()) / getPeriod();
double fraction_part = modulated_time - floor(modulated_time);
time = getFirstTime() + fraction_part * getPeriod();
break;
}
case(NO_LOOPING):
// no need to modulate the time.
break;
}

//... here I fill the control point through the data on _mobile.

return true;


}



but at the first call to "getInterpolatedControlPoint" the application crashes. Moreover, the _mobile pointer is "corrupted", i.e., when I try to access its data it returns garbage (but it not nullptr). Also the "time" value passed is random (sometimes huge, sometimes negative, etc...)

As I pointed on the code snippet, MSVS complains about my META_Object call, but the code compiles.

Am I missing something?

Cheers,

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=75403#75403








------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
dhhabyc
User


Joined: 17 Nov 2018
Posts: 24

PostPosted: Tue Jan 08, 2019 1:54 pm    Post subject:
Reply with quote

Hello Robert,

Thank you again.

It turns out that I forgot to initialize the _timeMultiplier variable on the constructor of my AnimationPath class. Also I had a problem with some crazy references retrieved wrongly: for some reason on a "for (auto e: stl_map)..." loop, &e.second, was not getting the rigth address for the mapped value) so I change the loop and everything works now.

When I use the original approach (filling control points on standard AnimationPath) my code took about a minute per mobile object. Now, as the data is referenced the time involved is almost zero.

Cheers,
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12321

PostPosted: Tue Jan 08, 2019 3:53 pm    Post subject:
Get Animation current time
Reply with quote

Good to hear you've resolved the problems and got things working
really efficiently ;-)

On Tue, 8 Jan 2019 at 14:11, Diego Mancilla <> wrote:
Quote:

Hello Robert,

Thank you again.

It turns out that I forgot to initialize the _timeMultiplier variable on the constructor of my AnimationPath class. Also I had a problem with some crazy references retrieved wrongly: for some reason on a "for (auto e: stl_map)..." loop, &e.second, was not getting the rigth address for the mapped value) so I change the loop and everything works now.

When I use the original approach (filling control points on standard AnimationPath) my code took about a minute per mobile object. Now, as the data is referenced the time involved is almost zero.

Cheers,

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=75430#75430








------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OpenSceneGraph Forum Forum Index -> General All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum

Similar Topics
Topic Author Forum Replies Posted
No new posts How to reset osgAnimation (put the an... GiacomoB General 1 Fri Jul 26, 2019 12:11 pm View latest post
No new posts long waiting time between cull and draw tomas259 General 3 Wed Jul 03, 2019 7:47 pm View latest post
No new posts [propal] compare VertexArrayState wit... mp3butcher General 0 Mon Dec 31, 2018 3:32 pm View latest post
No new posts Working with osg::Text on animation dhhabyc General 5 Thu Dec 20, 2018 1:39 pm View latest post
No new posts Questions concerning Performance issu... Andrea74 General 3 Fri Dec 14, 2018 11:24 am View latest post


Board Security Anti Bot Question MOD - phpBB MOD against Spam Bots
Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP