/* -*-c++-*- * Copyright (C) 2008 Cedric Pinson * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #ifndef OSGANIMATION_RIGGEOMETRY_H #define OSGANIMATION_RIGGEOMETRY_H #include #include #include #include namespace osgAnimation { class OSGANIMATION_EXPORT RigGeometry : public osg::Geometry { public: RigGeometry(); RigGeometry(const osg::Geometry& b); RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); META_Object(osgAnimation, RigGeometry); void setInfluenceMap(osgAnimation::VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } const osgAnimation::VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} osgAnimation::VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} const Skeleton* getSkeleton() const; Skeleton* getSkeleton(); void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;} bool getNeedToComputeMatrix() const { return _needToComputeMatrix;} void buildVertexSet(); void buildTransformer(Skeleton* root); void computeMatrixFromRootSkeleton(); virtual void transformSoftwareMethod(); const osgAnimation::VertexInfluenceSet& getVertexInfluenceSet() const { return _vertexInfluenceSet;} const std::vector& getPositionSource() const { return _positionSource;} const std::vector& getNormalSource() const { return _normalSource;} protected: std::vector _positionSource; std::vector _normalSource; osgAnimation::VertexInfluenceSet _vertexInfluenceSet; osg::ref_ptr _vertexInfluenceMap; osgAnimation::TransformVertexFunctor _transformVertexes; osg::Matrix _matrixFromSkeletonToGeometry; osg::Matrix _invMatrixFromSkeletonToGeometry; osg::observer_ptr _root; bool _needToComputeMatrix; struct FindNearestParentSkeleton : public osg::NodeVisitor { osg::ref_ptr _root; FindNearestParentSkeleton() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {} void apply(osg::Transform& node) { if (_root.valid()) return; _root = dynamic_cast(&node); traverse(node); } }; struct UpdateVertex : public osg::Drawable::UpdateCallback { virtual void update(osg::NodeVisitor*, osg::Drawable* drw) { RigGeometry* geom = dynamic_cast(drw); if (!geom) return; if (!geom->getSkeleton() && !geom->getParents().empty()) { FindNearestParentSkeleton finder; if (geom->getParents().size() > 1) osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << geom->getName() << " )" << std::endl; geom->getParents()[0]->accept(finder); if (!finder._root.valid()) return; geom->buildVertexSet(); geom->buildTransformer(finder._root.get()); } if (!geom->getSkeleton()) return; if (geom->getNeedToComputeMatrix()) geom->computeMatrixFromRootSkeleton(); geom->transformSoftwareMethod(); } }; /** BuildVertexTransformerVisitor is used to setup RigGeometry drawable * throw a subgraph. */ struct BuildVertexTransformerVisitor : public osg::NodeVisitor { osg::ref_ptr _root; BuildVertexTransformerVisitor(Skeleton* root): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _root = root;} META_NodeVisitor("osgAnimation","BuildVertexTransformerVisitor") void apply(osg::Geode& node) { int num = node.getNumDrawables(); for (int i = 0; i < num; i++) { RigGeometry* geom = dynamic_cast(node.getDrawable(i)); if (geom) { geom->buildVertexSet(); geom->buildTransformer(_root.get()); } } } }; }; } #endif