void RigTransformSoftware::initVertexSetFromBones(const BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence) { _boneSetVertexSet.clear(); int size = influence.size(); _boneSetVertexSet.resize(size); for (int i = 0; i < size; i++) { const VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i]; int nbBones = inf.getBones().size(); BoneWeightList& boneList = _boneSetVertexSet[i].getBones(); double sumOfWeight = 0; for (int b = 0; b < nbBones; b++) { const std::string& bname = inf.getBones()[b].getBoneName(); float weight = inf.getBones()[b].getWeight(); BoneMap::const_iterator it = map.find(bname); if (it == map.end()) { OSG_WARN << "RigTransformSoftware Bone " << bname << " not found, skip the influence group " <<bname << std::endl; continue; } Bone* bone = it->second.get(); boneList.push_back(BoneWeight(bone, weight)); sumOfWeight += weight; } // if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0 // so we check it and renormalize the all weight bone const double threshold = 1e-4; if (!_boneSetVertexSet[i].getBones().empty() && (sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold)) { for (int b = 0; b < (int)boneList.size(); b++) boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight); } _boneSetVertexSet[i].getVertexes() = inf.getVertexes(); } }
bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap) { typedef std::map<std::string, int> BoneNameCountMap; BonePalette palette; BoneNameCountMap boneNameCountMap; // init vertex attribute data VertexIndexWeightList vertexIndexWeight; vertexIndexWeight.resize(nbVertexes); int maxBonePerVertex = 0; for (VertexInfluenceSet::VertexIndexToBoneWeightMap::const_iterator vit = vertexIndexToBoneWeightMap.begin(); vit != vertexIndexToBoneWeightMap.end(); ++vit) { int vertexIndex = vit->first; const VertexInfluenceSet::BoneWeightList& boneWeightList = vit->second; int bonesForThisVertex = 0; for (VertexInfluenceSet::BoneWeightList::const_iterator it = boneWeightList.begin(); it != boneWeightList.end(); ++it) { const VertexInfluenceSet::BoneWeight& bw = *it; if(fabs(bw.getWeight()) > 1e-2) // dont use bone with weight too small { if (boneNameCountMap.find(bw.getBoneName()) != boneNameCountMap.end()) { boneNameCountMap[bw.getBoneName()]++; bonesForThisVertex++; // count max number of bones per vertexes vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight())); } else { if (boneMap.find(bw.getBoneName()) == boneMap.end()) { OSG_INFO << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << " skip this influence" << std::endl; continue; } boneNameCountMap[bw.getBoneName()] = 1; // for stats bonesForThisVertex++; palette.push_back(boneMap[bw.getBoneName()]); _boneNameToPalette[bw.getBoneName()] = palette.size()-1; vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(_boneNameToPalette[bw.getBoneName()],bw.getWeight())); } } else { OSG_WARN << "RigTransformHardware::createPalette Bone " << bw.getBoneName() << " has a weight " << bw.getWeight() << " for vertex " << vertexIndex << " this bone will not be in the palette" << std::endl; } } maxBonePerVertex = osg::maximum(maxBonePerVertex, bonesForThisVertex); } OSG_INFO << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; OSG_INFO << "RigTransformHardware::createPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); ++it) { OSG_INFO << "RigTransformHardware::createPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; } OSG_INFO << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++) vertexIndexWeight[i].resize(maxBonePerVertex); _nbVertexes = nbVertexes; _bonesPerVertex = maxBonePerVertex; _bonePalette = palette; _vertexIndexMatrixWeightList = vertexIndexWeight; _uniformMatrixPalette = createVertexUniform(); _boneWeightAttribArrays = createVertexAttribList(); return true; }