root/OpenSceneGraph/trunk/src/osgAnimation/RigTransformSoftware.cpp @ 10693

Revision 10693, 3.8 kB (checked in by cedricpinson, 5 years ago)

From Cedric Pinson, The following commit include:
* Refactore of RigGeometry? to support hardware skinning
* Refactore of Timeline to split Action in differents files
* Add example how to use hardware skinning

RevLine 
[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
15
16#include <osgAnimation/RigTransformSoftware>
17#include <osgAnimation/RigGeometry>
18
19using namespace osgAnimation;
20
21bool RigTransformSoftware::init(RigGeometry& geom)
22{
23    if (!geom.getSkeleton())
24        return false;
25    Bone::BoneMap bm = geom.getSkeleton()->getBoneMap();
26    initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexSetToBoneSetList());
27    _needInit = false;
28    return true;
29}
30
31void RigTransformSoftware::update(RigGeometry& geom)
32{
33    osg::Vec3Array* pos = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
34    if (pos && _positionSource.size() != pos->size())
35    {
36        _positionSource = std::vector<osg::Vec3>(pos->begin(),pos->end());
37        geom.getVertexArray()->setDataVariance(osg::Object::DYNAMIC);
38    }
39    osg::Vec3Array* normal = dynamic_cast<osg::Vec3Array*>(geom.getNormalArray());
40    if (normal && _normalSource.size() != normal->size())
41    {
42        _normalSource = std::vector<osg::Vec3>(normal->begin(),normal->end());
43        geom.getNormalArray()->setDataVariance(osg::Object::DYNAMIC);
44    }
45
46    if (!_positionSource.empty())
47    {
48        compute<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry(),  &_positionSource.front(), &pos->front());
49        pos->dirty();
50    }
51    if (!_normalSource.empty())
52    {
53        computeNormal<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry(), &_normalSource.front(), &normal->front());
54        normal->dirty();
55    }
56}
57
58void RigTransformSoftware::initVertexSetFromBones(const Bone::BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence)
59{
60    _boneSetVertexSet.clear();
61
62    int size = influence.size();
63    _boneSetVertexSet.resize(size);
64    for (int i = 0; i < size; i++)
65    {
66        const VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i];
67        int nbBones = inf.getBones().size();
68        BoneWeightList& boneList = _boneSetVertexSet[i].getBones();
69
70        double sumOfWeight = 0;
71        for (int b = 0; b < nbBones; b++)
72        {
73            const std::string& bname = inf.getBones()[b].getBoneName();
74            float weight = inf.getBones()[b].getWeight();
75            Bone::BoneMap::const_iterator it = map.find(bname);
76            if (it == map.end())
77            {
78                osg::notify(osg::WARN) << "RigTransformSoftware Bone " << bname << " not found, skip the influence group " <<bname  << std::endl;
79                continue;
80            }
81            Bone* bone = it->second.get();
82            boneList.push_back(BoneWeight(bone, weight));
83            sumOfWeight += weight;
84        }
85        // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0
86        // so we check it and renormalize the all weight bone
87        const double threshold = 1e-4;
88        if (!_boneSetVertexSet[i].getBones().empty() &&
89            (sumOfWeight < 1.0 - threshold ||  sumOfWeight > 1.0 + threshold))
90        {
91            for (int b = 0; b < (int)boneList.size(); b++)
92                boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight);
93        }
94        _boneSetVertexSet[i].getVertexes() = inf.getVertexes();
95    }
96}
Note: See TracBrowser for help on using the browser.