VR-Vantage 2.8 API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
exampleSequenceControl

Table of Contents

Overview

An example of querying/modifying animations(osg::sequence) of an DtOsgArticulatedModel.

Expected Result

exampleSequenceControl2.png
Sequence Control Result

Example Details

Each 'entity' is our numbered grid model (a row with 7 boxes): -The row has 7 boxes, each of which have a different type of animation. Starting animations in the model starting from Large box on the far left are as follows:

Each box's animation is basically a numbered sequence with the textures indicating the 'frame number'

Animation Frame and Speed

Pressing key '1' tests DtOsgArticulatedModel::setAnimationFrame and DtOsgArticulatedModel::setAnimationSpeed methods using row 1 (the top row). The first time key '1' is pressed, all the boxes in the top row will be reset to frame 0 and the animation speed will be set to 0.5 fps (every 2 seconds). The second time it is pressed, the animations will be set to frame 5 and the animation speed set to 1.0 fps. All subsequent presses of the '1' key will set the animations to frame 10 and the animation speed to 5.0 fps.

Animation Range

Pressing key '2' tests DtOsgArticulatedModel::setAnimationRange() methods using row 2. The first time key '2' is pressed, the animation range is set to be from frame 0 to frame 9 (1-10). The second time it is pressed the range is set from frame 4 to frame 7 (5-8). The third time it is pressed the range is from from frame 1 to frame 3 (2-4). On the fourth key press the range is set from frame 4 to frame 4 (5 only). Subsequent presses have no effect.

Animation State

Pressing key '3' tests DtOsgArticulatedModel::setAnimationState methods using row 3. The first, third, fifth, etc. presses of key '3' will pause the first four boxes and stop the last three. The second, fourth, sixth, etc. key press resumes the first four boxes and restarts the last three.

Current Frame

Pressing key '4' tests DtOsgArticulatedModel::animationCurrentFrame methods using row 4. This test reports the animation frame for each box in row 4 (to the console window).

Additional Information

Pressing key 5 will test any random code you wish to add for row 5. The example also outputs the animations it found in the articulated model with their initial values. Please see the comments in the code as well since it describes what is being queried/set, etc.

Building the Example

To build the example, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.

Running the Example

This example is an application. You can run it by running ./bin64/exampleSequenceControl.exe (on Windows) or ./bin64/exampleSequenceControl (on Linux). For more information about running examples, please see Running Applications and Examples.

Learn More

Example Source Files


exampleSequenceControl.cxx

/*****************************************************************************
* Copyright (c) 2020 MAK Technologies, Inc.
* All rights reserved.
*****************************************************************************/
// Each 'entity' is our numbered grid model (a row with 7 boxes)
// -The row has 7 boxes, each of which have a different type of animation
// (Please see exampleSequenceControl\media\readme.txt)
// -Each box's animation is basically a numbered sequence with the textures indicating
// the 'frame number'
// Pressing key 1 tests the following API for row 1 (top most row)
// -DtOsgArticulatedModel::setAnimationFrame
// -DtOsgArticulatedModel::setAnimationSpeed
// Pressing key 2 tests the following API for row 2
// -DtOsgArticulatedModel::setAnimationRange
// Pressing key 3 tests the following API for row 3
// -DtOsgArticulatedModel::setAnimationState
// Pressing key 4 tests the following API for row 4
// -DtOsgArticulatedModel::animationCurrentFrame
// Pressing key 5 will test any random code you wish to add for row 5
// The example also outputs the animations it found in the articulated model with
// their initial values
#include <vrvCore/DtDe.h>
#include <matrix/vlTaitBryan.h>
#include <matrix/vlVector.h>
#include <string>
#include <cmath>
#include <array>
// All VR-Vantage classes are in the same namespace.
using namespace makVrv;
// This driver class is used to create and manage the articulation-model and
// its scene-object. This driver is registered with the driver-manager in
// order to get regular simulation 'ticks' during the run of the application.
//
// This driver indirectly creates the articulated-model and the scene-object by
// creating their 'agent' counterparts instead. Since this driver is using the
// DtArticulatedModelAgent and DtSceneObjectAgent, any calls to the interfaces
// of these classes get propagated to the underlying objects and also get
// marshaled to other distributed simulations.
class MyArticulationDriver : public DtDriver
{
public:
// The constructor of this driver is hard-coded to create a model-definition
// which loads a specific model, then it registers the model-definition with
// the DtDe for later use. The constructor also builds the default map
// of part-ids to part-orientations.
MyArticulationDriver(DtDe& de) : DtDriver(de.agentManager(), "MyArticulationDriver")
, myModelDefinition("testModel")
, mySceneObjectsAndModels()
{
// The name of the geometry file to load.
const std::string modelFilePath("../examples/exampleSequenceControl/media/FlipBookTest.flt");
myModelDefinition.setParameter("filename", modelFilePath);
de.sharedState().addModelDefinition(myModelDefinition);
// initialize the test counters
resetCounts();
}
virtual void destroyObjects()
{
for (auto& val : mySceneObjectsAndModels)
{
DtSceneObjectAgent* sceneObject = val.first;
DtArticulatedModelAgent* model = val.second;
// If both the scene object and model exist
// remove the model from the scene object
if (sceneObject && model)
{
sceneObject->removeModel(model);
}
// delete model
delete model;
model = 0;
// delete scene object
delete sceneObject;
sceneObject = 0;
}
}
// This drivers destructor destroys the objects it is currently managing.
virtual ~MyArticulationDriver()
{
destroyObjects();
}
// When the simulation starts, this driver creates the model-agent and the
// scene-object-agent and saves the starting time of the simulation.
virtual bool onStart()
{
for (int i = 0; i < mySceneObjectsAndModels.size(); ++i)
{
// Create the agent and set the model-definition
// Set the model definition
model->setModelDefinition(myModelDefinition.name());
// Create the scene-object
DtSceneObjectAgent* sceneObject = DtSceneObjectAgent::create(myAgentManager);
sceneObject->addModel(model, 0);
// Add it to our array
mySceneObjectsAndModels[i] = std::make_pair(sceneObject, model);
}
const float xPos = 0.0f;
const float yPos = 25.0f;
const float zDecrement = 3;
float posZ = 5.4; // top to bottom
DtTaitBryan taitBryan;
taitBryan.setPsi(-10.554191782826420);
// These values are defined in the DIS specification.
static const int partId = 4096;
// set up the entity
// Our model is the numbered grid
// -The numbered grid has 7 boxes, each of which have a different type of animation
// (Please see exampleSequenceControl\media\readme.txt)
// -Each box's animation is basically a numbered sequence with the textures indicating
// the 'frame number'
// Each 'entity' is our numbered grid model (a row with 7 boxes)
for (int i = 0; i < mySceneObjectsAndModels.size(); ++i)
{
// set the position
mySceneObjectsAndModels[i].first->setPosition(0, DtVector(xPos, yPos, posZ));
// set the orientation
mySceneObjectsAndModels[i].second->setPartOrientation(partId, taitBryan, DtVector());
// next one beneath the previous one
posZ -= zDecrement;
}
return true;
}
// When the simulation stops, this driver destroys the model-agent and the
// scene-object-agent that it was managing.
virtual bool onStop()
{
destroyObjects();
return true;
}
// utility function to convert an animation state to a printable string
static std::string toString(const DtArticulatedModel::AnimationState state)
{
{
return "START";
}
{
return "STOP";
}
{
return "PAUSE";
}
{
return "RESUME";
}
return "UNKNOWN!!";
}
// On each simulation update, the driver gets the current simulation time
// then updates the articulated parts of the model based on that time.
virtual bool onTick()
{
static bool once = false;
// see if we have already processed
if (once)
{
return true;
}
DtArticulatedModelAgent* model = mySceneObjectsAndModels[0].second;
// see if there's a model available yet
if (once==false && model->findObject())
{
// see if there's a the actual DtOsgArticulatedModel available yet
DtOsgArticulatedModel* articulatedModel = dynamic_cast<DtOsgArticulatedModel*>(model->findObject());
// look for the animations in this osg articulated model
const DtArticulatedModelParser::AnimationMap& animations = articulatedModel->animations();
// Print some details about the animations we found
// This essentially demonstrates the API to query information about the animations
for (auto it = animations.begin(); it != animations.end(); ++it)
{
std::cout << "animation: " << it->first<<":" << std::endl;
const std::string& animationName = it->first;
std::cout << " animationFrameCount: " << articulatedModel->animationFrameCount(animationName) << std::endl;
std::cout << " animationFirstFrame: " << articulatedModel->animationFirstFrame(animationName) << std::endl;
std::cout << " animationLastFrame: " << articulatedModel->animationLastFrame(animationName) << std::endl;
std::cout << " animationSpeed: " << articulatedModel->animationSpeed(animationName) << std::endl;
std::cout << " animationState: " << toString(articulatedModel->animationState(animationName)) << std::endl;
std::cout << " animationLastFrameTime: " << articulatedModel->animationLastFrameTime(animationName) << std::endl;
std::cout << " animationLoopCount: " << articulatedModel->animationLoopCount(animationName) << std::endl;
std::cout <<" ------------------"<< std::endl;
std::cout << std::endl;
// add this to the list of animations we found
myAnimationNames.insert(animationName);
// do this only once
once = true;
}
}
return true;
}
// This tests the following API:
// -DtOsgArticulatedModel::setAnimationFrame
// -DtOsgArticulatedModel::setAnimationSpeed
// This is run when the key binding for this test is pressed (in this case key 1)
void setAnimationSpeedAndAnimationFrameTest(void)
{
if (myAnimationNames.empty())
{
return;
}
// 1st entity(row) / the top most row
DtOsgArticulatedModel* articulatedModel = findOsgArticulatedModel(0);
if (articulatedModel == nullptr)
{
return;
}
std::cout << "row 1: " << std::endl;
// first time here?
if (mySpeedAndAnimationFrameTestCount == 0)
{
// reset all 7 boxes' animations to the 0th frame
// set all 7 boxes' animations' speed to 0.5 fps
std::cout << "reset to 0th frame (entity 0)" << std::endl;
std::cout << "reset to 0.5 fps (entity 0)" << std::endl;
std::cout << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
// reset to 0th frame:
articulatedModel->setAnimationFrame(*it, 0);
//0.5 frame per sec or 1 frame every 2 seconds
articulatedModel->setAnimationSpeed(*it, 0.5);
}
}
// second time here?
else if (mySpeedAndAnimationFrameTestCount==1)
{
// reset all 7 boxes' animations to the 5th frame
// set all 7 boxes' animations' speed to 1 fps
std::cout << "reset to 5th frame (entity 0)" << std::endl;
std::cout << "reset to 1 fps (entity 0)" << std::endl;
std::cout << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
// reset to 5th frame:
articulatedModel->setAnimationFrame(*it, 4);
//1 frame per sec
articulatedModel->setAnimationSpeed(*it, 1);
}
}
// every time after the 2nd..
else
{
// reset all 7 boxes' animations to the 10th frame
// change the speed of all animations to 5 fps
std::cout << "reset to 10th frame (entity 0)" << std::endl;
std::cout << "reset to 5 fps (entity 0)" << std::endl;
std::cout << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
// reset to 10th frame:
articulatedModel->setAnimationFrame(*it, 9);
//5 fps
articulatedModel->setAnimationSpeed(*it, 5);
}
}
++mySpeedAndAnimationFrameTestCount;
}
// This tests the following API:
// -DtOsgArticulatedModel::setAnimationRange
// This is run when the key binding for this test is pressed (in this case key 2)
void setAnimationRangeTest(void)
{
if (myAnimationNames.empty())
{
return;
}
// 2nd entity (row) from the top
DtOsgArticulatedModel* articulatedModel = findOsgArticulatedModel(1);
if (articulatedModel == nullptr)
{
return;
}
std::cout << "row 2: " << std::endl;
// first time here?
if (myAnimationRangeTestCount == 0)
{
std::cout << "reset animation range [1-10] (entity 1)" << std::endl;
std::cout << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
articulatedModel->setAnimationRange(*it, 0, 9);
}
}
// second time here?
else if (myAnimationRangeTestCount == 1)
{
std::cout << "reset animation range [5-8] (entity 1)" << std::endl;
std::cout << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
articulatedModel->setAnimationRange(*it, 4, 7);
}
}
// second time here?
else if (myAnimationRangeTestCount == 2)
{
std::cout << "reset animation range [2-4] (entity 1)" << std::endl;
std::cout << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
articulatedModel->setAnimationRange(*it, 1, 3);
}
}
// 4th time here?
else if (myAnimationRangeTestCount == 3)
{
std::cout << "reset animation range [5-5] (entity 1)" << std::endl;
std::cout << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
articulatedModel->setAnimationRange(*it, 4, 4);
}
}
++myAnimationRangeTestCount;
}
// This tests the following API:
// -DtOsgArticulatedModel::setAnimationState
// This is run when the key binding for this test is pressed (in this case key 3)
// Every other time a few boxes in the row are pause/stopped and the others are resumed/started
void setAnimationStateTest(void)
{
if (myAnimationNames.empty())
{
return;
}
// 3rd entity (row) from the top
DtOsgArticulatedModel* articulatedModel = findOsgArticulatedModel(2);
if (articulatedModel == nullptr)
{
return;
}
std::cout << "row 3: " << std::endl;
if (myAnimationStateTestCount%2 == 0)
{
std::cout << "Pause first 4" << std::endl;
std::cout << "Stop last 3" << std::endl;
std::cout << std::endl;
articulatedModel->setAnimationState("Slow", DtArticulatedModel::PAUSE);
articulatedModel->setAnimationState("Fast", DtArticulatedModel::PAUSE);
articulatedModel->setAnimationState("VeryFast", DtArticulatedModel::PAUSE);
articulatedModel->setAnimationState("OneLoop", DtArticulatedModel::PAUSE);
articulatedModel->setAnimationState("Swing", DtArticulatedModel::STOP);
articulatedModel->setAnimationState("Backwards", DtArticulatedModel::STOP);
articulatedModel->setAnimationState("LastFrame", DtArticulatedModel::STOP);
}
if (myAnimationStateTestCount % 2 == 1)
{
std::cout << "Resume first 4" << std::endl;
std::cout << "Start last 3 again" << std::endl;
std::cout << std::endl;
articulatedModel->setAnimationState("Slow", DtArticulatedModel::RESUME);
articulatedModel->setAnimationState("Fast", DtArticulatedModel::RESUME);
articulatedModel->setAnimationState("VeryFast", DtArticulatedModel::RESUME);
articulatedModel->setAnimationState("OneLoop", DtArticulatedModel::RESUME);
articulatedModel->setAnimationState("Swing", DtArticulatedModel::START);
articulatedModel->setAnimationState("Backwards", DtArticulatedModel::START);
articulatedModel->setAnimationState("LastFrame", DtArticulatedModel::START);
}
++myAnimationStateTestCount;
}
// This tests the following API:
// -DtOsgArticulatedModel::animationCurrentFrame
// This is run when the key binding for this test is pressed (in this case key 4)
// When the key is pressed, it will printout which frame the animation for the box is at
void queryAnimationCurrentFrameTest(void)
{
if (myAnimationNames.empty())
{
return;
}
// bottom to last entity (row)
DtOsgArticulatedModel* articulatedModel = findOsgArticulatedModel(3);
if (articulatedModel == nullptr)
{
return;
}
int i = 0;
std::cout << "row 4: " << std::endl;
std::cout <<"current frame (left to right): " << std::endl;
std::cout <<"\t box["<<i++<<"]: "<<articulatedModel->animationCurrentFrame("Slow") << std::endl;
std::cout <<"\t box["<<i++<<"]: "<<articulatedModel->animationCurrentFrame("Fast") << std::endl;
std::cout <<"\t box["<<i++<<"]: "<<articulatedModel->animationCurrentFrame("VeryFast") << std::endl;
std::cout <<"\t box["<<i++<<"]: "<<articulatedModel->animationCurrentFrame("OneLoop") << std::endl;
std::cout <<"\t box["<<i++<<"]: "<<articulatedModel->animationCurrentFrame("Swing") << std::endl;
std::cout <<"\t box["<<i++<<"]: "<<articulatedModel->animationCurrentFrame("Backwards") << std::endl;
std::cout <<"\t box["<<i++<<"]: "<<articulatedModel->animationCurrentFrame("LastFrame") << std::endl;
}
// This is run when the key binding for this test is pressed (in this case key 5)
// You can add any custom test code here
void testOtherThings(void)
{
if (myAnimationNames.empty())
{
return;
}
// bottom most entity (row)
std::cout << "row 5: " << std::endl;
DtOsgArticulatedModel* articulatedModel = findOsgArticulatedModel(4);
if (articulatedModel == nullptr)
{
return;
}
if (myTestOtherStuffCount == 0)
{
std::cout << "setting animation loop count to 5" << std::endl;
for (auto it = myAnimationNames.begin(); it != myAnimationNames.end(); ++it)
{
articulatedModel->setAnimationLoopCount(*it, 5);
}
}
else if (myTestOtherStuffCount == 1)
{
// TO DO
// Add any custom test code here
}
++myTestOtherStuffCount;
}
// resets the test counts
void resetCounts()
{
mySpeedAndAnimationFrameTestCount = 0;
myAnimationRangeTestCount = 0;
myAnimationStateTestCount = 0;
myTestOtherStuffCount = 0;
}
// Implement the base-class pure virtual function to return
// a class name. This name is used when registering this class.
virtual const std::string& className() const
{
static const std::string name("MyArticulationDriver");
return name;
}
DtOsgArticulatedModel* findOsgArticulatedModel(int index)
{
if (index >= mySceneObjectsAndModels.size())
{
return nullptr;
}
DtArticulatedModelAgent* articulatedModelAgent = mySceneObjectsAndModels[index].second;
if (articulatedModelAgent == nullptr)
{
return nullptr;
}
DtOsgArticulatedModel* articulatedModel = dynamic_cast<DtOsgArticulatedModel*>(articulatedModelAgent->findObject());
return articulatedModel;
}
protected:
std::set<std::string> myAnimationNames;
static const int numEntities = 5; // rows
std::array< std::pair<DtSceneObjectAgent*, DtArticulatedModelAgent*>, numEntities> mySceneObjectsAndModels;
DtModelDefinition myModelDefinition;
// the number of times we have entered each test
int mySpeedAndAnimationFrameTestCount;
int myAnimationRangeTestCount;
int myAnimationStateTestCount;
int myTestOtherStuffCount;
};
// The main function creates, initializes and runs the application.
// It creates an instance of the driver to populate the scene and
// articulate the model while the application is running.
int main(int argc,char** argv)
{
// Create and initialize a VR-Vantage application.
// install the command line processor.
// here we use the vantage command line processor
// so that --disableIndirectEntities can be turned on/off
makVrv::DtVantageIgCommandLineProcessor vantageCommandLineParser;
igApp.installCommandLineProcessor(&vantageCommandLineParser);
igApp.initialize(argc, argv);
// Create the driver to manage the objects in the scene.
MyArticulationDriver* driver = new MyArticulationDriver(igApp.de());
// set up the key bindings
DtInputDriver& inputDriver = igApp.de().driverManager().inputDriver();
DtKeyMapManager& keyMapManager = DtKeyMapManager::instance(igApp.de());
keyMapManager.addKeyFunction("setAnimationSpeedAndAnimationFrameTest", boost::bind(
&MyArticulationDriver::setAnimationSpeedAndAnimationFrameTest, driver), DtKeyMapManager::Miscellaneous);
keyMapManager.addKeyFunction("setAnimationRangeTest", boost::bind(
&MyArticulationDriver::setAnimationRangeTest, driver), DtKeyMapManager::Miscellaneous);
keyMapManager.addKeyFunction("setAnimationStateTest", boost::bind(
&MyArticulationDriver::setAnimationStateTest, driver), DtKeyMapManager::Miscellaneous);
keyMapManager.addKeyFunction("queryAnimationCurrentFrameTest", boost::bind(
&MyArticulationDriver::queryAnimationCurrentFrameTest, driver), DtKeyMapManager::Miscellaneous);
keyMapManager.addKeyFunction("testOtherThings", boost::bind(
&MyArticulationDriver::testOtherThings, driver), DtKeyMapManager::Miscellaneous);
// Bind the above key functions to the respective keys
// ("Observer Frame") key map
DtKeyMap* obsFrame = keyMapManager.findKeyMap("Observer Frame");
if (obsFrame)
{
inputDriver.addKeyBinding(obsFrame, DtKeyState::KEY_1, "setAnimationSpeedAndAnimationFrameTest");
inputDriver.addKeyBinding(obsFrame, DtKeyState::KEY_2, "setAnimationRangeTest");
inputDriver.addKeyBinding(obsFrame, DtKeyState::KEY_3, "setAnimationStateTest");
inputDriver.addKeyBinding(obsFrame, DtKeyState::KEY_4, "queryAnimationCurrentFrameTest");
inputDriver.addKeyBinding(obsFrame, DtKeyState::KEY_5, "testOtherThings");
}
// Register the driver with the display engine. The display engine will
// manage the driver so we will not delete it.
igApp.de().driverManager().addDriver(driver);
// Start the driver.
igApp.de().driverManager().startDriver(driver);
// Run the application, render the loaded model and have the driver
// articulate all the parts of the model.
igApp.run();
return 0;
}

[<< Examples] [Home] [Top of Page]



Copyright © 2005-2021 MAK Technologies. All Rights Reserved (www.mak.com)