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

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

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
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
16#include <osgAnimation/VertexInfluence>
17#include <osgAnimation/RigTransformSoftware>
18#include <osgAnimation/BoneMapVisitor>
19#include <osgAnimation/RigGeometry>
20
21using namespace osgAnimation;
22
23RigTransformSoftware::RigTransformSoftware()
24{
25    _needInit = true;
26}
27
28bool RigTransformSoftware::init(RigGeometry& geom)
29{
30    if (!geom.getSkeleton())
31        return false;
32
33    BoneMapVisitor mapVisitor;
34    geom.getSkeleton()->accept(mapVisitor);
35    BoneMap bm = mapVisitor.getBoneMap();
36    initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexSetToBoneSetList());
37
38    if (geom.getSourceGeometry())
39        geom.copyFrom(*geom.getSourceGeometry());
40    geom.setVertexArray(0);
41    geom.setNormalArray(0);
42
43    _needInit = false;
44    return true;
45}
46
47void RigTransformSoftware::operator()(RigGeometry& geom)
48{
49    if (_needInit)
50        if (!init(geom))
51            return;
52
53    if (!geom.getSourceGeometry()) {
54        OSG_WARN << this << " RigTransformSoftware no source geometry found on RigGeometry" << std::endl;
55        return;
56    }
57    osg::Geometry& source = *geom.getSourceGeometry();
58    osg::Geometry& destination = geom;
59
60    osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
61    osg::Vec3Array* positionDst = dynamic_cast<osg::Vec3Array*>(destination.getVertexArray());
62    if (positionSrc && (!positionDst || (positionDst->size() != positionSrc->size()) ) )
63    {
64        if (!positionDst)
65        {
66            positionDst = new osg::Vec3Array;
67            positionDst->setDataVariance(osg::Object::DYNAMIC);
68            destination.setVertexArray(positionDst);
69        }
70        *positionDst = *positionSrc;
71    }
72
73    osg::Vec3Array* normalSrc = dynamic_cast<osg::Vec3Array*>(source.getNormalArray());
74    osg::Vec3Array* normalDst = dynamic_cast<osg::Vec3Array*>(destination.getNormalArray());
75    if (normalSrc && (!normalDst || (normalDst->size() != normalSrc->size()) ) )
76    {
77        if (!normalDst)
78        {
79            normalDst = new osg::Vec3Array;
80            normalDst->setDataVariance(osg::Object::DYNAMIC);
81            destination.setNormalArray(normalDst);
82            destination.setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
83        }
84        *normalDst = *normalSrc;
85    }
86
87    if (positionDst && !positionDst->empty())
88    {
89        compute<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
90                           geom.getInvMatrixFromSkeletonToGeometry(),
91                           &positionSrc->front(),
92                           &positionDst->front());
93        positionDst->dirty();
94    }
95
96    if (normalDst && !normalDst->empty())
97    {
98        computeNormal<osg::Vec3>(geom.getMatrixFromSkeletonToGeometry(),
99                           geom.getInvMatrixFromSkeletonToGeometry(),
100                           &normalSrc->front(),
101                           &normalDst->front());
102        normalDst->dirty();
103    }
104}
105
106void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence)
107{
108    _boneSetVertexSet.clear();
109
110    int size = influence.size();
111    _boneSetVertexSet.resize(size);
112    for (int i = 0; i < size; i++)
113    {
114        const VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i];
115        int nbBones = inf.getBones().size();
116        BoneWeightList& boneList = _boneSetVertexSet[i].getBones();
117
118        double sumOfWeight = 0;
119        for (int b = 0; b < nbBones; b++)
120        {
121            const std::string& bname = inf.getBones()[b].getBoneName();
122            float weight = inf.getBones()[b].getWeight();
123            BoneMap::const_iterator it = map.find(bname);
124            if (it == map.end())
125            {
126                OSG_WARN << "RigTransformSoftware Bone " << bname << " not found, skip the influence group " <<bname  << std::endl;
127                continue;
128            }
129            Bone* bone = it->second.get();
130            boneList.push_back(BoneWeight(bone, weight));
131            sumOfWeight += weight;
132        }
133        // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0
134        // so we check it and renormalize the all weight bone
135        const double threshold = 1e-4;
136        if (!_boneSetVertexSet[i].getBones().empty() &&
137            (sumOfWeight < 1.0 - threshold ||  sumOfWeight > 1.0 + threshold))
138        {
139            for (int b = 0; b < (int)boneList.size(); b++)
140                boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight);
141        }
142        _boneSetVertexSet[i].getVertexes() = inf.getVertexes();
143    }
144}
Note: See TracBrowser for help on using the browser.