Skip to content

Instantly share code, notes, and snippets.

@sbrkopac
Last active April 9, 2019 00:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sbrkopac/2ea619b90573c4cb25af639589c31e2d to your computer and use it in GitHub Desktop.
Save sbrkopac/2ea619b90573c4cb25af639589c31e2d to your computer and use it in GitHub Desktop.
/***
This example intentionally doesn't include any stacked transforms or animations.
It is just being used to showcase that the osgAnimation skeleton doesn't traverse
all bones down the hierarchy
***/
#include <iostream>
#include <osgViewer/Viewer>
#include <osgAnimation/Bone>
#include <osgAnimation/UpdateBone>
#include <osgAnimation/Skeleton>
// override classes to get outputs
namespace test
{
class Bone : public osgAnimation::Bone
{
public:
Bone(const std::string name = "") : osgAnimation::Bone(name)
{
}
virtual ~Bone()
{
std::cout << "test::Bone::~Bone(" << getName() << ")" << std::endl;
}
};
class UpdateBone : public osgAnimation::UpdateBone
{
public:
UpdateBone(const std::string name = "") : osgAnimation::UpdateBone(name)
{
std::cout << "test::UpdateBone::UpdateBone(" << name << ") constructed" << std::endl;
}
virtual ~UpdateBone()
{
std::cout << "test::UpdateBone::~UpdateBone(" << getName() << ")" << std::endl;
}
void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
std::cout << "test::UpdateBone::operator(node, nv) being called for " << node->getName() << " should traverse[" << node->getNumChildrenRequiringUpdateTraversal() << "] children" << std::endl;
osgAnimation::UpdateBone::operator()(node, nv);
}
};
}
// struct used in plugin
struct BoneInfo
{
BoneInfo(std::string name, unsigned int parent) : name(name), parent(parent) {}
std::string name;
unsigned int parent;
unsigned int flags;
};
// this is parsed from binary data and held prior to generating the OSG bone structure
std::vector<BoneInfo> boneNamesLoadedFromPlugin;
void addDummyBoneWithNameAndParent(std::string name, unsigned int parent);
void generateDummyBoneNames();
int main(int argc, char* argv[])
{
osgViewer::Viewer viewer;
generateDummyBoneNames();
// create our skeleton and add the callback
osg::ref_ptr<osgAnimation::Skeleton> skeleton = new osgAnimation::Skeleton;
skeleton->setDefaultUpdateCallback();
viewer.getCamera()->setCullingMode(osg::CullSettings::NO_CULLING);
skeleton->setCullingActive(false);
// hold a reference to all bones for quick and easy lookup
std::vector<test::Bone *> vecBoneLookup;
const std::string& rootBoneName = boneNamesLoadedFromPlugin[0].name;
osg::ref_ptr<test::Bone> rootBone = new test::Bone(rootBoneName);
// add our root bone to our skeleton and our lookup
skeleton->addChild(rootBone);
vecBoneLookup.push_back(rootBone);
osg::ref_ptr<test::UpdateBone> rootBoneUpdater = new test::UpdateBone(rootBoneName);
rootBone->setUpdateCallback(rootBoneUpdater);
// loop over our entire bone information loaded from the plugin
for (unsigned int i = 0; i < boneNamesLoadedFromPlugin.size(); ++i)
{
test::Bone* parentBone = nullptr;
// just grab the root bone as it already exists
if (i == 0)
{
parentBone = rootBone;
std::cout << "Dealing with rootBone[" << parentBone->getName() << "]" << std::endl;
}
// create a new bone and add it to our look up
if (parentBone == nullptr)
{
// get name from the loaded list
parentBone = new test::Bone(boneNamesLoadedFromPlugin[i].name);
vecBoneLookup.push_back(parentBone);
}
// loop over our children and create our hierarchy
for (unsigned int j = 0; j < boneNamesLoadedFromPlugin.size(); ++j)
{
// check to make sure we don't parent a bone to itself
if (i != j && i == boneNamesLoadedFromPlugin[j].parent)
{
std::string childBoneName = boneNamesLoadedFromPlugin[j].name;
osg::ref_ptr<test::Bone> childBone = new test::Bone(childBoneName);
// add it to its parent
parentBone->addChild(childBone);
// setup the updater
osg::ref_ptr <test::UpdateBone> updateBone = new test::UpdateBone(childBoneName);
childBone->addUpdateCallback(updateBone);
}
}
std::cout << "Parent bone [" << parentBone->getName() << "] has [" << parentBone->getNumChildren() << "] children" << std::endl;
}
// create our scene
osg::ref_ptr<osg::Group> scene = new osg::Group;
scene->addChild(skeleton);
viewer.setSceneData(scene);
std::cout << "-------------" << std::endl;
for (test::Bone* bone : vecBoneLookup)
{
std::cout << "Bone[" << bone->getName() << "] has [" << bone->getNumChildren() << "] children" << std::endl;
}
std::cout << "-------------" << std::endl;
return viewer.run();
}
void addDummyBoneWithNameAndParent(std::string name, unsigned int parent)
{
boneNamesLoadedFromPlugin.push_back(BoneInfo(name, parent));
}
void generateDummyBoneNames()
{
boneNamesLoadedFromPlugin.clear();
// add a root bone
addDummyBoneWithNameAndParent("root", 0); // index 0
// add two children to our root bone
addDummyBoneWithNameAndParent("rootChild1", 0); // index 1
addDummyBoneWithNameAndParent("rootChild2", 0); // index 2
// add one child to the rootChild1 and rootChild2
addDummyBoneWithNameAndParent("child1X", 1); // index 3
addDummyBoneWithNameAndParent("child2X", 2); // index 4
// add two children to child1X and child2X
addDummyBoneWithNameAndParent("child1X1", 3); // index 5
addDummyBoneWithNameAndParent("child1X2", 3); // index 6
addDummyBoneWithNameAndParent("child2X1", 4); // index 7
addDummyBoneWithNameAndParent("child2x2", 4); // index 8
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment