From 55e89e446663f4ce4b22f25d00cb141a12380438 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 21 Jan 2009 19:02:54 +0000 Subject: [PATCH] From Cedric Pinson, "updated osgAnimation with the trunk here the update: examples/osganimationviewer/AnimtkViewer.cpp: - add option to display bone (--drawbone) - dont crash if the file does not contains a AnimationManagerBase, display the content only examples/osganimationviewer/AnimtkViewerGUI.cpp: - adjust the path of image for the gui include/osgAnimation/Interpolator: - add warn message instead of old assert include/osgAnimation/Bone: src/osgAnimation/Skeleton.cpp: - change a method name to fit better with what it does. setMatrixInSkeletonSpace instead of setBoneInSkeletonSpace include/osgAnimation/Skinning: src/osgAnimation/RigGeometry.cpp: - add patch from Fabien Lavignotte to compute normal correctly include/osgAnimation/Sampler: - adjust behviour without assert, return 0 instead of crashing " --- .../osganimationskinning.cpp | 2 +- examples/osganimationviewer/AnimtkViewer.cpp | 77 ++++++++++++++++--- include/osgAnimation/Bone | 2 +- include/osgAnimation/Interpolator | 11 ++- include/osgAnimation/Sampler | 4 + include/osgAnimation/Skinning | 25 +++++- src/osgAnimation/RigGeometry.cpp | 2 +- src/osgAnimation/Skeleton.cpp | 4 +- 8 files changed, 105 insertions(+), 22 deletions(-) diff --git a/examples/osganimationskinning/osganimationskinning.cpp b/examples/osganimationskinning/osganimationskinning.cpp index 628866232..d5cb697f3 100644 --- a/examples/osganimationskinning/osganimationskinning.cpp +++ b/examples/osganimationskinning/osganimationskinning.cpp @@ -237,7 +237,7 @@ int main (int argc, char* argv[]) osg::MatrixTransform* trueroot = new osg::MatrixTransform; trueroot->setMatrix(osg::Matrix(root->getMatrixInBoneSpace().ptr())); trueroot->addChild(createAxis()); - trueroot->addChild(skelroot); + trueroot->addChild(skelroot.get()); trueroot->setDataVariance(osg::Object::DYNAMIC); rootTransform->addChild(trueroot); scene->addChild(rootTransform); diff --git a/examples/osganimationviewer/AnimtkViewer.cpp b/examples/osganimationviewer/AnimtkViewer.cpp index ea348fc91..809adf9a5 100644 --- a/examples/osganimationviewer/AnimtkViewer.cpp +++ b/examples/osganimationviewer/AnimtkViewer.cpp @@ -31,6 +31,7 @@ #include #include #include +#include const int WIDTH = 1440; const int HEIGHT = 900; @@ -68,32 +69,86 @@ osg::Geode* createAxis() return geode; } + +struct AnimationManagerFinder : public osg::NodeVisitor +{ + osg::ref_ptr _am; + AnimationManagerFinder() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + void apply(osg::Node& node) { + if (_am.valid()) + return; + if (node.getUpdateCallback()) { + osgAnimation::AnimationManagerBase* b = dynamic_cast(node.getUpdateCallback()); + if (b) { + _am = new osgAnimation::BasicAnimationManager(*b); + return; + } + } + traverse(node); + } +}; + + +struct AddHelperBone : public osg::NodeVisitor +{ + AddHelperBone() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {} + void apply(osg::Transform& node) { + osgAnimation::Bone* bone = dynamic_cast(&node); + if (bone) + bone->addChild(createAxis()); + traverse(node); + } +}; + int main(int argc, char** argv) { - osg::ArgumentParser psr(&argc, argv); + osg::ArgumentParser arguments(&argc, argv); + arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName()); + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is a 3d poker game client"); + arguments.getApplicationUsage()->addCommandLineOption("-h or --help","List command line options."); + arguments.getApplicationUsage()->addCommandLineOption("--drawbone","draw helps to display bones."); - if(argc < 2) + if (arguments.read("-h") || arguments.read("--help")) { - std::cerr << "usage: AnimtkViewer " << std::endl; + arguments.getApplicationUsage()->write(std::cout, osg::ApplicationUsage::COMMAND_LINE_OPTION); + return 0; + } + + if (arguments.argc()<=1) + { + arguments.getApplicationUsage()->write(std::cout, osg::ApplicationUsage::COMMAND_LINE_OPTION); return 1; } - osgViewer::Viewer viewer(psr); + bool drawBone = false; + if (arguments.read("--drawbone")) + drawBone = true; + + osgViewer::Viewer viewer(arguments); osg::ref_ptr group = new osg::Group(); - osg::Group* node = dynamic_cast(osgDB::readNodeFile(psr[1])); //dynamic_cast(osgDB::readNodeFile(psr[1])); - if(!node) + osg::Group* node = dynamic_cast(osgDB::readNodeFiles(arguments)); //dynamic_cast(osgDB::readNodeFile(psr[1])); + if(!node) { - std::cerr << "Can't read file " << psr[1]<< std::endl; + std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl; return 1; } // Set our Singleton's model. - osgAnimation::AnimationManagerBase* base = dynamic_cast(node->getUpdateCallback()); - osgAnimation::BasicAnimationManager* manager = new osgAnimation::BasicAnimationManager(*base); - node->setUpdateCallback(manager); - AnimtkViewerModelController::setModel(manager); + AnimationManagerFinder finder; + node->accept(finder); + if (finder._am.valid()) { + node->setUpdateCallback(finder._am.get()); + AnimtkViewerModelController::setModel(finder._am.get()); + } else { + osg::notify(osg::WARN) << "no osgAnimation::AnimationManagerBase found in the subgraph, no animations available" << std::endl; + } + if (drawBone) { + osg::notify(osg::INFO) << "Add Bones Helper" << std::endl; + AddHelperBone addHelper; + node->accept(addHelper); + } node->addChild(createAxis()); AnimtkViewerGUI* gui = new AnimtkViewerGUI(&viewer, WIDTH, HEIGHT, 0x1234); diff --git a/include/osgAnimation/Bone b/include/osgAnimation/Bone index 5cc8342e1..6fac97db2 100644 --- a/include/osgAnimation/Bone +++ b/include/osgAnimation/Bone @@ -213,7 +213,7 @@ namespace osgAnimation const osg::Matrix& getBindMatrixInBoneSpace() const { return _bindInBoneSpace; } const osg::Matrix& getMatrixInSkeletonSpace() const { return _boneInSkeletonSpace; } const osg::Matrix& getInvBindMatrixInSkeletonSpace() const { return _invBindInSkeletonSpace;} - void setBoneInSkeletonSpace(const osg::Matrix& matrix) { _boneInSkeletonSpace = matrix; } + void setMatrixInSkeletonSpace(const osg::Matrix& matrix) { _boneInSkeletonSpace = matrix; } void setBindMatrixInBoneSpace(const osg::Matrix& matrix) { _bindInBoneSpace = matrix; diff --git a/include/osgAnimation/Interpolator b/include/osgAnimation/Interpolator index bdf172fe1..f50310818 100644 --- a/include/osgAnimation/Interpolator +++ b/include/osgAnimation/Interpolator @@ -15,6 +15,7 @@ #ifndef OSGANIMATION_INTERPOLATOR_H #define OSGANIMATION_INTERPOLATOR_H +#include #include #include @@ -38,8 +39,12 @@ namespace osgAnimation { // todo use a cache int key_size = keys.size(); + if (!key_size) { + osg::notify(osg::WARN) << "TemplateInterpolatorBase::getKeyIndexFromTime the container is empty, impossible to get key index from time" << std::endl;; + return -1; + } const TemplateKeyframe* keysVector = &keys.front(); - for (int i = 0; i < key_size-1; i++) + for (int i = 0; i < key_size-1; i++) { float time0 = keysVector[i].getTime(); float time1 = keysVector[i+1].getTime(); @@ -50,9 +55,7 @@ namespace osgAnimation return i; } } - std::cout << time << " first key " << keysVector[0].getTime() << " last key " << keysVector[key_size-1].getTime() << std::endl; - *((int *)0) = 0; - + osg::notify(osg::WARN) << time << " first key " << keysVector[0].getTime() << " last key " << keysVector[key_size-1].getTime() << std::endl; return -1; } }; diff --git a/include/osgAnimation/Sampler b/include/osgAnimation/Sampler index bad4a928b..1f5a66c1b 100644 --- a/include/osgAnimation/Sampler +++ b/include/osgAnimation/Sampler @@ -64,11 +64,15 @@ namespace osgAnimation float getStartTime() const { + if (!_keyframes) + return 0.0f; return _keyframes->front().getTime(); } float getEndTime() const { + if (!_keyframes) + return 0.0f; return _keyframes->back().getTime(); } diff --git a/include/osgAnimation/Skinning b/include/osgAnimation/Skinning index 528053c6b..926995b6a 100644 --- a/include/osgAnimation/Skinning +++ b/include/osgAnimation/Skinning @@ -91,9 +91,9 @@ namespace osgAnimation ptrresult[13] += ptr[13] * weight; ptrresult[14] += ptr[14] * weight; } - void computeMatrixForVertexSet() + void computeMatrixForVertexSet() { - if (_bones.empty()) + if (_bones.empty()) { osg::notify(osg::WARN) << "TransformVertexFunctor::UniqBoneSetVertexSet no bones found" << std::endl; _result = MatrixType::identity(); @@ -181,6 +181,7 @@ namespace osgAnimation template void compute(const MatrixType& transform, const MatrixType& invTransform, const V* src, V* dst) { + // the result of matrix mult should be cached to be used for vertexes transform and normal transform and maybe other computation int size = _boneSetVertexSet.size(); for (int i = 0; i < size; i++) { @@ -198,6 +199,26 @@ namespace osgAnimation } } + + template void computeNormal(const MatrixType& transform, const MatrixType& invTransform, const V* src, V* dst) + { + int size = _boneSetVertexSet.size(); + for (int i = 0; i < size; i++) + { + UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i]; + uniq.computeMatrixForVertexSet(); + MatrixType matrix = transform * uniq.getMatrix() * invTransform; + + const VertexList& vertexes = uniq.getVertexes(); + int vertexSize = vertexes.size(); + for (int j = 0; j < vertexSize; j++) + { + int idx = vertexes[j]; + dst[idx] = MatrixType::transform3x3(src[idx],matrix); + } + } + } + protected: std::vector _boneSetVertexSet; diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index 2692caa76..293ab5e52 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -117,7 +117,7 @@ void RigGeometry::transformSoftwareMethod() } if (!_normalSource.empty()) { - _transformVertexes.compute(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_normalSource.front(), &normal->front()); + _transformVertexes.computeNormal(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_normalSource.front(), &normal->front()); normal->dirty(); } if (getUseDisplayList()) diff --git a/src/osgAnimation/Skeleton.cpp b/src/osgAnimation/Skeleton.cpp index 6e587333e..62db25588 100644 --- a/src/osgAnimation/Skeleton.cpp +++ b/src/osgAnimation/Skeleton.cpp @@ -52,9 +52,9 @@ struct updateMatrixVisitor : public osg::NodeVisitor } if (parent) - bone->setBoneInSkeletonSpace(bone->getMatrixInBoneSpace() * bone->getBoneParent()->getMatrixInSkeletonSpace()); + bone->setMatrixInSkeletonSpace(bone->getMatrixInBoneSpace() * bone->getBoneParent()->getMatrixInSkeletonSpace()); else - bone->setBoneInSkeletonSpace(bone->getMatrixInBoneSpace()); + bone->setMatrixInSkeletonSpace(bone->getMatrixInBoneSpace()); traverse(node); }