Overview

osgField is a NodeKit which provides universal animation mechanism and update event hierarchy to the OpenSceneGraph. With this NodeKit, you can make a built-in animations not only for transformation but also material, text and so on.

Field has typed input and output by write only setInputValue() method and read only getOutputValue() method. You can connect one field's output to multiple other field's input to make a update event hierarchy. Examples of the fields are osg::Vec3 keyframe interporation field, one shot bool field which triggers output fields after a while, etc.

PropertyFields is a special type of the field to access OSG objects through osgIntrospection's property or set and get method pair. You can connect the fields' update event hierarchy to OSG objects to change their states.

The following line creates a new property field to control the diffuse color of the osg::Material object 'pMaterial'.

PropertyVec4* pDiffuseProp = getManager()->createProperty(pMaterial, "DiffuseColor", Material::FRONT));
pDiffuseProp->setInputValue(Vec4(1.0, 0.0, 0.0, 1.0));

Some fields have useful constructors for instant animation. The following line creates a simple fade effect. This code changes the current color to white color for 1.5 seconds. You don't need to care its updating nor deletion.

pDiffuseProp->setInputField(new LinearVec4(pDiffuseProp, Vec4(1.0, 1.0, 1.0, 1.0), 1.5));

As the osgField is implmented as a NodeKit, you can write and read osgField objects and their connections in a .osg file. Even the usual osgviewer can handle the animation without modify nor recompile it.

Further more, the latest osgDirector application from Orihalcon Framework helps to use the osgField NodeKit. You can create and edit fields and property fields with its GUI. You can also edit field connections in its 'Fields' tree view.

Author

Toshiyuki Takahei (takahei<at>orihalcon.jp)

Platform

Windows 2000/XP, Linux

Licence

Lesser General Public License (LGPL)

Download

Source and Windows binary (from sourceforge.net)

Usage

Use library

Setup updater

At first, you need to provide a way to update field animaitions.

1) Add a osgField::ManagerUpdateCallback instance to a node somewhere in the scene.

pRoot->addUpdateCallback(new osgField::ManagerUpdateCallback);

2) Call update method every time in update the scene.

while (true) {
   viewer.update();
   osgField::getManager()->update(
       viewer.getFrameStamp()->getReferenceCount());
   viewer.cull();
   viewer.frame();
}

Create a PropertyField

osgField::PropertyField* pTextProp =
    osgField::getManager()->createProperty(pText, "Text");
pTextProp->setInputValue("Hello World");
// same as pText->setText("Hello World");

Create a TypeWriter effect

pText->setInputField(new osgField::TypeWriter("TypeWriter effect", 0.25));

Create a Keyframe animeation

osgField::PropertyField* pTextPosProp =
    osgField::getManager()->createProperty(pText, "Position");

osgField::KeyframeVec3* pKeyframe = new osgField::KeyframeVec3;
pKeyframe->addKey(0.0, osg::Vec3(0.0, 0.0, 0.0));
pKeyframe->addKey(1.0, osg::Vec3(1.0, 0.0, 0.0));
pKeyframe->addKey(2.0, osg::Vec3(1.0, 1.0, 0.0));
pKeyframe->addKey(3.0, osg::Vec3(0.0, 1.0, 0.0));
pKeyframe->addKey(3.0, osg::Vec3(0.0, 0.0, 0.0));
pKeyframe->setLoopMode(osgField::Field::LOOP);
pTextPosProp->setInputField(pKeyframe);

Field management

When you create a field or property field, it will be automatically registed to osgField::Manager class (singleton instance). After that you can retrieve the field instance from the Manager by its name or index. So you had better to give a unique name to the new field. If you want to remove a field, use Manager::removeField() method to remove it and all its connection properly.

Serialize

In the current version of osgField NodeKit, when you write out the scene with property field you must call Manager::beginWriteProperties() method before write out, and call Manager::endWriteProperties() method after that.

See examples and header files for more detail.

Work with osgDirector

osgDirector in Orihalcon Framework is a graphical scene graph editor for OpenSceneGraph. The latest version of the osgDirector has a GUI support to create and edit the osgField's fields and property fields. Here is an example to add a property field to an osgText::Text object, then create a new DateTime field and connect it to the property to realtime date and time text.


At first, create a osgText::Text object or load it from a file, then select it in the 'Scene Graph' tree.


Select 'Text' property in the property editor.


Click [Add Field] button in the tool bar of the property editor. osgDirector ask you to input a name of the new PropertyField. Input a unique name for it, then click [OK] button.


Now the 'Text' property is highlighted. This means that it has a PropertyField bound to it.


Click the 'Fields' tree tab. You'll see the visualized field connections. There are a default 'globalTime' ElapsedTime Field and a new 'Text_Text' PropertyField you created.


Select the new PropertyField and right click to show a context menu, then select [New Field...] menu. osgDirector shows a dialog to create a new Field to use as an input field of the selected dialog. Select DateTime Field and click [OK] button. osgDirector ask you if you want to make the new Field to be a input field (parent) of the selected Field. Click [OK] button.


Now you see the updated Field connections. 'globalTime' field provides update timing to 'new_DateTime' field every frame, and the 'new_DateTime' field provides the current date and time text to the 'Text_Text' property field. 'Text_Text' property field set the new text to the osgText::Text object.

So this is the result scene, a realtime clock in the OpenSceneGraph ;-).

Inside osgField NodeKit

All PropertyFields which access the same OSG object are contained in a PropertyContainer object. PropertyContainer object is stored with the OSG object's as a userData, so the PropertyContainer object shares its life time with the OSG object.

When you set an input value to a Field, it updates its inner value or OSG object's state if it is a PropertyField. Then it marks dirty flags to its output fields. These output fields also marks dirty flag to their output fields, so all of the subsequent fields are now marked as dirty. But these values themselves are not updated yet. When you or OSG requires the current value of a field from getOutputValue() method, it calls update() method to check its dirty flag and update the value on demand. Field requires its current input value from its input field, so all its input fields in the connection chain will be updated.

As this pull value process, the minumum number of fields are updated by getOutputValue(). Exception of the pull value model is a field with self destuction flag, such as OneShotBool field with constructor like osgField::OneShotBool(true, 1.2). After 1.2 seconds it set 'true'vlaue to all its output fields, then delete itself. This is a kind of push value process.

PropertyFields need to be updated in each update timing of the OSG main loop to provide the latest value to OSG objects. osgField::Manager's update() method updates all PropertyFields instances. This update() method also updates the 'globalTime' field to provide a life beat to animations.

Field Classes

LinearInt, LinearDouble, LinearVec2, LinearVec3, LinearVec4, LinearQuat, LinearMatrix
LinearTYPE class linearly interpolates value from A to B. Constructor LinearTYPE(A, B, duration) animates its output value from A to B for 'duration' seconds, then delete itself. So after create and connect it to othe field or property, you don't need to care about it. See 'typewriter' exmample for detail.
OneShotBool, OneShotInt, OneShotDouble, OneShotVec2, OneShotVec3, OneShotVec4, OneShotQuat, OneShotMatrix, OneShotString
LinearTYPE class outputs a value after the specified interval. Constructor OneShot(A, interval) outputs A after 'interval' seconds, then delete itself. So after create and connect it to othe field or property, you don't need to care about it.
KeyframeInt, KeyframeDouble, KeyframeVec2, KeyframeVec3, KeyframeVec4, KeyframeQuat, KeyframeMatrix
KeyframeTYPE class linearly interpolates key frame values. It's useful to use this KeyframeTYPE class to export animations in 3DCG software exporter.
ElapsedTime
ElapsedTime class changes speed and pause its input time counter. It's useful to make it as a source input of all animation fields to contorl the whole animations. osgField::Manager class has a special ElapsedTime field 'globalTime', and it's a default input field of all animation fields.
TypeWriter
TypeWriter class output a text string by the character like a typing a type writer. Constructor TypeWriter(A, interval) outputs A with 'interval' seconds for each character, then delete itself. So after create and connect it to othe field or property, you don't need to care about it. See 'typewriter' exmample for detail.
DateTime
DteTime class demonstrates simple field which output the current date and time by text string. See 'datetime' exmample for detail.

Build

Windows

Open VisualStudio/osgField.sln with Microsoft VisualStudio.NET 2003 or later, then build the projects.

In the OSGFILEPATH you need osgwrapper_*.dll and other OSG dll files. osgField NodeKit itself consists of osgField.dll, osgwrapper_osgField.dll and osgdb_osgField.dll.

Linux

Execute 'gmake', then 'gmake install' like the OSGlibrary.

osgField NodeKit depends on osgIntrospection (and osgText for TypeWriter field). So you need to compile the OSG library with osgIntrospection by setting 'COMPILE_INTROSPECTION ?= yes' in OSG/Make/dependencies.

Todo

  • Remove ugly Manager::beginWriteProperties() and Manager::endWriteProperties() method.
    When write out the properties PropertyContainer must know 'UniqueId' of its owner OSG object. But the UniqueId is not given to objects whose reference counter is less than 2. So you have to increment the reference coun of the owner object before write out it. If the PropertyContainer had a ref_ptr reference to the owner object, it causes mutual referencing and you will not be able to delete the owner object. Thoughts?

Future Plans

  • More Field classes and examples.
  • New field category 'SyncField', which synchronizes the value over the network. You can simply define variables to be synchlonized in the cluster environment in a .osg scene file. For example, you may want to share a master time clock, view point, visible flags, animation state and so on.

Change Log

  • 2006/10/6 osgField 0.1.0, the first public release.