mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-21 08:09:39 +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;
|
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)
|
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);
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
|
@ -1091,25 +1073,12 @@ namespace NifOsg
|
||||||
influence.mWeights.insert(indexWeight);
|
influence.mWeights.insert(indexWeight);
|
||||||
}
|
}
|
||||||
influence.mInvBindMatrix = toMatrix(data->bones[i].trafo);
|
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));
|
map->mMap.insert(std::make_pair(boneName, influence));
|
||||||
}
|
}
|
||||||
rig->setInfluenceMap(map);
|
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);
|
geode->addDrawable(rig);
|
||||||
|
|
||||||
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
||||||
|
|
|
@ -6,14 +6,34 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
|
#include <osg/io_utils>
|
||||||
|
|
||||||
#include "skeleton.hpp"
|
#include "skeleton.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
#include <osg/io_utils>
|
|
||||||
|
|
||||||
namespace SceneUtil
|
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
|
// TODO: make threadsafe for multiple cull threads
|
||||||
class UpdateRigGeometry : public osg::Drawable::CullCallback
|
class UpdateRigGeometry : public osg::Drawable::CullCallback
|
||||||
{
|
{
|
||||||
|
@ -40,6 +60,7 @@ public:
|
||||||
RigGeometry::RigGeometry()
|
RigGeometry::RigGeometry()
|
||||||
{
|
{
|
||||||
setCullCallback(new UpdateRigGeometry);
|
setCullCallback(new UpdateRigGeometry);
|
||||||
|
setUpdateCallback(new UpdateRigBounds);
|
||||||
setSupportsDisplayList(false);
|
setSupportsDisplayList(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +146,8 @@ bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBoneSphereMap[bone] = it->second.mBoundSphere;
|
||||||
|
|
||||||
const BoneInfluence& bi = it->second;
|
const BoneInfluence& bi = it->second;
|
||||||
|
|
||||||
const std::map<unsigned short, float>& weights = it->second.mWeights;
|
const std::map<unsigned short, float>& weights = it->second.mWeights;
|
||||||
|
@ -178,19 +201,7 @@ void RigGeometry::update(osg::NodeVisitor* nv)
|
||||||
|
|
||||||
mSkeleton->updateBoneMatrices(nv);
|
mSkeleton->updateBoneMatrices(nv);
|
||||||
|
|
||||||
osg::NodePath path;
|
osg::Matrixf geomToSkel = getGeomToSkelMatrix(nv);
|
||||||
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);
|
|
||||||
|
|
||||||
// skinning
|
// skinning
|
||||||
osg::Vec3Array* positionSrc = static_cast<osg::Vec3Array*>(mSourceGeometry->getVertexArray());
|
osg::Vec3Array* positionSrc = static_cast<osg::Vec3Array*>(mSourceGeometry->getVertexArray());
|
||||||
|
@ -228,6 +239,47 @@ void RigGeometry::update(osg::NodeVisitor* nv)
|
||||||
normalDst->dirty();
|
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)
|
void RigGeometry::setInfluenceMap(osg::ref_ptr<InfluenceMap> influenceMap)
|
||||||
{
|
{
|
||||||
mInfluenceMap = influenceMap;
|
mInfluenceMap = influenceMap;
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace SceneUtil
|
||||||
struct BoneInfluence
|
struct BoneInfluence
|
||||||
{
|
{
|
||||||
osg::Matrixf mInvBindMatrix;
|
osg::Matrixf mInvBindMatrix;
|
||||||
|
osg::BoundingSpheref mBoundSphere;
|
||||||
// <vertex index, weight>
|
// <vertex index, weight>
|
||||||
std::map<unsigned short, float> mWeights;
|
std::map<unsigned short, float> mWeights;
|
||||||
};
|
};
|
||||||
|
@ -40,6 +41,8 @@ namespace SceneUtil
|
||||||
// Called automatically by our CullCallback
|
// Called automatically by our CullCallback
|
||||||
void update(osg::NodeVisitor* nv);
|
void update(osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
// Called automatically by our UpdateCallback
|
||||||
|
void updateBounds(osg::NodeVisitor* nv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Geometry> mSourceGeometry;
|
osg::ref_ptr<osg::Geometry> mSourceGeometry;
|
||||||
|
@ -57,7 +60,13 @@ namespace SceneUtil
|
||||||
|
|
||||||
Bone2VertexMap mBone2VertexMap;
|
Bone2VertexMap mBone2VertexMap;
|
||||||
|
|
||||||
|
typedef std::map<Bone*, osg::BoundingSpheref> BoneSphereMap;
|
||||||
|
|
||||||
|
BoneSphereMap mBoneSphereMap;
|
||||||
|
|
||||||
bool initFromParentSkeleton(osg::NodeVisitor* nv);
|
bool initFromParentSkeleton(osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
osg::Matrixf getGeomToSkelMatrix(osg::NodeVisitor* nv);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue