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

Revision 10693, 4.8 kB (checked in by cedricpinson, 4 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 
[9093]1/*  -*-c++-*-
[10693]2 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
[9093]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.
[10693]13 */
[9093]14
15#include <osgAnimation/VertexInfluence>
[10656]16#include <osg/Notify>
[9093]17#include <iostream>
18#include <algorithm>
19
20using namespace osgAnimation;
21
[10693]22void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); }
23const VertexInfluenceSet::VertexIndexToBoneWeightMap& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;}
[9093]24// this class manage VertexInfluence database by mesh
25// reference bones per vertex ...
[10693]26void VertexInfluenceSet::buildVertex2BoneList()
[9093]27{
28    _vertex2Bones.clear();
29    for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); it++)
30    {
31        const VertexInfluence& vi = (*it);
32        int size = vi.size();
33        for (int i = 0; i < size; i++)
34        {
35            VertexIndexWeight viw = vi[i];
36            int index = viw.first;
37            float weight = viw.second;
38            if (vi.getName().empty())
[10693]39                osg::notify(osg::WARN) << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl;
[9093]40            _vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight));
41        }
42    }
43
44    // normalize weight per vertex
[10656]45    for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); it++)
[9093]46    {
47        BoneWeightList& bones = it->second;
48        int size = bones.size();
49        float sum = 0;
50        for (int i = 0; i < size; i++)
51            sum += bones[i].getWeight();
52        if (sum < 1e-4)
53        {
[10656]54            osg::notify(osg::WARN) << "VertexInfluenceSet::buildVertex2BoneList warning the vertex " << it->first << " seems to have 0 weight, skip normalize for this vertex" << std::endl;
[9093]55        }
56        else 
57        {
58            float mult = 1.0/sum;
59            for (int i = 0; i < size; i++)
60                bones[i].setWeight(bones[i].getWeight() * mult);
61        }
62    }
63}
64
65
66
67// sort by name and weight
[10693]68struct SortByNameAndWeight : public std::less<VertexInfluenceSet::BoneWeight>
[9093]69{
[10693]70    bool operator()(const VertexInfluenceSet::BoneWeight& b0,
71                    const VertexInfluenceSet::BoneWeight& b1) const 
[9093]72    {
73        if (b0.getBoneName() < b1.getBoneName())
74            return true;
75        else if (b0.getBoneName() > b1.getBoneName())
76            return false;
77        if (b0.getWeight() < b1.getWeight())
78            return true;
79        return false;
80    }
81};
82
[10693]83struct SortByBoneWeightList : public std::less<VertexInfluenceSet::BoneWeightList>
[9093]84{
[10693]85    bool operator()(const VertexInfluenceSet::BoneWeightList& b0,
86                    const VertexInfluenceSet::BoneWeightList& b1) const 
[9093]87    {
88        if (b0.size() < b1.size())
89            return true;
90        else if (b0.size() > b1.size())
91            return false;
92
93        int size = b0.size();
94        for (int i = 0; i < size; i++)
95        {
96            bool result = SortByNameAndWeight()(b0[i], b1[i]);
97            if (result)
98                return true;
99            else if (SortByNameAndWeight()(b1[i], b0[i]))
100                return false;
101        }
102        return false;
103    }
104};
105
[10693]106void VertexInfluenceSet::clear()
[9093]107{
[10693]108    _bone2Vertexes.clear();
[9093]109    _uniqVertexSetToBoneSet.clear();
[10693]110}
[9093]111
[10693]112void VertexInfluenceSet::buildUniqVertexSetToBoneSetList()
113{
114    _uniqVertexSetToBoneSet.clear();
115
[9093]116    typedef std::map<BoneWeightList,UniqVertexSetToBoneSet, SortByBoneWeightList> UnifyBoneGroup;
117    UnifyBoneGroup unifyBuffer;
118
119    for (VertexIndexToBoneWeightMap::iterator it = _vertex2Bones.begin(); it != _vertex2Bones.end(); it++)
120    {
121        BoneWeightList bones = it->second;
122        int vertexIndex = it->first;
123
124        // sort the vector to have a consistent key
125        std::sort(bones.begin(), bones.end(), SortByNameAndWeight());
126   
127        // we use the vector<BoneWeight> as key to differentiate group
128        UnifyBoneGroup::iterator result = unifyBuffer.find(bones);
129        if (result == unifyBuffer.end())
130            unifyBuffer[bones].setBones(bones);
131        unifyBuffer[bones].getVertexes().push_back(vertexIndex);
132    }
133
134    _uniqVertexSetToBoneSet.reserve(unifyBuffer.size());
135    for (UnifyBoneGroup::iterator it = unifyBuffer.begin(); it != unifyBuffer.end(); it++)
136    {
137        _uniqVertexSetToBoneSet.push_back(it->second);
138    }
139}
Note: See TracBrowser for help on using the browser.