: Documentation : Multimedia Tutorials

Introduction

This tutorial demonstrates how to perform rigid body animation on an object within an osgART scene.

OSG Viewer & Scene Setup

Using the same process as in previous tutorials, we set up a scene tracking one marker. The preceding code has been omitted for brevity.

osg::MatrixTransform* mt = scene->addTrackedTransform("single;data/patt.hiro;80;0;0");

Animate 3D Object

Here we demonstrate how to add animate an object, relative to its marker. In previous tutorials, we added our 3D object as a child of the osg::MatrixTransform node - “mt” here - returned to us by the addTrackedTransform() call. To perform transforms, inlcluding animation, on a 3D object, we must introduce an additional transform node into the scene graph, between “mt”, and the 3D object. Any transforms we apply to this additional transform node will transform the 3D object relative to the marker.

To create the animation, we add update callbacks to this transform node, so we can update and alter the position and/or rotation of the 3D object every scene graph traversal. This gives us our animation.

In OSG we can assign update callbacks to any osg::Node, this includes both MatrixTransform and osg::PositionAttitudeTransform nodes. It is also possible to add more than one callback to a node. It is probably best to add update callbacks using the addUpdateCallback() method. This method handles multiple callbacks for us - it sets the new callback to the node if the node has no callbacks already, and nests any subsequently added callbacks.

To create an update callback in OSG, we must subclass osg::NodeCallbackand override the operator() method. However, for animations, OSG provides such a class for us - osg::AnimationPathCallback - which can be used to apply transformations on both MatrixTransform and PositionAttitudeTransform nodes. There are two kinds of AnimationPathCallback.

In order to demonstrate both versions, we’ll add two different models to our marker, and animate each in a different way.

AnimationPathCallback Version 1

One, used for applying a simple rotation to node, takes three parameters- a pivot point, an axis of rotation, and an angular velocity. Here, we use this version of AnimationPathCallback to continuously rotate a 3D model of the HITLAB logo. Here the additional transform node is named “hitlabAnimation”. Note that wherever we use a MatrixTransform node we could equivalently and just as correctly use an OSG PositionAttitudeTransform instead.

osg::ref_ptr<osg::MatrixTransform> hitlabMT = new osg::MatrixTransform();
hitlabMT->addChild(osgDB::readNodeFile("data/hitl_logo.osg"));
hitlabMT->addUpdateCallback(new osg::AnimationPathCallback(osg::Vec3(0.0,0.0,0.0),
                                                           osg::Z_AXIS,
                                                           osg::inDegrees(45.0f)));
mt->addChild(hitlabMT.get());

AnimationPathCallback Version 2

The second kind of AnimationPathCallback is used to perform more complex animation on a node, including translation, scale, rotation, and combinations of these. This version of AnimationPathCallback takes an osg::AnimationPath as a parameter. In this example, we animate a 3D model of a car in this way, and define the AnimationPath in a support function. Here the additional transform node is named “carMT”

osg::ref_ptr<osg::MatrixTransform> carMT = new osg::MatrixTransform();
carMT->addChild(osgDB::readNodeFile("data/car.ive"));
carMT->addUpdateCallback(new osg::AnimationPathCallback(carAnimationPath()));
mt->addChild(carMT.get());

AnimationPath

Here is the body of our support function which creates and returns the AnimationPath used by our AnimationPathCallback.

  • First we create an AnimationPath object which, according to the OSG documentation, encapsulates a time varying transformation pathway. The LoopMode of an AnimationPath can be either LOOP (object continuously follows the pathway in the same direction), SWING (object continuously follows the pathway, but reverses direction each time), or NO_LOOP (pathway travel occurs once).
osg::AnimationPath* carAnimationPath()
{
osg::AnimationPath* path = new osg::AnimationPath();
path->setLoopMode(osg::AnimationPath::LOOP);

An AnimationPath consists of a number of osg::AnimationPath::AnimationPath::ControlPoint objects each inserted at a given “time”. The AnimationPath interpolates between each ControlPoint. A ControlPoint consists of a position value, and optionally, a rotation value, or rotation and scale values.

Note that an AnimationPath does not, in fact, need to be a “path”, it could just as correctly consist of a number of ControlPoint objects defining various transformations at a single co-ordinate.

 /** point 1 - start point **/
path->insert(0.0, osg::AnimationPath::ControlPoint(osg::Vec3d(-60.0,-60.0,0.0),
osg::Quat(osg::inDegrees(0.0f),osg::Z_AXIS)));
path->insert(0.2, osg::AnimationPath::ControlPoint(osg::Vec3d(-60.0,-60.0,0.0),
            osg::Quat(osg::inDegrees(90.0f),osg::Z_AXIS)));
/** point 2 **/
path->insert(1.2, osg::AnimationPath::ControlPoint(osg::Vec3d(60.0,-60.0,0.0),
            osg::Quat(osg::inDegrees(90.0f),osg::Z_AXIS)));
path->insert(1.7, osg::AnimationPath::ControlPoint(osg::Vec3d(60.0,-60.0,0.0),
            osg::Quat(osg::inDegrees(180.0f),osg::Z_AXIS)));

/** point 3 **/
path->insert(2.7, osg::AnimationPath::ControlPoint(osg::Vec3d(60.0,60.0,0.0),
            osg::Quat(osg::inDegrees(180.0f),osg::Z_AXIS)));
path->insert(2.9, osg::AnimationPath::ControlPoint(osg::Vec3d(60.0,60.0,0.0),
            osg::Quat(osg::inDegrees(270.0f),osg::Z_AXIS)));

/** point 4 **/
path->insert(3.9, osg::AnimationPath::ControlPoint(osg::Vec3d(-60.0,60.0,0.0),
            osg::Quat(osg::inDegrees(270.0f),osg::Z_AXIS)));
path->insert(4.1, osg::AnimationPath::ControlPoint(osg::Vec3d(-60.0,60.0,0.0),
            osg::Quat(osg::inDegrees(360.0f),osg::Z_AXIS)));

/** back to point 1 **/
path->insert(5.1, osg::AnimationPath::ControlPoint(osg::Vec3d(-60.0,-60.0,0.0),
            osg::Quat(osg::inDegrees(360.0f),osg::Z_AXIS)));

return path;
}

The following diagram represents the car’s AnimationPath in 2D. At each co-ordinate there are two ControlPoint objects inserted, a short time apart. The arrows represent the rotation - you can think of this as the car’s rotation coming into, and out of, each co-ordinate.

AnimationPath_pathway.png

Finally…

As before, we add the scene data to the Viewer, and set up the viewer loop. The code has been omitted for brevity.

RigidBodyAnimationScreenshot.png RigidBodyAnimationGraph.png