1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 21:40:03 +00:00

Merge branch 'skinning' into 'master'

RigGeometry: convert some pairs to structs

See merge request OpenMW/openmw!327
This commit is contained in:
psi29a 2020-10-08 08:56:17 +00:00
commit bbcfcc8823
3 changed files with 54 additions and 39 deletions

View File

@ -1239,15 +1239,13 @@ namespace NifOsg
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->name);
SceneUtil::RigGeometry::BoneInfluence influence;
const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[i].weights;
const auto& weights = data->bones[i].weights;
for(size_t j = 0;j < weights.size();j++)
{
influence.mWeights.emplace_back(weights[j].vertex, weights[j].weight);
}
influence.mWeights.push_back({weights[j].vertex, weights[j].weight});
influence.mInvBindMatrix = data->bones[i].trafo.toMatrix();
influence.mBoundSphere = osg::BoundingSpheref(data->bones[i].boundSphereCenter, data->bones[i].boundSphereRadius);
map->mData.emplace_back(boneName, influence);
map->mData.push_back({boneName, influence});
}
rig->setInfluenceMap(map);

View File

@ -137,14 +137,13 @@ bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv)
}
mBoneNodesVector.clear();
for (auto& bonePair : mBoneSphereVector->mData)
for (auto& boundPair : mBoneSphereVector->mData)
{
const std::string& boneName = bonePair.first;
Bone* bone = mSkeleton->getBone(boneName);
Bone* bone = mSkeleton->getBone(boundPair.name);
if (!bone)
{
mBoneNodesVector.push_back(nullptr);
Log(Debug::Error) << "Error: RigGeometry did not find bone " << boneName;
Log(Debug::Error) << "Error: RigGeometry did not find bone " << boundPair.name;
continue;
}
@ -155,12 +154,11 @@ bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv)
{
for (auto &weight : pair.first)
{
const std::string& boneName = weight.first.first;
Bone* bone = mSkeleton->getBone(boneName);
Bone* bone = mSkeleton->getBone(weight.boneName);
if (!bone)
{
mBoneNodesVector.push_back(nullptr);
Log(Debug::Error) << "Error: RigGeometry did not find bone " << boneName;
Log(Debug::Error) << "Error: RigGeometry did not find bone " << weight.boneName;
continue;
}
@ -218,7 +216,7 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
if (bone == nullptr)
continue;
accumulateMatrix(weight.first.second, bone->mMatrixInSkeletonSpace, weight.second, resultMat);
accumulateMatrix(weight.bindMatrix, bone->mMatrixInSkeletonSpace, weight.value, resultMat);
index++;
}
@ -281,7 +279,7 @@ void RigGeometry::updateBounds(osg::NodeVisitor *nv)
continue;
index++;
osg::BoundingSpheref bs = boundPair.second;
osg::BoundingSpheref bs = boundPair.sphere;
if (mGeomToSkelMatrix)
transformBoundingSphere(bone->mMatrixInSkeletonSpace * (*mGeomToSkelMatrix), bs);
else
@ -337,30 +335,21 @@ void RigGeometry::setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap)
{
mInfluenceMap = influenceMap;
typedef std::map<unsigned short, std::vector<BoneWeight> > Vertex2BoneMap;
using Vertex2BoneMap = std::map<unsigned short, std::vector<BoneWeight>>;
Vertex2BoneMap vertex2BoneMap;
mBoneSphereVector = new BoneSphereVector;
mBoneSphereVector->mData.reserve(mInfluenceMap->mData.size());
mBone2VertexVector = new Bone2VertexVector;
for (auto& influencePair : mInfluenceMap->mData)
for (const BoneData& bone : mInfluenceMap->mData)
{
const std::string& boneName = influencePair.first;
const BoneInfluence& bi = influencePair.second;
mBoneSphereVector->mData.emplace_back(boneName, bi.mBoundSphere);
for (auto& weightPair: bi.mWeights)
{
std::vector<BoneWeight>& vec = vertex2BoneMap[weightPair.first];
vec.emplace_back(std::make_pair(boneName, bi.mInvBindMatrix), weightPair.second);
}
mBoneSphereVector->mData.push_back({bone.name, bone.influence.mBoundSphere});
for (auto& weight : bone.influence.mWeights)
vertex2BoneMap[weight.vertex].push_back({bone.name, bone.influence.mInvBindMatrix, weight.value});
}
Bone2VertexMap bone2VertexMap;
for (auto& vertexPair : vertex2BoneMap)
{
bone2VertexMap[vertexPair.second].emplace_back(vertexPair.first);
}
mBone2VertexVector->mData.reserve(bone2VertexMap.size());
mBone2VertexVector->mData.assign(bone2VertexMap.begin(), bone2VertexMap.end());

View File

@ -25,17 +25,32 @@ namespace SceneUtil
// Currently empty as this is difficult to implement. Technically we would need to compile both internal geometries in separate frames but this method is only called once. Alternatively we could compile just the static parts of the model.
virtual void compileGLObjects(osg::RenderInfo& renderInfo) const {}
struct VertexWeight
{
unsigned short vertex;
float value;
};
struct BoneInfluence
{
osg::Matrixf mInvBindMatrix;
osg::BoundingSpheref mBoundSphere;
// <vertex index, weight>
std::vector<std::pair<unsigned short, float>> mWeights;
std::vector<VertexWeight> mWeights;
};
struct BoneData
{
std::string name;
BoneInfluence influence;
bool operator<(const BoneData& other) const
{
return name < other.name;
}
};
struct InfluenceMap : public osg::Referenced
{
std::vector<std::pair<std::string, BoneInfluence>> mData;
std::vector<BoneData> mData;
};
void setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap);
@ -79,23 +94,36 @@ namespace SceneUtil
osg::ref_ptr<InfluenceMap> mInfluenceMap;
typedef std::pair<std::string, osg::Matrixf> BoneBindMatrixPair;
struct BoneWeight
{
std::string boneName;
osg::Matrixf bindMatrix;
float value;
bool operator<(const BoneWeight& other) const
{
return boneName < other.boneName;
}
};
typedef std::pair<BoneBindMatrixPair, float> BoneWeight;
typedef std::vector<unsigned short> VertexList;
typedef std::map<std::vector<BoneWeight>, VertexList> Bone2VertexMap;
using VertexList = std::vector<unsigned short>;
using BoneWeightList = std::vector<BoneWeight>;
using Bone2VertexMap = std::map<BoneWeightList, VertexList>;
struct Bone2VertexVector : public osg::Referenced
{
std::vector<std::pair<std::vector<BoneWeight>, VertexList>> mData;
std::vector<std::pair<BoneWeightList, VertexList>> mData;
};
osg::ref_ptr<Bone2VertexVector> mBone2VertexVector;
struct BoneSphere
{
std::string name;
osg::BoundingSpheref sphere;
};
struct BoneSphereVector : public osg::Referenced
{
std::vector<std::pair<std::string, osg::BoundingSpheref>> mData;
std::vector<BoneSphere> mData;
};
osg::ref_ptr<BoneSphereVector> mBoneSphereVector;
std::vector<Bone*> mBoneNodesVector;