RigTransformSoftware 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* -*-c++-*-
  2. * Copyright (C) 2009 Cedric Pinson <cedric.pinson@plopbyte.net>
  3. * Copyright (C) 2017 Julien Valentin <mp3butcher@hotmail.com>
  4. *
  5. * This library is open source and may be redistributed and/or modified under
  6. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  7. * (at your option) any later version. The full license is in LICENSE file
  8. * included with this distribution, and on the openscenegraph.org website.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * OpenSceneGraph Public License for more details.
  14. */
  15. #ifndef OSGANIMATION_RIGTRANSFORM_SOFTWARE
  16. #define OSGANIMATION_RIGTRANSFORM_SOFTWARE 1
  17. #include <osgAnimation/Export>
  18. #include <osgAnimation/RigTransform>
  19. #include <osgAnimation/Bone>
  20. #include <osgAnimation/VertexInfluence>
  21. #include <osg/observer_ptr>
  22. namespace osgAnimation
  23. {
  24. class RigGeometry;
  25. /// This class manage format for software skinning
  26. class OSGANIMATION_EXPORT RigTransformSoftware : public RigTransform
  27. {
  28. public:
  29. RigTransformSoftware();
  30. RigTransformSoftware(const RigTransformSoftware& rts,const osg::CopyOp& copyop);
  31. META_Object(osgAnimation,RigTransformSoftware)
  32. virtual void operator()(RigGeometry&);
  33. //to call when a skeleton is reacheable from the rig to prepare technic data
  34. virtual bool prepareData(RigGeometry&);
  35. typedef std::pair<unsigned int, float> LocalBoneIDWeight;
  36. class BonePtrWeight: LocalBoneIDWeight
  37. {
  38. public:
  39. BonePtrWeight(unsigned int id,float weight, Bone*bone=0 ): LocalBoneIDWeight(id,weight), _boneptr(bone) {}
  40. BonePtrWeight(const BonePtrWeight &bw2): LocalBoneIDWeight(bw2.getBoneID(),bw2.getWeight()), _boneptr(bw2._boneptr.get()) {}
  41. inline const float & getWeight() const { return second; }
  42. inline void setWeight(float b) { second=b; }
  43. inline const unsigned int & getBoneID() const { return first; }
  44. inline void setBoneID(unsigned int b) { first=b; }
  45. inline bool operator< (const BonePtrWeight &b1) const {
  46. if (second > b1.second) return true;
  47. if (second < b1.second) return false;
  48. return (first > b1.first);
  49. }
  50. ///set Bone pointer
  51. inline const Bone * getBonePtr() const { return _boneptr.get(); }
  52. inline void setBonePtr(Bone*b) { _boneptr=b; }
  53. protected:
  54. osg::observer_ptr< Bone > _boneptr;
  55. };
  56. typedef std::vector<BonePtrWeight> BonePtrWeightList;
  57. /// map a set of boneinfluence to a list of vertex indices sharing this set
  58. class VertexGroup
  59. {
  60. public:
  61. inline BonePtrWeightList& getBoneWeights() { return _boneweights; }
  62. inline IndexList& getVertices() { return _vertexes; }
  63. inline void resetMatrix()
  64. {
  65. _result.set(0, 0, 0, 0,
  66. 0, 0, 0, 0,
  67. 0, 0, 0, 0,
  68. 0, 0, 0, 1);
  69. }
  70. inline void accummulateMatrix(const osg::Matrix& invBindMatrix, const osg::Matrix& matrix, osg::Matrix::value_type weight)
  71. {
  72. osg::Matrix m = invBindMatrix * matrix;
  73. osg::Matrix::value_type* ptr = m.ptr();
  74. osg::Matrix::value_type* ptrresult = _result.ptr();
  75. ptrresult[0] += ptr[0] * weight;
  76. ptrresult[1] += ptr[1] * weight;
  77. ptrresult[2] += ptr[2] * weight;
  78. ptrresult[4] += ptr[4] * weight;
  79. ptrresult[5] += ptr[5] * weight;
  80. ptrresult[6] += ptr[6] * weight;
  81. ptrresult[8] += ptr[8] * weight;
  82. ptrresult[9] += ptr[9] * weight;
  83. ptrresult[10] += ptr[10] * weight;
  84. ptrresult[12] += ptr[12] * weight;
  85. ptrresult[13] += ptr[13] * weight;
  86. ptrresult[14] += ptr[14] * weight;
  87. }
  88. inline void computeMatrixForVertexSet()
  89. {
  90. if (_boneweights.empty())
  91. {
  92. osg::notify(osg::WARN) << this << " RigTransformSoftware::VertexGroup no bones found" << std::endl;
  93. _result = osg::Matrix::identity();
  94. return;
  95. }
  96. resetMatrix();
  97. for(BonePtrWeightList::iterator bwit=_boneweights.begin(); bwit!=_boneweights.end(); ++bwit )
  98. {
  99. const Bone* bone = bwit->getBonePtr();
  100. if (!bone)
  101. {
  102. osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl;
  103. continue;
  104. }
  105. const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
  106. const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace();
  107. osg::Matrix::value_type w = bwit->getWeight();
  108. accummulateMatrix(invBindMatrix, matrix, w);
  109. }
  110. }
  111. void normalize();
  112. inline const osg::Matrix& getMatrix() const { return _result; }
  113. protected:
  114. BonePtrWeightList _boneweights;
  115. IndexList _vertexes;
  116. osg::Matrix _result;
  117. };
  118. template <class V>
  119. inline void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
  120. {
  121. // the result of matrix mult should be cached to be used for vertices transform and normal transform and maybe other computation
  122. for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg)
  123. {
  124. VertexGroup& uniq = *itvg;
  125. uniq.computeMatrixForVertexSet();
  126. osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
  127. const IndexList& vertices = uniq.getVertices();
  128. for(IndexList::const_iterator vertIDit=vertices.begin(); vertIDit!=vertices.end(); ++vertIDit)
  129. {
  130. dst[*vertIDit] = src[*vertIDit] * matrix;
  131. }
  132. }
  133. }
  134. template <class V>
  135. inline void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
  136. {
  137. for(VertexGroupList::iterator itvg=_uniqVertexGroupList.begin(); itvg!=_uniqVertexGroupList.end(); ++itvg)
  138. {
  139. VertexGroup& uniq = *itvg;
  140. uniq.computeMatrixForVertexSet();
  141. osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
  142. const IndexList& vertices = uniq.getVertices();
  143. for(IndexList::const_iterator vertIDit=vertices.begin(); vertIDit!=vertices.end(); ++vertIDit)
  144. {
  145. dst[*vertIDit] = osg::Matrix::transform3x3(src[*vertIDit],matrix);
  146. }
  147. }
  148. }
  149. protected:
  150. bool _needInit;
  151. virtual bool init(RigGeometry&);
  152. std::map<std::string,bool> _invalidInfluence;
  153. typedef std::vector<VertexGroup> VertexGroupList;
  154. VertexGroupList _uniqVertexGroupList;
  155. void buildMinimumUpdateSet(const RigGeometry&rig );
  156. };
  157. }
  158. #endif