mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
Optimize skinning (task #4605)
This commit is contained in:
parent
a7242d9e7a
commit
ff241fb787
@ -124,6 +124,7 @@
|
||||
Feature #4581: Use proper logging system
|
||||
Task #2490: Don't open command prompt window on Release-mode builds automatically
|
||||
Task #4545: Enable is_pod string test
|
||||
Task #4605: Optimize skinning
|
||||
|
||||
0.44.0
|
||||
------
|
||||
|
@ -8,6 +8,31 @@
|
||||
#include "skeleton.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
inline void accumulateMatrix(const osg::Matrixf& invBindMatrix, const osg::Matrixf& matrix, const float weight, osg::Matrixf& result)
|
||||
{
|
||||
osg::Matrixf m = invBindMatrix * matrix;
|
||||
float* ptr = m.ptr();
|
||||
float* ptrresult = result.ptr();
|
||||
ptrresult[0] += ptr[0] * weight;
|
||||
ptrresult[1] += ptr[1] * weight;
|
||||
ptrresult[2] += ptr[2] * weight;
|
||||
|
||||
ptrresult[4] += ptr[4] * weight;
|
||||
ptrresult[5] += ptr[5] * weight;
|
||||
ptrresult[6] += ptr[6] * weight;
|
||||
|
||||
ptrresult[8] += ptr[8] * weight;
|
||||
ptrresult[9] += ptr[9] * weight;
|
||||
ptrresult[10] += ptr[10] * weight;
|
||||
|
||||
ptrresult[12] += ptr[12] * weight;
|
||||
ptrresult[13] += ptr[13] * weight;
|
||||
ptrresult[14] += ptr[14] * weight;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
|
||||
@ -141,28 +166,6 @@ bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv)
|
||||
return true;
|
||||
}
|
||||
|
||||
void accumulateMatrix(const osg::Matrixf& invBindMatrix, const osg::Matrixf& matrix, float weight, osg::Matrixf& result)
|
||||
{
|
||||
osg::Matrixf m = invBindMatrix * matrix;
|
||||
float* ptr = m.ptr();
|
||||
float* ptrresult = result.ptr();
|
||||
ptrresult[0] += ptr[0] * weight;
|
||||
ptrresult[1] += ptr[1] * weight;
|
||||
ptrresult[2] += ptr[2] * weight;
|
||||
|
||||
ptrresult[4] += ptr[4] * weight;
|
||||
ptrresult[5] += ptr[5] * weight;
|
||||
ptrresult[6] += ptr[6] * weight;
|
||||
|
||||
ptrresult[8] += ptr[8] * weight;
|
||||
ptrresult[9] += ptr[9] * weight;
|
||||
ptrresult[10] += ptr[10] * weight;
|
||||
|
||||
ptrresult[12] += ptr[12] * weight;
|
||||
ptrresult[13] += ptr[13] * weight;
|
||||
ptrresult[14] += ptr[14] * weight;
|
||||
}
|
||||
|
||||
void RigGeometry::cull(osg::NodeVisitor* nv)
|
||||
{
|
||||
if (!mSkeleton)
|
||||
@ -173,7 +176,8 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!mSkeleton->getActive() && mLastFrameNumber != 0) || mLastFrameNumber == nv->getTraversalNumber())
|
||||
unsigned int traversalNumber = nv->getTraversalNumber();
|
||||
if (mLastFrameNumber == traversalNumber || (mLastFrameNumber != 0 && !mSkeleton->getActive()))
|
||||
{
|
||||
osg::Geometry& geom = *getGeometry(mLastFrameNumber);
|
||||
nv->pushOntoNodePath(&geom);
|
||||
@ -181,10 +185,10 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
|
||||
nv->popFromNodePath();
|
||||
return;
|
||||
}
|
||||
mLastFrameNumber = nv->getTraversalNumber();
|
||||
mLastFrameNumber = traversalNumber;
|
||||
osg::Geometry& geom = *getGeometry(mLastFrameNumber);
|
||||
|
||||
mSkeleton->updateBoneMatrices(nv->getTraversalNumber());
|
||||
mSkeleton->updateBoneMatrices(traversalNumber);
|
||||
|
||||
// skinning
|
||||
const osg::Vec3Array* positionSrc = static_cast<osg::Vec3Array*>(mSourceGeometry->getVertexArray());
|
||||
@ -195,34 +199,31 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
|
||||
osg::Vec3Array* normalDst = static_cast<osg::Vec3Array*>(geom.getNormalArray());
|
||||
osg::Vec4Array* tangentDst = static_cast<osg::Vec4Array*>(geom.getTexCoordArray(7));
|
||||
|
||||
for (Bone2VertexMap::const_iterator it = mBone2VertexMap.begin(); it != mBone2VertexMap.end(); ++it)
|
||||
for (auto &pair : mBone2VertexMap)
|
||||
{
|
||||
osg::Matrixf resultMat (0, 0, 0, 0,
|
||||
osg::Matrixf resultMat (0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
for (std::vector<BoneWeight>::const_iterator weightIt = it->first.begin(); weightIt != it->first.end(); ++weightIt)
|
||||
for (auto &weight : pair.first)
|
||||
{
|
||||
Bone* bone = weightIt->first.first;
|
||||
const osg::Matrix& invBindMatrix = weightIt->first.second;
|
||||
float weight = weightIt->second;
|
||||
const osg::Matrixf& boneMatrix = bone->mMatrixInSkeletonSpace;
|
||||
accumulateMatrix(invBindMatrix, boneMatrix, weight, resultMat);
|
||||
accumulateMatrix(weight.first.second, weight.first.first->mMatrixInSkeletonSpace, weight.second, resultMat);
|
||||
}
|
||||
|
||||
if (mGeomToSkelMatrix)
|
||||
resultMat *= (*mGeomToSkelMatrix);
|
||||
|
||||
for (std::vector<unsigned short>::const_iterator vertexIt = it->second.begin(); vertexIt != it->second.end(); ++vertexIt)
|
||||
for (auto &vertex : pair.second)
|
||||
{
|
||||
unsigned short vertex = *vertexIt;
|
||||
(*positionDst)[vertex] = resultMat.preMult((*positionSrc)[vertex]);
|
||||
if (normalDst)
|
||||
(*normalDst)[vertex] = osg::Matrix::transform3x3((*normalSrc)[vertex], resultMat);
|
||||
(*normalDst)[vertex] = osg::Matrixf::transform3x3((*normalSrc)[vertex], resultMat);
|
||||
|
||||
if (tangentDst)
|
||||
{
|
||||
osg::Vec4f srcTangent = (*tangentSrc)[vertex];
|
||||
osg::Vec3f transformedTangent = osg::Matrix::transform3x3(osg::Vec3f(srcTangent.x(), srcTangent.y(), srcTangent.z()), resultMat);
|
||||
const osg::Vec4f& srcTangent = (*tangentSrc)[vertex];
|
||||
osg::Vec3f transformedTangent = osg::Matrixf::transform3x3(osg::Vec3f(srcTangent.x(), srcTangent.y(), srcTangent.z()), resultMat);
|
||||
(*tangentDst)[vertex] = osg::Vec4f(transformedTangent, srcTangent.w());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user