/* -*-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 #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(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} const Skeleton* getSkeleton() const; Skeleton* getSkeleton(); // will be used by the update callback to init correctly the rig mesh void setSkeleton(Skeleton*); void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;} bool getNeedToComputeMatrix() const { return _needToComputeMatrix;} // this build the internal database about vertex influence and bones void buildVertexInfluenceSet(); const VertexInfluenceSet& getVertexInfluenceSet() const; void computeMatrixFromRootSkeleton(); // set implementation of rig method void setRigTransformImplementation(RigTransform*); RigTransform* getRigTransformImplementation(); virtual void drawImplementation(osg::RenderInfo& renderInfo) const; void update(); const osg::Matrix& getMatrixFromSkeletonToGeometry() const; const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const; osg::Geometry* getSourceGeometry(); const osg::Geometry* getSourceGeometry() const; void setSourceGeometry(osg::Geometry* geometry); void copyFrom(osg::Geometry& from); protected: osg::ref_ptr _geometry; osg::ref_ptr _rigTransformImplementation; VertexInfluenceSet _vertexInfluenceSet; osg::ref_ptr _vertexInfluenceMap; 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()) { osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeomtry ( " << geom->getName() << " )" << std::endl; return; } geom->buildVertexInfluenceSet(); geom->setSkeleton(finder._root.get()); } if (!geom->getSkeleton()) return; if (geom->getNeedToComputeMatrix()) geom->computeMatrixFromRootSkeleton(); geom->update(); } }; }; } #endif