From Cedric Pinson, updates toosgAnimation.

Merged by Robert Osfield, from OpenSceneGraph-osgWidget-dev.
This commit is contained in:
Robert Osfield
2008-11-28 14:34:38 +00:00
parent 37682c6668
commit d3b2d9b074
6 changed files with 112 additions and 27 deletions

View File

@@ -78,7 +78,7 @@ namespace osgAnimation
{
setName(name);
_needToRecomputeBindMatrix = false;
setUpdateCallback(new UpdateBone);
setUpdateCallback(new UpdateBone(name));
}

View File

@@ -17,11 +17,6 @@
namespace osgAnimation {
struct LinearFunction
{
inline static void getValueAt(float t, float& result) { result = t;}
};
struct OutBounceFunction
{
@@ -75,7 +70,15 @@ namespace osgAnimation {
}
};
/// Linear function
struct LinearFunction
{
inline static void getValueAt(float t, float& result) { result = t;}
};
/// Quad function
struct OutQuadFunction
{
inline static void getValueAt(float t, float& result) { result = - (t * (t -2.0));}
@@ -101,6 +104,7 @@ namespace osgAnimation {
};
/// Cubic function
struct OutCubicFunction
{
inline static void getValueAt(float t, float& result) { t = t-1.0; result = t*t*t + 1;}
@@ -123,6 +127,35 @@ namespace osgAnimation {
}
};
/// Quart function
struct InQuartFunction
{
inline static void getValueAt(float t, float& result) { result = t*t*t*t*t;}
};
struct OutQuartFunction
{
inline static void getValueAt(float t, float& result) { t = t - 1; result = - (t*t*t*t -1); }
};
struct InOutQuartFunction
{
inline static void getValueAt(float t, float& result)
{
t = t * 2.0;
if ( t < 1)
result = 0.5*t*t*t*t;
else
{
t -= 2.0;
result = -0.5 * (t*t*t*t -2);
}
}
};
class Motion
{
public:
@@ -185,6 +218,7 @@ namespace osgAnimation {
};
template <typename T>
struct MathMotionTemplate : public Motion
{
@@ -217,15 +251,21 @@ namespace osgAnimation {
// linear
typedef MathMotionTemplate<LinearFunction > LinearMotion;
// quad
typedef MathMotionTemplate<OutQuadFunction > OutQuadMotion;
typedef MathMotionTemplate<InQuadFunction> InQuadMotion;
typedef MathMotionTemplate<InOutQuadFunction> InOutQuadMotion;
// cubic
typedef MathMotionTemplate<OutCubicFunction > OutCubicMotion;
typedef MathMotionTemplate<InCubicFunction> InCubicMotion;
typedef MathMotionTemplate<InOutCubicFunction> InOutCubicMotion;
// quad
typedef MathMotionTemplate<OutQuadFunction > OutQuadMotion;
typedef MathMotionTemplate<InQuadFunction> InQuadMotion;
typedef MathMotionTemplate<InOutQuadFunction> InOutQuadMotion;
// quart
typedef MathMotionTemplate<OutQuartFunction > OutQuartMotion;
typedef MathMotionTemplate<InQuartFunction> InQuartMotion;
typedef MathMotionTemplate<InOutQuartFunction> InOutQuartMotion;
// bounce
typedef MathMotionTemplate<OutBounceFunction > OutBounceMotion;

View File

@@ -30,7 +30,12 @@
namespace osgAnimation
{
/// This class manage format for software skinning
/// it used the technic on this paper http://www.intel.com/cd/ids/developer/asmo-na/eng/172124.htm
/// The idea is to prepare the data to do only v' = M x v with M a combined matrix as below
/// M = Mbone1 * w1 + Mbone2 * w2 + ...
/// a M matrix is uniq for a set of vertex then to fully compute the skinned mesh
/// you have to iterate on each UniqBoneSetVertexSet
class TransformVertexFunctor
{
public:
@@ -44,6 +49,7 @@ namespace osgAnimation
BoneWeight(BoneType* bone, float weight) : _bone(bone), _weight(weight) {}
const BoneType* getBone() const { return &(*_bone); }
float getWeight() const { return _weight; }
void setWeight(float w) { _weight = w; }
protected:
osg::ref_ptr<BoneType> _bone;
float _weight;
@@ -57,6 +63,35 @@ namespace osgAnimation
public:
BoneWeightList& getBones() { return _bones; }
VertexList& getVertexes() { return _vertexes; }
void resetMatrix()
{
_result.set(0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1);
}
void accummulateMatrix(const osg::Matrix& invBindMatrix, const osg::Matrix& matrix, osg::Matrix::value_type weight)
{
osg::Matrix m = invBindMatrix * matrix;
osg::Matrix::value_type* ptr = m.ptr();
osg::Matrix::value_type* 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 computeMatrixForVertexSet()
{
if (_bones.empty())
@@ -65,18 +100,16 @@ namespace osgAnimation
_result = MatrixType::identity();
return;
}
_result = MatrixType(0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0);
resetMatrix();
int size = _bones.size();
for (int i = 0; i < size; i++)
for (int i = 0; i < size; i++)
{
const BoneType* bone = _bones[i].getBone();
const MatrixType& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
const MatrixType& matrix = bone->getMatrixInSkeletonSpace();
double w = _bones[i].getWeight();
_result = _result + ( (invBindMatrix * matrix ) * w);
osg::Matrix::value_type w = _bones[i].getWeight();
accummulateMatrix(invBindMatrix, matrix, w);
}
}
const MatrixType& getMatrix() const { return _result;}
@@ -97,21 +130,31 @@ namespace osgAnimation
{
const osgAnimation::VertexInfluenceSet::UniqVertexSetToBoneSet& inf = influence[i];
int nbBones = inf.getBones().size();
BoneWeightList& boneList = _boneSetVertexSet[i].getBones();
double sumOfWeight = 0;
for (int b = 0; b < nbBones; b++)
{
const std::string& bname = inf.getBones()[b].getBoneName();
float weight = inf.getBones()[b].getWeight();
if (map.find(bname) == map.end())
BoneMap::const_iterator it = map.find(bname);
if (it == map.end())
{
std::cerr << "Warning TransformVertexFunctor Bone " << bname << " not found, skip the influence group " <<bname << std::endl;
osg::notify(osg::WARN) << "TransformVertexFunctor Bone " << bname << " not found, skip the influence group " <<bname << std::endl;
continue;
}
BoneMap::const_iterator it = map.find(bname);
if (it == map.end())
std::cerr << "Warning TransformVertexFunctor does not find bone " << bname << " in the map" << std::endl;
BoneType* bone = it->second.get();
_boneSetVertexSet[i].getBones().push_back(BoneWeight(bone, weight));
boneList.push_back(BoneWeight(bone, weight));
sumOfWeight += weight;
}
// if a bone referenced by a vertexinfluence is missed it can make the sum less than 1.0
// so we check it and renormalize the all weight bone
const double threshold = 1e-4;
if (!_boneSetVertexSet[i].getBones().empty() &&
(sumOfWeight < 1.0 - threshold || sumOfWeight > 1.0 + threshold))
{
for (int b = 0; b < boneList.size(); b++)
boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight);
}
_boneSetVertexSet[i].getVertexes() = inf.getVertexes();
}

View File

@@ -15,14 +15,15 @@
#ifndef OSGANIMATION_TIMELINE_H
#define OSGANIMATION_TIMELINE_H
#include <osgAnimation/Export>
#include <osg/Object>
#include <map>
#include <vector>
#include <cmath>
#include <osg/Notify>
#include <osg/Group>
#include <osgAnimation/Animation>
#include <osgAnimation/AnimationManagerBase>
#include <osgAnimation/Export>
namespace osgAnimation
{
@@ -213,7 +214,7 @@ namespace osgAnimation
// process all pending remove action operation
while( !_removeActionOperations.empty())
{
internalRemoveAction(_removeActionOperations.back().second.get());
internalRemoveAction(_removeActionOperations.back().second);
_removeActionOperations.pop_back();
}
}

View File

@@ -93,7 +93,6 @@ namespace osgAnimation
void buildUniqVertexSetToBoneSetList();
void clear()
{
_bone2Vertexes.clear();
_bone2Vertexes.clear();
_uniqVertexSetToBoneSet.clear();
}