root/OpenSceneGraph/trunk/include/osgAnimation/RigTransformSoftware @ 13041

Revision 13041, 6.2 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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
24namespace 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
34        RigTransformSoftware();
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:
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                {
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;
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
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
Note: See TracBrowser for help on using the browser.