From Cedric Pinson, remove unused file Skinning, cleanup file Timeline.cpp
This commit is contained in:
@@ -1,228 +0,0 @@
|
||||
/* -*-c++-*-
|
||||
* Copyright (C) 2008 Cedric Pinson <mornifle@plopbyte.net>
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGANIMATION_SKINNING_H
|
||||
#define OSGANIMATION_SKINNING_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <osgAnimation/VertexInfluence>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Quat>
|
||||
|
||||
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:
|
||||
typedef osg::Matrix MatrixType;
|
||||
typedef osgAnimation::Bone BoneType;
|
||||
typedef Bone::BoneMap BoneMap;
|
||||
|
||||
class BoneWeight
|
||||
{
|
||||
public:
|
||||
BoneWeight(BoneType* bone, float weight) : _bone(bone), _weight(weight) {}
|
||||
const BoneType* getBone() const { return _bone.get(); }
|
||||
float getWeight() const { return _weight; }
|
||||
void setWeight(float w) { _weight = w; }
|
||||
protected:
|
||||
osg::observer_ptr<BoneType> _bone;
|
||||
float _weight;
|
||||
};
|
||||
|
||||
typedef std::vector<BoneWeight> BoneWeightList;
|
||||
typedef std::vector<int> VertexList;
|
||||
|
||||
class UniqBoneSetVertexSet
|
||||
{
|
||||
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())
|
||||
{
|
||||
osg::notify(osg::WARN) << "TransformVertexFunctor::UniqBoneSetVertexSet no bones found" << std::endl;
|
||||
_result = MatrixType::identity();
|
||||
return;
|
||||
}
|
||||
resetMatrix();
|
||||
|
||||
int size = _bones.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const BoneType* bone = _bones[i].getBone();
|
||||
const MatrixType& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace();
|
||||
const MatrixType& matrix = bone->getMatrixInSkeletonSpace();
|
||||
osg::Matrix::value_type w = _bones[i].getWeight();
|
||||
accummulateMatrix(invBindMatrix, matrix, w);
|
||||
}
|
||||
}
|
||||
const MatrixType& getMatrix() const { return _result;}
|
||||
protected:
|
||||
BoneWeightList _bones;
|
||||
VertexList _vertexes;
|
||||
MatrixType _result;
|
||||
};
|
||||
|
||||
|
||||
void init(const BoneMap& map, const osgAnimation::VertexInfluenceSet::UniqVertexSetToBoneSetList& influence)
|
||||
{
|
||||
_boneSetVertexSet.clear();
|
||||
|
||||
int size = influence.size();
|
||||
_boneSetVertexSet.resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
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();
|
||||
BoneMap::const_iterator it = map.find(bname);
|
||||
if (it == map.end())
|
||||
{
|
||||
osg::notify(osg::WARN) << "TransformVertexFunctor Bone " << bname << " not found, skip the influence group " <<bname << std::endl;
|
||||
continue;
|
||||
}
|
||||
BoneType* bone = it->second.get();
|
||||
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 < (int)boneList.size(); b++)
|
||||
boneList[b].setWeight(boneList[b].getWeight() / sumOfWeight);
|
||||
}
|
||||
_boneSetVertexSet[i].getVertexes() = inf.getVertexes();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class V> void compute(const V* src, V* dst)
|
||||
{
|
||||
int size = _boneSetVertexSet.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
||||
uniq.computeMatrixForVertexSet();
|
||||
const MatrixType& matrix = uniq.getMatrix();
|
||||
|
||||
const VertexList& vertexes = uniq.getVertexes();
|
||||
int vertexSize = vertexes.size();
|
||||
for (int j = 0; j < vertexSize; j++)
|
||||
{
|
||||
int idx = vertexes[j];
|
||||
dst[idx] = src[idx] * matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class V> void compute(const MatrixType& transform, const MatrixType& invTransform, const V* src, V* dst)
|
||||
{
|
||||
// the result of matrix mult should be cached to be used for vertexes transform and normal transform and maybe other computation
|
||||
int size = _boneSetVertexSet.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
||||
uniq.computeMatrixForVertexSet();
|
||||
MatrixType matrix = transform * uniq.getMatrix() * invTransform;
|
||||
|
||||
const VertexList& vertexes = uniq.getVertexes();
|
||||
int vertexSize = vertexes.size();
|
||||
for (int j = 0; j < vertexSize; j++)
|
||||
{
|
||||
int idx = vertexes[j];
|
||||
dst[idx] = src[idx] * matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class V> void computeNormal(const MatrixType& transform, const MatrixType& invTransform, const V* src, V* dst)
|
||||
{
|
||||
int size = _boneSetVertexSet.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i];
|
||||
uniq.computeMatrixForVertexSet();
|
||||
MatrixType matrix = transform * uniq.getMatrix() * invTransform;
|
||||
|
||||
const VertexList& vertexes = uniq.getVertexes();
|
||||
int vertexSize = vertexes.size();
|
||||
for (int j = 0; j < vertexSize; j++)
|
||||
{
|
||||
int idx = vertexes[j];
|
||||
dst[idx] = MatrixType::transform3x3(src[idx],matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<UniqBoneSetVertexSet> _boneSetVertexSet;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -19,7 +19,7 @@
|
||||
using namespace osgAnimation;
|
||||
|
||||
|
||||
osgAnimation::Timeline::Timeline()
|
||||
Timeline::Timeline()
|
||||
{
|
||||
_lastUpdate = 0;
|
||||
_currentFrame = 0;
|
||||
@@ -35,7 +35,7 @@ osgAnimation::Timeline::Timeline()
|
||||
setName("Timeline");
|
||||
}
|
||||
|
||||
osgAnimation::Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op)
|
||||
Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op)
|
||||
: Action(nc, op),
|
||||
_actions(nc._actions)
|
||||
{
|
||||
@@ -58,7 +58,7 @@ void Timeline::setAnimationManager(AnimationManagerBase* manager)
|
||||
_animationManager = manager;
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::traverse(ActionVisitor& visitor)
|
||||
void Timeline::traverse(ActionVisitor& visitor)
|
||||
{
|
||||
int layer = visitor.getCurrentLayer();
|
||||
visitor.pushTimelineOnStack(this);
|
||||
@@ -79,19 +79,19 @@ void osgAnimation::Timeline::traverse(ActionVisitor& visitor)
|
||||
}
|
||||
|
||||
|
||||
void osgAnimation::Timeline::setStats(osg::Stats* stats) { _stats = stats;}
|
||||
osg::Stats* osgAnimation::Timeline::getStats() { return _stats.get();}
|
||||
void osgAnimation::Timeline::collectStats(bool state) { _collectStats = state;}
|
||||
osgAnimation::StatsActionVisitor* osgAnimation::Timeline::getStatsVisitor() { return _statsVisitor.get(); }
|
||||
void Timeline::setStats(osg::Stats* stats) { _stats = stats;}
|
||||
osg::Stats* Timeline::getStats() { return _stats.get();}
|
||||
void Timeline::collectStats(bool state) { _collectStats = state;}
|
||||
StatsActionVisitor* Timeline::getStatsVisitor() { return _statsVisitor.get(); }
|
||||
|
||||
void osgAnimation::Timeline::clearActions()
|
||||
void Timeline::clearActions()
|
||||
{
|
||||
_actions.clear();
|
||||
_addActionOperations.clear();
|
||||
_removeActionOperations.clear();
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::update(double simulationTime)
|
||||
void Timeline::update(double simulationTime)
|
||||
{
|
||||
// first time we call update we generate one frame
|
||||
UpdateActionVisitor updateTimeline;
|
||||
@@ -108,7 +108,7 @@ void osgAnimation::Timeline::update(double simulationTime)
|
||||
if (_collectStats)
|
||||
{
|
||||
if (!_statsVisitor)
|
||||
_statsVisitor = new osgAnimation::StatsActionVisitor();
|
||||
_statsVisitor = new StatsActionVisitor();
|
||||
_statsVisitor->setStats(_stats.get());
|
||||
_statsVisitor->setFrame(_currentFrame);
|
||||
_statsVisitor->reset();
|
||||
@@ -149,7 +149,7 @@ void osgAnimation::Timeline::update(double simulationTime)
|
||||
}
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::removeAction(Action* action)
|
||||
void Timeline::removeAction(Action* action)
|
||||
{
|
||||
if (getEvaluating())
|
||||
_removeActionOperations.push_back(FrameAction(0, action));
|
||||
@@ -157,7 +157,7 @@ void osgAnimation::Timeline::removeAction(Action* action)
|
||||
internalRemoveAction(action);
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::addActionAt(unsigned int frame, Action* action, int priority)
|
||||
void Timeline::addActionAt(unsigned int frame, Action* action, int priority)
|
||||
{
|
||||
// skip if this action has already been added this frame
|
||||
for (CommandList::iterator it = _addActionOperations.begin(); it != _addActionOperations.end(); ++it)
|
||||
@@ -180,18 +180,18 @@ void osgAnimation::Timeline::addActionAt(unsigned int frame, Action* action, int
|
||||
else
|
||||
internalAddAction(priority, FrameAction(frame, action));
|
||||
}
|
||||
void osgAnimation::Timeline::addActionAt(double t, Action* action, int priority)
|
||||
void Timeline::addActionAt(double t, Action* action, int priority)
|
||||
{
|
||||
unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
|
||||
addActionAt(frame, action, priority);
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::addActionNow(Action* action, int priority)
|
||||
void Timeline::addActionNow(Action* action, int priority)
|
||||
{
|
||||
addActionAt(getCurrentFrame()+1, action, priority);
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::processPendingOperation()
|
||||
void Timeline::processPendingOperation()
|
||||
{
|
||||
// process all pending add action operation
|
||||
while( !_addActionOperations.empty())
|
||||
@@ -208,7 +208,7 @@ void osgAnimation::Timeline::processPendingOperation()
|
||||
}
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::internalRemoveAction(Action* action)
|
||||
void Timeline::internalRemoveAction(Action* action)
|
||||
{
|
||||
for (ActionLayers::iterator it = _actions.begin(); it != _actions.end(); it++)
|
||||
{
|
||||
@@ -222,12 +222,12 @@ void osgAnimation::Timeline::internalRemoveAction(Action* action)
|
||||
}
|
||||
}
|
||||
|
||||
void osgAnimation::Timeline::internalAddAction(int priority, const FrameAction& ftl)
|
||||
void Timeline::internalAddAction(int priority, const FrameAction& ftl)
|
||||
{
|
||||
_actions[priority].insert(_actions[priority].begin(), ftl);
|
||||
}
|
||||
|
||||
bool osgAnimation::Timeline::isActive(Action* activeAction)
|
||||
bool Timeline::isActive(Action* activeAction)
|
||||
{
|
||||
// update from high priority to low priority
|
||||
for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim != _actions.end(); ++iterAnim )
|
||||
|
||||
Reference in New Issue
Block a user