mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 14:59:54 +00:00
Support Fallout 4 skinning
Convert the skinning data into NiSkinData-compatible format
This commit is contained in:
parent
b9d42946be
commit
284129b9ec
2 changed files with 39 additions and 2 deletions
|
@ -426,6 +426,8 @@ namespace Nif
|
|||
mSkin.post(nif);
|
||||
mShaderProperty.post(nif);
|
||||
mAlphaProperty.post(nif);
|
||||
if (!mSkin.empty())
|
||||
nif.setUseSkinning(true);
|
||||
}
|
||||
|
||||
void BSDynamicTriShape::read(NIFStream* nif)
|
||||
|
|
|
@ -1572,6 +1572,8 @@ namespace NifOsg
|
|||
geometry->addPrimitiveSet(
|
||||
new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, triangles.size(), triangles.data()));
|
||||
|
||||
osg::ref_ptr<osg::Drawable> drawable = geometry;
|
||||
|
||||
auto normbyteToFloat = [](uint8_t value) { return value / 255.f * 2.f - 1.f; };
|
||||
auto halfToFloat = [](uint16_t value) {
|
||||
uint32_t bits = static_cast<uint32_t>(value & 0x8000) << 16;
|
||||
|
@ -1639,6 +1641,39 @@ namespace NifOsg
|
|||
geometry->setTexCoordArray(
|
||||
0, new osg::Vec2Array(uvlist.size(), uvlist.data()), osg::Array::BIND_PER_VERTEX);
|
||||
|
||||
if (!bsTriShape->mSkin.empty() && bsTriShape->mSkin->recType == Nif::RC_BSSkinInstance
|
||||
&& bsTriShape->mVertDesc.mFlags & Nif::BSVertexDesc::VertexAttribute::Skinned)
|
||||
{
|
||||
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::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]));
|
||||
|
||||
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);
|
||||
}
|
||||
rig->setInfluenceMap(map);
|
||||
|
||||
drawable = rig;
|
||||
}
|
||||
|
||||
std::vector<const Nif::NiProperty*> drawableProps;
|
||||
collectDrawableProperties(nifNode, parent, drawableProps);
|
||||
if (!bsTriShape->mShaderProperty.empty())
|
||||
|
@ -1647,8 +1682,8 @@ namespace NifOsg
|
|||
drawableProps.emplace_back(bsTriShape->mAlphaProperty.getPtr());
|
||||
applyDrawableProperties(parentNode, drawableProps, composite, !colors.empty(), animflags);
|
||||
|
||||
geometry->setName(nifNode->mName);
|
||||
parentNode->addChild(geometry);
|
||||
drawable->setName(nifNode->mName);
|
||||
parentNode->addChild(drawable);
|
||||
}
|
||||
|
||||
osg::BlendFunc::BlendFuncMode getBlendMode(int mode)
|
||||
|
|
Loading…
Reference in a new issue