2 * Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
4 * This library is open source and may be redistributed and/or modified under
5 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
6 * (at your option) any later version. The full license is in LICENSE file
7 * included with this distribution, and on the openscenegraph.org website.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * OpenSceneGraph Public License for more details.
15#ifndef OSGANIMATION_RIGGEOMETRY_H
16#define OSGANIMATION_RIGGEOMETRY_H
18#include <osgAnimation/Export>
19#include <osgAnimation/Skeleton>
20#include <osgAnimation/RigTransform>
21#include <osgAnimation/VertexInfluence>
22#include <osg/Geometry>
26 // The idea is to compute a bounding box with a factor x of the first step we compute the bounding box
27 class OSGANIMATION_EXPORT RigComputeBoundingBoxCallback : public osg::Drawable::ComputeBoundingBoxCallback
30 RigComputeBoundingBoxCallback(double factor = 2.0): _computed(false), _factor(factor) {}
32 RigComputeBoundingBoxCallback(const RigComputeBoundingBoxCallback& rhs, const osg::CopyOp& copyop) :
33 osg::Drawable::ComputeBoundingBoxCallback(rhs, copyop),
35 _factor(rhs._factor) {}
37 META_Object(osgAnimation, RigComputeBoundingBoxCallback);
39 void reset() { _computed = false; }
41 virtual osg::BoundingBox computeBound(const osg::Drawable& drawable) const;
43 mutable bool _computed;
45 mutable osg::BoundingBox _boundingBox;
49 class OSGANIMATION_EXPORT RigGeometry : public osg::Geometry
55 RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
57 META_Object(osgAnimation, RigGeometry);
59 inline void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; }
60 inline const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get(); }
61 inline VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get(); }
63 inline const Skeleton* getSkeleton() const { return _root.get(); }
64 inline Skeleton* getSkeleton() { return _root.get(); }
65 // will be used by the update callback to init correctly the rig mesh
66 inline void setSkeleton(Skeleton* root) { _root = root; }
68 void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state; }
69 bool getNeedToComputeMatrix() const { return _needToComputeMatrix; }
71 void computeMatrixFromRootSkeleton();
73 // set implementation of rig method
74 inline RigTransform* getRigTransformImplementation() { return _rigTransformImplementation.get(); }
75 inline void setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; }
76 inline const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); }
80 void buildVertexInfluenceSet() { _rigTransformImplementation->prepareData(*this); }
82 const osg::Matrix& getMatrixFromSkeletonToGeometry() const;
84 const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const;
86 inline osg::Geometry* getSourceGeometry() { return _geometry.get(); }
87 inline const osg::Geometry* getSourceGeometry() const { return _geometry.get(); }
88 inline void setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; }
90 void copyFrom(osg::Geometry& from);
92 struct FindNearestParentSkeleton : public osg::NodeVisitor
94 osg::ref_ptr<Skeleton> _root;
95 FindNearestParentSkeleton() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {}
96 void apply(osg::Transform& node)
100 _root = dynamic_cast<osgAnimation::Skeleton*>(&node);
107 osg::ref_ptr<osg::Geometry> _geometry;
108 osg::ref_ptr<RigTransform> _rigTransformImplementation;
109 osg::ref_ptr<VertexInfluenceMap> _vertexInfluenceMap;
111 osg::Matrix _matrixFromSkeletonToGeometry;
112 osg::Matrix _invMatrixFromSkeletonToGeometry;
113 osg::observer_ptr<Skeleton> _root;
114 bool _needToComputeMatrix;
119 struct UpdateRigGeometry : public osg::Drawable::UpdateCallback
121 UpdateRigGeometry() {}
123 UpdateRigGeometry(const UpdateRigGeometry& org, const osg::CopyOp& copyop):
124 osg::Object(org, copyop),
125 osg::Callback(org, copyop),
126 osg::DrawableUpdateCallback(org, copyop) {}
128 META_Object(osgAnimation, UpdateRigGeometry);
130 virtual void update(osg::NodeVisitor* nv, osg::Drawable* drw)
132 RigGeometry* geom = dynamic_cast<RigGeometry*>(drw);
135 if(!geom->getSkeleton() && !geom->getParents().empty())
137 RigGeometry::FindNearestParentSkeleton finder;
138 if(geom->getParents().size() > 1)
139 osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << geom->getName() << " )" << std::endl;
140 geom->getParents()[0]->accept(finder);
142 if(!finder._root.valid())
144 osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << geom->getName() << " )" << std::endl;
147 geom->getRigTransformImplementation()->prepareData(*geom);
148 geom->setSkeleton(finder._root.get());
151 if(!geom->getSkeleton())
154 if(geom->getNeedToComputeMatrix())
155 geom->computeMatrixFromRootSkeleton();
157 if(geom->getSourceGeometry())
159 osg::Drawable::UpdateCallback * up = dynamic_cast<osg::Drawable::UpdateCallback*>(geom->getSourceGeometry()->getUpdateCallback());
161 up->update(nv, geom->getSourceGeometry());