OSG  3.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RigTransformSoftware.h
Go to the documentation of this file.
1 /* -*-c++-*-
2  * Copyright (C) 2009 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 
15 #ifndef OSGANIMATION_RIGTRANSFORM_SOFTWARE
16 #define OSGANIMATION_RIGTRANSFORM_SOFTWARE 1
17 
18 #include <osgAnimation/Export>
19 #include <osgAnimation/RigTransform>
20 #include <osgAnimation/Bone>
21 #include <osgAnimation/VertexInfluence>
22 #include <osg/observer_ptr>
23 
24 namespace osgAnimation
25 {
26 
27  class RigGeometry;
28 
31  {
32  public:
33 
35  virtual void operator()(RigGeometry&);
36 
37 
38  class BoneWeight
39  {
40  public:
41  BoneWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {}
42  const Bone* getBone() const { return _bone.get(); }
43  float getWeight() const { return _weight; }
44  void setWeight(float w) { _weight = w; }
45  protected:
47  float _weight;
48  };
49 
50  typedef std::vector<BoneWeight> BoneWeightList;
51  typedef std::vector<int> VertexList;
52 
54  {
55  public:
56  BoneWeightList& getBones() { return _bones; }
57  VertexList& getVertexes() { return _vertexes; }
58 
59  void resetMatrix()
60  {
61  _result.set(0, 0, 0, 0,
62  0, 0, 0, 0,
63  0, 0, 0, 0,
64  0, 0, 0, 1);
65  }
66  void accummulateMatrix(const osg::Matrix& invBindMatrix, const osg::Matrix& matrix, osg::Matrix::value_type weight)
67  {
68  osg::Matrix m = invBindMatrix * matrix;
69  osg::Matrix::value_type* ptr = m.ptr();
70  osg::Matrix::value_type* ptrresult = _result.ptr();
71  ptrresult[0] += ptr[0] * weight;
72  ptrresult[1] += ptr[1] * weight;
73  ptrresult[2] += ptr[2] * weight;
74 
75  ptrresult[4] += ptr[4] * weight;
76  ptrresult[5] += ptr[5] * weight;
77  ptrresult[6] += ptr[6] * weight;
78 
79  ptrresult[8] += ptr[8] * weight;
80  ptrresult[9] += ptr[9] * weight;
81  ptrresult[10] += ptr[10] * weight;
82 
83  ptrresult[12] += ptr[12] * weight;
84  ptrresult[13] += ptr[13] * weight;
85  ptrresult[14] += ptr[14] * weight;
86  }
88  {
89  if (_bones.empty())
90  {
91  osg::notify(osg::WARN) << this << " RigTransformSoftware::UniqBoneSetVertexSet no bones found" << std::endl;
92  _result = osg::Matrix::identity();
93  return;
94  }
95  resetMatrix();
96 
97  int size = _bones.size();
98  for (int i = 0; i < size; i++)
99  {
100  const Bone* bone = _bones[i].getBone();
101  if (!bone)
102  {
103  osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl;
104  continue;
105  }
106  const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
107  const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace();
108  osg::Matrix::value_type w = _bones[i].getWeight();
109  accummulateMatrix(invBindMatrix, matrix, w);
110  }
111  }
112  const osg::Matrix& getMatrix() const { return _result;}
113  protected:
114  BoneWeightList _bones;
115  VertexList _vertexes;
117  };
118 
119 
120 
121  template <class V> void compute(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
122  {
123  // the result of matrix mult should be cached to be used for vertexes transform and normal transform and maybe other computation
124  int size = _boneSetVertexSet.size();
125  for (int i = 0; i < size; i++)
126  {
127  UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
129  osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
130 
131  const VertexList& vertexes = uniq.getVertexes();
132  int vertexSize = vertexes.size();
133  for (int j = 0; j < vertexSize; j++)
134  {
135  int idx = vertexes[j];
136  dst[idx] = src[idx] * matrix;
137  }
138  }
139  }
140 
141 
142  template <class V> void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst)
143  {
144  int size = _boneSetVertexSet.size();
145  for (int i = 0; i < size; i++)
146  {
147  UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
149  osg::Matrix matrix = transform * uniq.getMatrix() * invTransform;
150 
151  const VertexList& vertexes = uniq.getVertexes();
152  int vertexSize = vertexes.size();
153  for (int j = 0; j < vertexSize; j++)
154  {
155  int idx = vertexes[j];
156  dst[idx] = osg::Matrix::transform3x3(src[idx],matrix);
157  }
158  }
159  }
160 
161  protected:
162 
163  bool init(RigGeometry&);
164  void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence);
165  std::vector<UniqBoneSetVertexSet> _boneSetVertexSet;
166 
167  bool _needInit;
168 
169  };
170 }
171 
172 #endif
#define OSGANIMATION_EXPORT
Definition: Export.h:40
static Matrixd identity(void)
Definition: Matrixd.h:438
static Vec3f transform3x3(const Vec3f &v, const Matrixd &m)
Definition: Matrixd.h:659
void computeNormal(const osg::Matrix &transform, const osg::Matrix &invTransform, const V *src, V *dst)
std::vector< BoneWeight > BoneWeightList
double value_type
Definition: Matrixd.h:30
const osg::Matrix & getInvBindMatrixInSkeletonSpace() const
Definition: Bone.h:46
std::map< std::string, osg::ref_ptr< Bone > > BoneMap
Definition: Bone.h:59
const osg::Matrix & getMatrixInSkeletonSpace() const
Definition: Bone.h:45
This class manage format for software skinning.
std::vector< UniqVertexSetToBoneSet > UniqVertexSetToBoneSetList
value_type * ptr()
Definition: Matrixd.h:92
OSG_EXPORT std::ostream & notify(const NotifySeverity severity)
std::vector< UniqBoneSetVertexSet > _boneSetVertexSet
void compute(const osg::Matrix &transform, const osg::Matrix &invTransform, const V *src, V *dst)
void accummulateMatrix(const osg::Matrix &invBindMatrix, const osg::Matrix &matrix, osg::Matrix::value_type weight)