Optimize skinning (task #4605)

pull/541/head
Andrei Kortunov 6 years ago
parent a7242d9e7a
commit ff241fb787

@ -124,6 +124,7 @@
Feature #4581: Use proper logging system Feature #4581: Use proper logging system
Task #2490: Don't open command prompt window on Release-mode builds automatically Task #2490: Don't open command prompt window on Release-mode builds automatically
Task #4545: Enable is_pod string test Task #4545: Enable is_pod string test
Task #4605: Optimize skinning
0.44.0 0.44.0
------ ------

@ -8,6 +8,31 @@
#include "skeleton.hpp" #include "skeleton.hpp"
#include "util.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 namespace SceneUtil
{ {
@ -141,28 +166,6 @@ bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv)
return true; 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) void RigGeometry::cull(osg::NodeVisitor* nv)
{ {
if (!mSkeleton) if (!mSkeleton)
@ -173,7 +176,8 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
return; 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); osg::Geometry& geom = *getGeometry(mLastFrameNumber);
nv->pushOntoNodePath(&geom); nv->pushOntoNodePath(&geom);
@ -181,10 +185,10 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
nv->popFromNodePath(); nv->popFromNodePath();
return; return;
} }
mLastFrameNumber = nv->getTraversalNumber(); mLastFrameNumber = traversalNumber;
osg::Geometry& geom = *getGeometry(mLastFrameNumber); osg::Geometry& geom = *getGeometry(mLastFrameNumber);
mSkeleton->updateBoneMatrices(nv->getTraversalNumber()); mSkeleton->updateBoneMatrices(traversalNumber);
// skinning // skinning
const osg::Vec3Array* positionSrc = static_cast<osg::Vec3Array*>(mSourceGeometry->getVertexArray()); 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::Vec3Array* normalDst = static_cast<osg::Vec3Array*>(geom.getNormalArray());
osg::Vec4Array* tangentDst = static_cast<osg::Vec4Array*>(geom.getTexCoordArray(7)); 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, 0, 0, 0, 0, 0,
0, 0, 0, 1); 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; accumulateMatrix(weight.first.second, weight.first.first->mMatrixInSkeletonSpace, weight.second, resultMat);
const osg::Matrix& invBindMatrix = weightIt->first.second;
float weight = weightIt->second;
const osg::Matrixf& boneMatrix = bone->mMatrixInSkeletonSpace;
accumulateMatrix(invBindMatrix, boneMatrix, weight, resultMat);
} }
if (mGeomToSkelMatrix) if (mGeomToSkelMatrix)
resultMat *= (*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]); (*positionDst)[vertex] = resultMat.preMult((*positionSrc)[vertex]);
if (normalDst) if (normalDst)
(*normalDst)[vertex] = osg::Matrix::transform3x3((*normalSrc)[vertex], resultMat); (*normalDst)[vertex] = osg::Matrixf::transform3x3((*normalSrc)[vertex], resultMat);
if (tangentDst) if (tangentDst)
{ {
osg::Vec4f srcTangent = (*tangentSrc)[vertex]; const osg::Vec4f& srcTangent = (*tangentSrc)[vertex];
osg::Vec3f transformedTangent = osg::Matrix::transform3x3(osg::Vec3f(srcTangent.x(), srcTangent.y(), srcTangent.z()), resultMat); osg::Vec3f transformedTangent = osg::Matrixf::transform3x3(osg::Vec3f(srcTangent.x(), srcTangent.y(), srcTangent.z()), resultMat);
(*tangentDst)[vertex] = osg::Vec4f(transformedTangent, srcTangent.w()); (*tangentDst)[vertex] = osg::Vec4f(transformedTangent, srcTangent.w());
} }
} }

Loading…
Cancel
Save