From 09427d3f5ec05aaa00f31da272f725f1cdba6976 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 16 Sep 2018 14:38:58 +0400 Subject: [PATCH] Take in account transformations of NiTriShape and NiSkinData in skinning (bug #4437) --- CHANGELOG.md | 1 + components/nifosg/nifloader.cpp | 6 +++++- components/sceneutil/riggeometry.cpp | 9 +++++++++ components/sceneutil/riggeometry.hpp | 2 ++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bea04fcb..9e8f04092 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ Bug #4431: "Lock 0" console command is a no-op Bug #4432: Guards behaviour is incorrect if they do not have AI packages Bug #4433: Guard behaviour is incorrect with Alarm = 0 + Bug #4437: Transformations for NiSkinInstance are ignored Bug #4451: Script fails to compile when using "Begin, [ScriptName]" syntax Bug #4452: Default terrain texture bleeds through texture transitions Bug #4453: Quick keys behaviour is invalid for equipment diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 3198e995c..81898e477 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1082,7 +1082,10 @@ namespace NifOsg // Assign bone weights osg::ref_ptr map (new SceneUtil::RigGeometry::InfluenceMap); + // We should take in account transformation of NiTriShape and NiSkinData const Nif::NiSkinData *data = skin->data.getPtr(); + osg::Matrixf shapeTransforms = triShape->trafo.toMatrix() * data->trafo.toMatrix(); + const Nif::NodeList &bones = skin->bones; for(size_t i = 0;i < bones.length();i++) { @@ -1096,11 +1099,12 @@ namespace NifOsg influence.mWeights.insert(indexWeight); } influence.mInvBindMatrix = data->bones[i].trafo.toMatrix(); - influence.mBoundSphere = osg::BoundingSpheref(data->bones[i].boundSphereCenter, data->bones[i].boundSphereRadius); + influence.mBoundSphere = osg::BoundingSpheref(shapeTransforms * data->bones[i].boundSphereCenter, data->bones[i].boundSphereRadius); map->mMap.insert(std::make_pair(boneName, influence)); } rig->setInfluenceMap(map); + rig->setRigTransforms(*&shapeTransforms); parentNode->addChild(rig); } diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp index c409bcd5c..94e4a3b3e 100644 --- a/components/sceneutil/riggeometry.cpp +++ b/components/sceneutil/riggeometry.cpp @@ -49,6 +49,7 @@ RigGeometry::RigGeometry(const RigGeometry ©, const osg::CopyOp ©op) : Drawable(copy, copyop) , mSkeleton(NULL) , mInfluenceMap(copy.mInfluenceMap) + , mRigTransforms(copy.mRigTransforms) , mLastFrameNumber(0) , mBoundsFirstFrame(true) { @@ -214,6 +215,9 @@ void RigGeometry::cull(osg::NodeVisitor* nv) if (mGeomToSkelMatrix) resultMat *= (*mGeomToSkelMatrix); + if (!mRigTransforms.isIdentity()) + resultMat *= mRigTransforms; + for (auto &vertex : pair.second) { (*positionDst)[vertex] = resultMat.preMult((*positionSrc)[vertex]); @@ -309,6 +313,11 @@ void RigGeometry::setInfluenceMap(osg::ref_ptr influenceMap) mInfluenceMap = influenceMap; } +void RigGeometry::setRigTransforms(osg::Matrixf& transform) +{ + mRigTransforms = transform; +} + void RigGeometry::accept(osg::NodeVisitor &nv) { if (!nv.validNodeMask(*this)) diff --git a/components/sceneutil/riggeometry.hpp b/components/sceneutil/riggeometry.hpp index 60b3edc9d..723455234 100644 --- a/components/sceneutil/riggeometry.hpp +++ b/components/sceneutil/riggeometry.hpp @@ -40,6 +40,7 @@ namespace SceneUtil }; void setInfluenceMap(osg::ref_ptr influenceMap); + void setRigTransforms(osg::Matrixf& transform); /// Initialize this geometry from the source geometry. /// @note The source geometry will not be modified. @@ -65,6 +66,7 @@ namespace SceneUtil osg::ref_ptr mGeomToSkelMatrix; osg::ref_ptr mInfluenceMap; + osg::Matrixf mRigTransforms; typedef std::pair BoneBindMatrixPair;