mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-29 17:15:34 +00:00
Streamline passing influence data to skinning
This commit is contained in:
parent
b67d89f2e0
commit
c1088e5f70
3 changed files with 70 additions and 57 deletions
|
@ -1515,24 +1515,24 @@ namespace NifOsg
|
|||
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
||||
rig->setSourceGeometry(geom);
|
||||
|
||||
// Assign bone weights
|
||||
osg::ref_ptr<SceneUtil::RigGeometry::InfluenceMap> map(new SceneUtil::RigGeometry::InfluenceMap);
|
||||
|
||||
const Nif::NiSkinInstance* skin = niGeometry->mSkin.getPtr();
|
||||
const Nif::NiSkinData* data = skin->mData.getPtr();
|
||||
const Nif::NiAVObjectList& bones = skin->mBones;
|
||||
|
||||
// Assign bone weights
|
||||
std::vector<SceneUtil::RigGeometry::BoneInfo> boneInfo;
|
||||
std::vector<SceneUtil::RigGeometry::VertexWeights> influences;
|
||||
boneInfo.resize(bones.size());
|
||||
influences.resize(bones.size());
|
||||
for (std::size_t i = 0; i < bones.size(); ++i)
|
||||
{
|
||||
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
||||
|
||||
SceneUtil::RigGeometry::BoneInfluence influence;
|
||||
influence.mWeights = data->mBones[i].mWeights;
|
||||
influence.mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
||||
influence.mBoundSphere = data->mBones[i].mBoundSphere;
|
||||
|
||||
map->mData.emplace_back(boneName, influence);
|
||||
boneInfo[i].mName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
||||
boneInfo[i].mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
||||
boneInfo[i].mBoundSphere = data->mBones[i].mBoundSphere;
|
||||
influences[i] = data->mBones[i].mWeights;
|
||||
}
|
||||
rig->setInfluenceMap(map);
|
||||
rig->setBoneInfo(std::move(boneInfo));
|
||||
rig->setInfluences(influences);
|
||||
|
||||
drawable = rig;
|
||||
}
|
||||
|
@ -1671,29 +1671,29 @@ namespace NifOsg
|
|||
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
||||
rig->setSourceGeometry(geometry);
|
||||
|
||||
osg::ref_ptr<SceneUtil::RigGeometry::InfluenceMap> map(new SceneUtil::RigGeometry::InfluenceMap);
|
||||
|
||||
auto skin = static_cast<const Nif::BSSkinInstance*>(bsTriShape->mSkin.getPtr());
|
||||
const Nif::BSSkinInstance* skin = static_cast<const Nif::BSSkinInstance*>(bsTriShape->mSkin.getPtr());
|
||||
const Nif::BSSkinBoneData* data = skin->mData.getPtr();
|
||||
const Nif::NiAVObjectList& bones = skin->mBones;
|
||||
std::vector<std::vector<Nif::NiSkinData::VertWeight>> vertWeights(data->mBones.size());
|
||||
for (size_t i = 0; i < vertices.size(); i++)
|
||||
for (int j = 0; j < 4; j++)
|
||||
vertWeights[bsTriShape->mVertData[i].mBoneIndices[j]].emplace_back(
|
||||
i, halfToFloat(bsTriShape->mVertData[i].mBoneWeights[j]));
|
||||
|
||||
std::vector<SceneUtil::RigGeometry::BoneInfo> boneInfo;
|
||||
std::vector<SceneUtil::RigGeometry::BoneWeights> influences;
|
||||
boneInfo.resize(bones.size());
|
||||
influences.resize(vertices.size());
|
||||
for (std::size_t i = 0; i < bones.size(); ++i)
|
||||
{
|
||||
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
||||
|
||||
SceneUtil::RigGeometry::BoneInfluence influence;
|
||||
influence.mWeights = vertWeights[i];
|
||||
influence.mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
||||
influence.mBoundSphere = data->mBones[i].mBoundSphere;
|
||||
|
||||
map->mData.emplace_back(boneName, influence);
|
||||
boneInfo[i].mName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
||||
boneInfo[i].mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
||||
boneInfo[i].mBoundSphere = data->mBones[i].mBoundSphere;
|
||||
}
|
||||
rig->setInfluenceMap(map);
|
||||
|
||||
for (size_t i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
const Nif::BSVertexData& vertData = bsTriShape->mVertData[i];
|
||||
for (int j = 0; j < 4; j++)
|
||||
influences[i].emplace_back(vertData.mBoneIndices[j], halfToFloat(vertData.mBoneWeights[j]));
|
||||
}
|
||||
rig->setBoneInfo(std::move(boneInfo));
|
||||
rig->setInfluences(influences);
|
||||
|
||||
drawable = rig;
|
||||
}
|
||||
|
|
|
@ -301,23 +301,29 @@ namespace SceneUtil
|
|||
}
|
||||
}
|
||||
|
||||
void RigGeometry::setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap)
|
||||
void RigGeometry::setBoneInfo(std::vector<BoneInfo>&& bones)
|
||||
{
|
||||
mData = new InfluenceData;
|
||||
mData->mBones.reserve(influenceMap->mData.size());
|
||||
if (!mData)
|
||||
mData = new InfluenceData;
|
||||
|
||||
std::unordered_map<unsigned short, std::vector<BoneWeight>> vertexToInfluences;
|
||||
mData->mBones = std::move(bones);
|
||||
}
|
||||
|
||||
void RigGeometry::setInfluences(const std::vector<VertexWeights>& influences)
|
||||
{
|
||||
if (!mData)
|
||||
mData = new InfluenceData;
|
||||
|
||||
std::unordered_map<unsigned short, BoneWeights> vertexToInfluences;
|
||||
size_t index = 0;
|
||||
for (const auto& [boneName, bi] : influenceMap->mData)
|
||||
for (const auto& influence : influences)
|
||||
{
|
||||
mData->mBones.push_back({ boneName, bi.mBoundSphere, bi.mInvBindMatrix });
|
||||
|
||||
for (const auto& [vertex, weight] : bi.mWeights)
|
||||
for (const auto& [vertex, weight] : influence)
|
||||
vertexToInfluences[vertex].emplace_back(index, weight);
|
||||
index++;
|
||||
}
|
||||
|
||||
std::map<std::vector<BoneWeight>, VertexList> influencesToVertices;
|
||||
std::map<BoneWeights, VertexList> influencesToVertices;
|
||||
for (const auto& [vertex, weights] : vertexToInfluences)
|
||||
influencesToVertices[weights].emplace_back(vertex);
|
||||
|
||||
|
@ -325,6 +331,19 @@ namespace SceneUtil
|
|||
mData->mInfluences.assign(influencesToVertices.begin(), influencesToVertices.end());
|
||||
}
|
||||
|
||||
void RigGeometry::setInfluences(const std::vector<BoneWeights>& influences)
|
||||
{
|
||||
if (!mData)
|
||||
mData = new InfluenceData;
|
||||
|
||||
std::map<BoneWeights, VertexList> influencesToVertices;
|
||||
for (size_t i = 0; i < influences.size(); i++)
|
||||
influencesToVertices[influences[i]].emplace_back(i);
|
||||
|
||||
mData->mInfluences.reserve(influencesToVertices.size());
|
||||
mData->mInfluences.assign(influencesToVertices.begin(), influencesToVertices.end());
|
||||
}
|
||||
|
||||
void RigGeometry::accept(osg::NodeVisitor& nv)
|
||||
{
|
||||
if (!nv.validNodeMask(*this))
|
||||
|
|
|
@ -36,21 +36,23 @@ namespace SceneUtil
|
|||
// static parts of the model.
|
||||
void compileGLObjects(osg::RenderInfo& renderInfo) const override {}
|
||||
|
||||
// TODO: Make InfluenceMap more similar to InfluenceData
|
||||
struct BoneInfluence
|
||||
struct BoneInfo
|
||||
{
|
||||
osg::Matrixf mInvBindMatrix;
|
||||
std::string mName;
|
||||
osg::BoundingSpheref mBoundSphere;
|
||||
// <vertex index, weight>
|
||||
std::vector<std::pair<unsigned short, float>> mWeights;
|
||||
osg::Matrixf mInvBindMatrix;
|
||||
};
|
||||
|
||||
struct InfluenceMap : public osg::Referenced
|
||||
{
|
||||
std::vector<std::pair<std::string, BoneInfluence>> mData;
|
||||
};
|
||||
using VertexWeight = std::pair<unsigned short, float>;
|
||||
using VertexWeights = std::vector<VertexWeight>;
|
||||
using BoneWeight = std::pair<size_t, float>;
|
||||
using BoneWeights = std::vector<BoneWeight>;
|
||||
|
||||
void setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap);
|
||||
void setBoneInfo(std::vector<BoneInfo>&& bones);
|
||||
// Convert influences in vertex and weight list per bone format
|
||||
void setInfluences(const std::vector<VertexWeights>& influences);
|
||||
// Convert influences in bone and weight list per vertex format
|
||||
void setInfluences(const std::vector<BoneWeights>& influences);
|
||||
|
||||
/// Initialize this geometry from the source geometry.
|
||||
/// @note The source geometry will not be modified.
|
||||
|
@ -89,19 +91,11 @@ namespace SceneUtil
|
|||
|
||||
osg::ref_ptr<osg::RefMatrix> mGeomToSkelMatrix;
|
||||
|
||||
struct BoneInfo
|
||||
{
|
||||
std::string mName;
|
||||
osg::BoundingSpheref mBoundSphere;
|
||||
osg::Matrixf mInvBindMatrix;
|
||||
};
|
||||
|
||||
using BoneWeight = std::pair<size_t, float>;
|
||||
using VertexList = std::vector<unsigned short>;
|
||||
struct InfluenceData : public osg::Referenced
|
||||
{
|
||||
std::vector<BoneInfo> mBones;
|
||||
std::vector<std::pair<std::vector<BoneWeight>, VertexList>> mInfluences;
|
||||
std::vector<std::pair<BoneWeights, VertexList>> mInfluences;
|
||||
};
|
||||
osg::ref_ptr<InfluenceData> mData;
|
||||
std::vector<Bone*> mNodes;
|
||||
|
|
Loading…
Reference in a new issue