RigGeometry 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* -*-c++-*-
  2. * Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
  3. *
  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.
  8. *
  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.
  13. */
  14. #ifndef OSGANIMATION_RIGGEOMETRY_H
  15. #define OSGANIMATION_RIGGEOMETRY_H
  16. #include <osgAnimation/Export>
  17. #include <osgAnimation/Skeleton>
  18. #include <osgAnimation/RigTransform>
  19. #include <osgAnimation/VertexInfluence>
  20. #include <osg/Geometry>
  21. namespace osgAnimation
  22. {
  23. // The idea is to compute a bounding box with a factor x of the first step we compute the bounding box
  24. class OSGANIMATION_EXPORT RigComputeBoundingBoxCallback : public osg::Drawable::ComputeBoundingBoxCallback
  25. {
  26. public:
  27. RigComputeBoundingBoxCallback(double factor = 2.0): _computed(false), _factor(factor) {}
  28. RigComputeBoundingBoxCallback(const RigComputeBoundingBoxCallback& rhs, const osg::CopyOp& copyop) :
  29. osg::Drawable::ComputeBoundingBoxCallback(rhs, copyop),
  30. _computed(false),
  31. _factor(rhs._factor) {}
  32. META_Object(osgAnimation, RigComputeBoundingBoxCallback);
  33. void reset() { _computed = false; }
  34. virtual osg::BoundingBox computeBound(const osg::Drawable& drawable) const;
  35. protected:
  36. mutable bool _computed;
  37. double _factor;
  38. mutable osg::BoundingBox _boundingBox;
  39. };
  40. class OSGANIMATION_EXPORT RigGeometry : public osg::Geometry
  41. {
  42. public:
  43. RigGeometry();
  44. RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
  45. META_Object(osgAnimation, RigGeometry);
  46. inline void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; }
  47. inline const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get(); }
  48. inline VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get(); }
  49. inline const Skeleton* getSkeleton() const { return _root.get(); }
  50. inline Skeleton* getSkeleton() { return _root.get(); }
  51. // will be used by the update callback to init correctly the rig mesh
  52. inline void setSkeleton(Skeleton* root) { _root = root; }
  53. void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state; }
  54. bool getNeedToComputeMatrix() const { return _needToComputeMatrix; }
  55. void computeMatrixFromRootSkeleton();
  56. // set implementation of rig method
  57. inline RigTransform* getRigTransformImplementation() { return _rigTransformImplementation.get(); }
  58. inline void setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; }
  59. inline const RigTransform* getRigTransformImplementation() const { return _rigTransformImplementation.get(); }
  60. void update();
  61. void buildVertexInfluenceSet() { _rigTransformImplementation->prepareData(*this); }
  62. const osg::Matrix& getMatrixFromSkeletonToGeometry() const;
  63. const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const;
  64. inline osg::Geometry* getSourceGeometry() { return _geometry.get(); }
  65. inline const osg::Geometry* getSourceGeometry() const { return _geometry.get(); }
  66. inline void setSourceGeometry(osg::Geometry* geometry) { _geometry = geometry; }
  67. void copyFrom(osg::Geometry& from);
  68. struct FindNearestParentSkeleton : public osg::NodeVisitor
  69. {
  70. osg::ref_ptr<Skeleton> _root;
  71. FindNearestParentSkeleton() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {}
  72. void apply(osg::Transform& node)
  73. {
  74. if (_root.valid())
  75. return;
  76. _root = dynamic_cast<osgAnimation::Skeleton*>(&node);
  77. traverse(node);
  78. }
  79. };
  80. protected:
  81. osg::ref_ptr<osg::Geometry> _geometry;
  82. osg::ref_ptr<RigTransform> _rigTransformImplementation;
  83. osg::ref_ptr<VertexInfluenceMap> _vertexInfluenceMap;
  84. osg::Matrix _matrixFromSkeletonToGeometry;
  85. osg::Matrix _invMatrixFromSkeletonToGeometry;
  86. osg::observer_ptr<Skeleton> _root;
  87. bool _needToComputeMatrix;
  88. };
  89. struct UpdateRigGeometry : public osg::Drawable::UpdateCallback
  90. {
  91. UpdateRigGeometry() {}
  92. UpdateRigGeometry(const UpdateRigGeometry& org, const osg::CopyOp& copyop):
  93. osg::Object(org, copyop),
  94. osg::Callback(org, copyop),
  95. osg::DrawableUpdateCallback(org, copyop) {}
  96. META_Object(osgAnimation, UpdateRigGeometry);
  97. virtual void update(osg::NodeVisitor* nv, osg::Drawable* drw)
  98. {
  99. RigGeometry* geom = dynamic_cast<RigGeometry*>(drw);
  100. if(!geom)
  101. return;
  102. if(!geom->getSkeleton() && !geom->getParents().empty())
  103. {
  104. RigGeometry::FindNearestParentSkeleton finder;
  105. if(geom->getParents().size() > 1)
  106. osg::notify(osg::WARN) << "A RigGeometry should not have multi parent ( " << geom->getName() << " )" << std::endl;
  107. geom->getParents()[0]->accept(finder);
  108. if(!finder._root.valid())
  109. {
  110. osg::notify(osg::WARN) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << geom->getName() << " )" << std::endl;
  111. return;
  112. }
  113. geom->getRigTransformImplementation()->prepareData(*geom);
  114. geom->setSkeleton(finder._root.get());
  115. }
  116. if(!geom->getSkeleton())
  117. return;
  118. if(geom->getNeedToComputeMatrix())
  119. geom->computeMatrixFromRootSkeleton();
  120. if(geom->getSourceGeometry())
  121. {
  122. osg::Drawable::UpdateCallback * up = dynamic_cast<osg::Drawable::UpdateCallback*>(geom->getSourceGeometry()->getUpdateCallback());
  123. if(up)
  124. up->update(nv, geom->getSourceGeometry());
  125. }
  126. geom->update();
  127. }
  128. };
  129. }
  130. #endif