mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +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);
|
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
||||||
rig->setSourceGeometry(geom);
|
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::NiSkinInstance* skin = niGeometry->mSkin.getPtr();
|
||||||
const Nif::NiSkinData* data = skin->mData.getPtr();
|
const Nif::NiSkinData* data = skin->mData.getPtr();
|
||||||
const Nif::NiAVObjectList& bones = skin->mBones;
|
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)
|
for (std::size_t i = 0; i < bones.size(); ++i)
|
||||||
{
|
{
|
||||||
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
boneInfo[i].mName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
||||||
|
boneInfo[i].mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
||||||
SceneUtil::RigGeometry::BoneInfluence influence;
|
boneInfo[i].mBoundSphere = data->mBones[i].mBoundSphere;
|
||||||
influence.mWeights = data->mBones[i].mWeights;
|
influences[i] = data->mBones[i].mWeights;
|
||||||
influence.mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
|
||||||
influence.mBoundSphere = data->mBones[i].mBoundSphere;
|
|
||||||
|
|
||||||
map->mData.emplace_back(boneName, influence);
|
|
||||||
}
|
}
|
||||||
rig->setInfluenceMap(map);
|
rig->setBoneInfo(std::move(boneInfo));
|
||||||
|
rig->setInfluences(influences);
|
||||||
|
|
||||||
drawable = rig;
|
drawable = rig;
|
||||||
}
|
}
|
||||||
|
@ -1671,29 +1671,29 @@ namespace NifOsg
|
||||||
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
osg::ref_ptr<SceneUtil::RigGeometry> rig(new SceneUtil::RigGeometry);
|
||||||
rig->setSourceGeometry(geometry);
|
rig->setSourceGeometry(geometry);
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::RigGeometry::InfluenceMap> map(new SceneUtil::RigGeometry::InfluenceMap);
|
const Nif::BSSkinInstance* skin = static_cast<const Nif::BSSkinInstance*>(bsTriShape->mSkin.getPtr());
|
||||||
|
|
||||||
auto skin = static_cast<const Nif::BSSkinInstance*>(bsTriShape->mSkin.getPtr());
|
|
||||||
const Nif::BSSkinBoneData* data = skin->mData.getPtr();
|
const Nif::BSSkinBoneData* data = skin->mData.getPtr();
|
||||||
const Nif::NiAVObjectList& bones = skin->mBones;
|
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)
|
for (std::size_t i = 0; i < bones.size(); ++i)
|
||||||
{
|
{
|
||||||
std::string boneName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
boneInfo[i].mName = Misc::StringUtils::lowerCase(bones[i].getPtr()->mName);
|
||||||
|
boneInfo[i].mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
||||||
SceneUtil::RigGeometry::BoneInfluence influence;
|
boneInfo[i].mBoundSphere = data->mBones[i].mBoundSphere;
|
||||||
influence.mWeights = vertWeights[i];
|
|
||||||
influence.mInvBindMatrix = data->mBones[i].mTransform.toMatrix();
|
|
||||||
influence.mBoundSphere = data->mBones[i].mBoundSphere;
|
|
||||||
|
|
||||||
map->mData.emplace_back(boneName, influence);
|
|
||||||
}
|
}
|
||||||
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;
|
drawable = rig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,23 +301,29 @@ namespace SceneUtil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RigGeometry::setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap)
|
void RigGeometry::setBoneInfo(std::vector<BoneInfo>&& bones)
|
||||||
{
|
{
|
||||||
|
if (!mData)
|
||||||
mData = new InfluenceData;
|
mData = new InfluenceData;
|
||||||
mData->mBones.reserve(influenceMap->mData.size());
|
|
||||||
|
|
||||||
std::unordered_map<unsigned short, std::vector<BoneWeight>> vertexToInfluences;
|
mData->mBones = std::move(bones);
|
||||||
size_t index = 0;
|
}
|
||||||
for (const auto& [boneName, bi] : influenceMap->mData)
|
|
||||||
|
void RigGeometry::setInfluences(const std::vector<VertexWeights>& influences)
|
||||||
{
|
{
|
||||||
mData->mBones.push_back({ boneName, bi.mBoundSphere, bi.mInvBindMatrix });
|
if (!mData)
|
||||||
|
mData = new InfluenceData;
|
||||||
|
|
||||||
for (const auto& [vertex, weight] : bi.mWeights)
|
std::unordered_map<unsigned short, BoneWeights> vertexToInfluences;
|
||||||
|
size_t index = 0;
|
||||||
|
for (const auto& influence : influences)
|
||||||
|
{
|
||||||
|
for (const auto& [vertex, weight] : influence)
|
||||||
vertexToInfluences[vertex].emplace_back(index, weight);
|
vertexToInfluences[vertex].emplace_back(index, weight);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::vector<BoneWeight>, VertexList> influencesToVertices;
|
std::map<BoneWeights, VertexList> influencesToVertices;
|
||||||
for (const auto& [vertex, weights] : vertexToInfluences)
|
for (const auto& [vertex, weights] : vertexToInfluences)
|
||||||
influencesToVertices[weights].emplace_back(vertex);
|
influencesToVertices[weights].emplace_back(vertex);
|
||||||
|
|
||||||
|
@ -325,6 +331,19 @@ namespace SceneUtil
|
||||||
mData->mInfluences.assign(influencesToVertices.begin(), influencesToVertices.end());
|
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)
|
void RigGeometry::accept(osg::NodeVisitor& nv)
|
||||||
{
|
{
|
||||||
if (!nv.validNodeMask(*this))
|
if (!nv.validNodeMask(*this))
|
||||||
|
|
|
@ -36,21 +36,23 @@ namespace SceneUtil
|
||||||
// static parts of the model.
|
// static parts of the model.
|
||||||
void compileGLObjects(osg::RenderInfo& renderInfo) const override {}
|
void compileGLObjects(osg::RenderInfo& renderInfo) const override {}
|
||||||
|
|
||||||
// TODO: Make InfluenceMap more similar to InfluenceData
|
struct BoneInfo
|
||||||
struct BoneInfluence
|
|
||||||
{
|
{
|
||||||
osg::Matrixf mInvBindMatrix;
|
std::string mName;
|
||||||
osg::BoundingSpheref mBoundSphere;
|
osg::BoundingSpheref mBoundSphere;
|
||||||
// <vertex index, weight>
|
osg::Matrixf mInvBindMatrix;
|
||||||
std::vector<std::pair<unsigned short, float>> mWeights;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InfluenceMap : public osg::Referenced
|
using VertexWeight = std::pair<unsigned short, float>;
|
||||||
{
|
using VertexWeights = std::vector<VertexWeight>;
|
||||||
std::vector<std::pair<std::string, BoneInfluence>> mData;
|
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.
|
/// Initialize this geometry from the source geometry.
|
||||||
/// @note The source geometry will not be modified.
|
/// @note The source geometry will not be modified.
|
||||||
|
@ -89,19 +91,11 @@ namespace SceneUtil
|
||||||
|
|
||||||
osg::ref_ptr<osg::RefMatrix> mGeomToSkelMatrix;
|
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>;
|
using VertexList = std::vector<unsigned short>;
|
||||||
struct InfluenceData : public osg::Referenced
|
struct InfluenceData : public osg::Referenced
|
||||||
{
|
{
|
||||||
std::vector<BoneInfo> mBones;
|
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;
|
osg::ref_ptr<InfluenceData> mData;
|
||||||
std::vector<Bone*> mNodes;
|
std::vector<Bone*> mNodes;
|
||||||
|
|
Loading…
Reference in a new issue