#
root/OpenSceneGraph/trunk/include/osgAnimation/RigTransformSoftware
@
11009

Revision 11009, 6.2 kB (checked in by robert, 7 years ago) |
---|

Rev | Line | |
---|---|---|

[10693] | 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 | ||

[11009] | 15 | #ifndef OSGANIMATION_RIGTRANSFORM_SOFTWARE |

16 | #define OSGANIMATION_RIGTRANSFORM_SOFTWARE 1 | |

[10693] | 17 | |

18 | #include <osgAnimation/Export> | |

19 | #include <osgAnimation/RigTransform> | |

20 | #include <osgAnimation/Bone> | |

[11009] | 21 | #include <osgAnimation/VertexInfluence> |

22 | #include <osg/observer_ptr> | |

[10693] | 23 | |

24 | namespace osgAnimation | |

25 | { | |

26 | ||

27 | class RigGeometry; | |

28 | ||

29 | /// This class manage format for hardware skinning | |

30 | class OSGANIMATION_EXPORT RigTransformSoftware : public RigTransform | |

31 | { | |

32 | public: | |

33 | ||

[11009] | 34 | RigTransformSoftware(); |

35 | virtual void operator()(RigGeometry&); | |

[10693] | 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: | |

46 | osg::observer_ptr<Bone> _bone; | |

47 | float _weight; | |

48 | }; | |

49 | ||

50 | typedef std::vector<BoneWeight> BoneWeightList; | |

51 | typedef std::vector<int> VertexList; | |

52 | ||

53 | class UniqBoneSetVertexSet | |

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 | } | |

87 | void computeMatrixForVertexSet() | |

88 | { | |

89 | if (_bones.empty()) | |

90 | { | |

[10877] | 91 | osg::notify(osg::WARN) << this << " RigTransformSoftware::UniqBoneSetVertexSet no bones found" << std::endl; |

[10693] | 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(); | |

[10877] | 101 | if (!bone) |

102 | { | |

103 | osg::notify(osg::WARN) << this << " RigTransformSoftware::computeMatrixForVertexSet Warning a bone is null, skip it" << std::endl; | |

104 | continue; | |

105 | } | |

[10693] | 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; | |

116 | osg::Matrix _result; | |

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]; | |

128 | uniq.computeMatrixForVertexSet(); | |

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]; | |

148 | uniq.computeMatrixForVertexSet(); | |

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 | ||

[11009] | 163 | bool init(RigGeometry&); |

164 | void initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence); | |

[10693] | 165 | std::vector<UniqBoneSetVertexSet> _boneSetVertexSet; |

166 | ||

[11009] | 167 | bool _needInit; |

168 | ||

[10693] | 169 | }; |

170 | } | |

171 | ||

172 | #endif |

**Note:**See TracBrowser for help on using the browser.