| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | #include <osgAnimation/VertexInfluence> |
|---|
| 17 | #include <osgAnimation/RigTransformSoftware> |
|---|
| 18 | #include <osgAnimation/BoneMapVisitor> |
|---|
| 19 | #include <osgAnimation/RigGeometry> |
|---|
| 20 | |
|---|
| 21 | using namespace osgAnimation; |
|---|
| 22 | |
|---|
| 23 | RigTransformSoftware::RigTransformSoftware() |
|---|
| 24 | { |
|---|
| 25 | _needInit = true; |
|---|
| 26 | } |
|---|
| 27 | |
|---|
| 28 | bool 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 | |
|---|
| 47 | void 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 | |
|---|
| 106 | void 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 | |
|---|
| 134 | |
|---|
| 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 | } |
|---|