mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-19 15:09:41 +00:00
Port skeleton based bounding boxes to the new skinning system
Not sure if going to keep this, there's a noticable performance impact.
This commit is contained in:
parent
8971a200f7
commit
63b69db617
3 changed files with 77 additions and 47 deletions
|
@ -1043,24 +1043,6 @@ namespace NifOsg
|
|||
return morphGeom;
|
||||
}
|
||||
|
||||
class BoundingBoxCallback : public osg::NodeCallback
|
||||
{
|
||||
public:
|
||||
virtual void operator()( osg::Node* node, osg::NodeVisitor* nv )
|
||||
{
|
||||
osg::BoundingBox bb = mDrawable->getBound();
|
||||
|
||||
static_cast<osg::MatrixTransform*>(node)->setMatrix(
|
||||
osg::Matrix::scale(bb.xMax()-bb.xMin(), bb.yMax()-bb.yMin(), bb.zMax()-bb.zMin()) *
|
||||
osg::Matrix::translate(bb.center()) );
|
||||
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
osg::Drawable* mDrawable;
|
||||
};
|
||||
|
||||
|
||||
static void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, const std::map<int, int>& boundTextures, int animflags)
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
|
@ -1091,25 +1073,12 @@ namespace NifOsg
|
|||
influence.mWeights.insert(indexWeight);
|
||||
}
|
||||
influence.mInvBindMatrix = toMatrix(data->bones[i].trafo);
|
||||
influence.mBoundSphere = osg::BoundingSpheref(data->bones[i].boundSphereCenter, data->bones[i].boundSphereRadius);
|
||||
|
||||
map->mMap.insert(std::make_pair(boneName, influence));
|
||||
}
|
||||
rig->setInfluenceMap(map);
|
||||
|
||||
// Compute the bounding box
|
||||
osg::BoundingBox boundingBox;
|
||||
|
||||
osg::Matrix worldTrans = getWorldTransform(triShape);
|
||||
for(size_t i = 0;i < bones.length();i++)
|
||||
{
|
||||
osg::BoundingSphere boneSphere (data->bones[i].boundSphereCenter, data->bones[i].boundSphereRadius);
|
||||
osg::Matrix boneWorldTrans(getWorldTransform(bones[i].getPtr()));
|
||||
osg::Matrix mat = boneWorldTrans * worldTrans.inverse(worldTrans);
|
||||
SceneUtil::transformBoundingSphere(mat, boneSphere);
|
||||
boundingBox.expandBy(boneSphere);
|
||||
}
|
||||
rig->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(boundingBox));
|
||||
|
||||
geode->addDrawable(rig);
|
||||
|
||||
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
||||
|
|
|
@ -6,14 +6,34 @@
|
|||
#include <cstdlib>
|
||||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include "skeleton.hpp"
|
||||
|
||||
#include <osg/io_utils>
|
||||
#include "util.hpp"
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
|
||||
class UpdateRigBounds : public osg::Drawable::UpdateCallback
|
||||
{
|
||||
public:
|
||||
UpdateRigBounds()
|
||||
{
|
||||
}
|
||||
|
||||
UpdateRigBounds(const UpdateRigBounds& copy, const osg::CopyOp& copyop)
|
||||
: osg::Drawable::UpdateCallback(copy, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
void update(osg::NodeVisitor* nv, osg::Drawable* drw)
|
||||
{
|
||||
RigGeometry* rig = static_cast<RigGeometry*>(drw);
|
||||
|
||||
rig->updateBounds(nv);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: make threadsafe for multiple cull threads
|
||||
class UpdateRigGeometry : public osg::Drawable::CullCallback
|
||||
{
|
||||
|
@ -40,6 +60,7 @@ public:
|
|||
RigGeometry::RigGeometry()
|
||||
{
|
||||
setCullCallback(new UpdateRigGeometry);
|
||||
setUpdateCallback(new UpdateRigBounds);
|
||||
setSupportsDisplayList(false);
|
||||
}
|
||||
|
||||
|
@ -125,6 +146,8 @@ bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv)
|
|||
continue;
|
||||
}
|
||||
|
||||
mBoneSphereMap[bone] = it->second.mBoundSphere;
|
||||
|
||||
const BoneInfluence& bi = it->second;
|
||||
|
||||
const std::map<unsigned short, float>& weights = it->second.mWeights;
|
||||
|
@ -178,19 +201,7 @@ void RigGeometry::update(osg::NodeVisitor* nv)
|
|||
|
||||
mSkeleton->updateBoneMatrices(nv);
|
||||
|
||||
osg::NodePath path;
|
||||
bool foundSkel = false;
|
||||
for (osg::NodePath::const_iterator it = nv->getNodePath().begin(); it != nv->getNodePath().end(); ++it)
|
||||
{
|
||||
if (!foundSkel)
|
||||
{
|
||||
if (*it == mSkeleton)
|
||||
foundSkel = true;
|
||||
}
|
||||
else
|
||||
path.push_back(*it);
|
||||
}
|
||||
osg::Matrixf geomToSkel = osg::computeWorldToLocal(path);
|
||||
osg::Matrixf geomToSkel = getGeomToSkelMatrix(nv);
|
||||
|
||||
// skinning
|
||||
osg::Vec3Array* positionSrc = static_cast<osg::Vec3Array*>(mSourceGeometry->getVertexArray());
|
||||
|
@ -228,6 +239,47 @@ void RigGeometry::update(osg::NodeVisitor* nv)
|
|||
normalDst->dirty();
|
||||
}
|
||||
|
||||
void RigGeometry::updateBounds(osg::NodeVisitor *nv)
|
||||
{
|
||||
if (!mSkeleton)
|
||||
{
|
||||
if (!initFromParentSkeleton(nv))
|
||||
return;
|
||||
}
|
||||
|
||||
mSkeleton->updateBoneMatrices(nv);
|
||||
|
||||
osg::Matrixf geomToSkel = getGeomToSkelMatrix(nv);
|
||||
osg::BoundingBox box;
|
||||
for (BoneSphereMap::const_iterator it = mBoneSphereMap.begin(); it != mBoneSphereMap.end(); ++it)
|
||||
{
|
||||
Bone* bone = it->first;
|
||||
osg::BoundingSpheref bs = it->second;
|
||||
transformBoundingSphere(bone->mMatrixInSkeletonSpace * geomToSkel, bs);
|
||||
box.expandBy(bs);
|
||||
}
|
||||
|
||||
setInitialBound(box);
|
||||
}
|
||||
|
||||
osg::Matrixf RigGeometry::getGeomToSkelMatrix(osg::NodeVisitor *nv)
|
||||
{
|
||||
osg::NodePath path;
|
||||
bool foundSkel = false;
|
||||
for (osg::NodePath::const_iterator it = nv->getNodePath().begin(); it != nv->getNodePath().end(); ++it)
|
||||
{
|
||||
if (!foundSkel)
|
||||
{
|
||||
if (*it == mSkeleton)
|
||||
foundSkel = true;
|
||||
}
|
||||
else
|
||||
path.push_back(*it);
|
||||
}
|
||||
return osg::computeWorldToLocal(path);
|
||||
|
||||
}
|
||||
|
||||
void RigGeometry::setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap)
|
||||
{
|
||||
mInfluenceMap = influenceMap;
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace SceneUtil
|
|||
struct BoneInfluence
|
||||
{
|
||||
osg::Matrixf mInvBindMatrix;
|
||||
osg::BoundingSpheref mBoundSphere;
|
||||
// <vertex index, weight>
|
||||
std::map<unsigned short, float> mWeights;
|
||||
};
|
||||
|
@ -40,6 +41,8 @@ namespace SceneUtil
|
|||
// Called automatically by our CullCallback
|
||||
void update(osg::NodeVisitor* nv);
|
||||
|
||||
// Called automatically by our UpdateCallback
|
||||
void updateBounds(osg::NodeVisitor* nv);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Geometry> mSourceGeometry;
|
||||
|
@ -57,7 +60,13 @@ namespace SceneUtil
|
|||
|
||||
Bone2VertexMap mBone2VertexMap;
|
||||
|
||||
typedef std::map<Bone*, osg::BoundingSpheref> BoneSphereMap;
|
||||
|
||||
BoneSphereMap mBoneSphereMap;
|
||||
|
||||
bool initFromParentSkeleton(osg::NodeVisitor* nv);
|
||||
|
||||
osg::Matrixf getGeomToSkelMatrix(osg::NodeVisitor* nv);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue