<- Dynamic Updates using the API | Dynamic Updates using Shared Memory -> |
Often it is desirable to use a utility such as osgviewer, to view a model and not write a complete application from scratch, just to be able to plug in certain functionality. osgEphemeris is a good example of a component you might want to add to a scene without having to write a special viewer just to see it.
osgEphemeris allows you to write an EphemerisUpdateCallback and compile it as a shared object, which can be loaded by a directive in a .osg file. Here we will see the steps required to make this work. We will use an example provided in src/CallbackExample in the distribution. Here we create a simple callback named "TimePassesCallback", which begins by ticking off 60 seconds for every frame, beginning with 0 of the UNIX epoch (midnight, Jan 1, 1970). Here is the .cpp file:
#include <time.h> #include <osgEphemeris/EphemerisUpdateCallback.h> #include <osgEphemeris/EphemerisData.h> class TimePassesCallback : public osgEphemeris::EphemerisUpdateCallback { public: TimePassesCallback(): EphemerisUpdateCallback( "TimePassesCallback" ), _seconds(0) {} void operator()( osgEphemeris::EphemerisData *data ) { _seconds += 60; struct tm *_tm = localtime(&_seconds); data->dateTime.setYear( _tm->tm_year + 1900 ); // DateTime uses _actual_ year (not since 1900) data->dateTime.setMonth( _tm->tm_mon + 1 ); // DateTime numbers months from 1 to 12, not 0 to 11 data->dateTime.setDayOfMonth( _tm->tm_mday + 1 ); // DateTime numbers days from 1 to 31, not 0 to 30 data->dateTime.setHour( _tm->tm_hour ); data->dateTime.setMinute( _tm->tm_min ); data->dateTime.setSecond( _tm->tm_sec ); } private: time_t _seconds; }; osgEphemeris::EphemerisUpdateCallbackProxy<TimePassesCallback> _timePassesCallbackProxy; |
This is quite similar to the previous section callback, other than the fact that we are not using the current time, but setting some artificial passage of time.
There is one line at the end of the file, which defines a static instance of a EphemerisUpdateCallbackProxy class. The role of this class is to register the callback with an internal registry of callbacks, so it is available for later use.
Also, important to note, is the string that we pass the EphemerisUpdateCallback super class. This is the name of the callback and something we will be using as a directive parameter in our .osg file format later.
This file can then be compiled into a shared object named "TimePasses" (no extension is really necessary).
g++ -O2 -shared -fPIC timePasses.cpp -o TimePasses |
Place this file TimePasses into a directory within your OSG_FILE_PATH definition or in a standard place where osgDB will find it.
Next, add the necessary directive to the ephemeris.osg file:
osgEphemerisModel::EphemerisModel { UniqueID EphemerisModel_0 Latitude 38.4765 Longitude -122.493 DateTime 20060224162800 SkyDomeRadius 200000 AutoDateTime False MoveWithEyePoint True UpdateCallback TimePasses::TimePassesCallback } |
By adding UpdateCallback TimePasses::TimePassesCallback, we've directed the NodeKit to load a callback named TimePassesCallback from a shared object named TimePasses. You can now run the following and watch time pass over your terrain database:
osgviewer --clear-color 0,0,0,1 myTerrain.osg ephemeris.osg |
<- Dynamic Updates using the API | Dynamic Updates using Shared Memory -> |