Streamline passing influence data to skinning

macos_ci_fix
Alexei Kotov 1 year ago
parent b67d89f2e0
commit c1088e5f70

@ -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); 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->setInfluenceMap(map); 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)
{ {
mData = new InfluenceData; if (!mData)
mData->mBones.reserve(influenceMap->mData.size()); mData = new InfluenceData;
mData->mBones = std::move(bones);
}
void RigGeometry::setInfluences(const std::vector<VertexWeights>& influences)
{
if (!mData)
mData = new InfluenceData;
std::unordered_map<unsigned short, std::vector<BoneWeight>> vertexToInfluences; std::unordered_map<unsigned short, BoneWeights> vertexToInfluences;
size_t index = 0; 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] : influence)
for (const auto& [vertex, weight] : bi.mWeights)
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…
Cancel
Save