diff --git a/include/osgAnimation/Action b/include/osgAnimation/Action index a39723855..7f81f29b8 100644 --- a/include/osgAnimation/Action +++ b/include/osgAnimation/Action @@ -57,6 +57,17 @@ namespace osgAnimation _nestedCallback = callback; } + void removeCallback(Callback* cb) + { + if (!cb) + return; + + if (_nestedCallback.get() == cb) + _nestedCallback = _nestedCallback->getNestedCallback(); + else + _nestedCallback->removeCallback(cb); + } + protected: osg::ref_ptr _nestedCallback; }; @@ -87,7 +98,9 @@ namespace osgAnimation return 0; return _framesCallback[frame].get(); } - + + void removeCallback(Callback*); + Callback* getFrameCallback(unsigned int frame); Callback* getFrameCallback(double time); unsigned int getFramesPerSecond() const { return _fps; } @@ -127,82 +140,6 @@ namespace osgAnimation - // blend in from 0 to weight in duration - class OSGANIMATION_EXPORT BlendIn : public Action - { - double _weight; - osg::ref_ptr _animation; - - public: - META_Action(osgAnimation, BlendIn); - BlendIn() : _weight(0) {} - BlendIn(const BlendIn& a, const osg::CopyOp& c) : Action(a,c) { _weight = a._weight; _animation = a._animation;} - BlendIn(Animation* animation, double duration, double weight); - double getWeight() const { return _weight;} - Animation* getAnimation() { return _animation.get(); } - void computeWeight(unsigned int frame); - }; - - // blend in from 0 to weight in duration - class OSGANIMATION_EXPORT BlendOut : public Action - { - double _weight; - osg::ref_ptr _animation; - public: - META_Action(osgAnimation, BlendOut); - BlendOut() : _weight(0) {} - BlendOut(const BlendOut& a, const osg::CopyOp& c) : Action(a,c) { _weight = a._weight; _animation = a._animation;} - BlendOut(Animation* animation, double duration); - Animation* getAnimation() { return _animation.get(); } - double getWeight() const { return _weight;} - void computeWeight(unsigned int frame); - }; - - - class OSGANIMATION_EXPORT ActionAnimation : public Action - { - public: - META_Action(osgAnimation, ActionAnimation); - ActionAnimation() {} - ActionAnimation(const ActionAnimation& a, const osg::CopyOp& c) : Action(a,c) { _animation = a._animation;} - ActionAnimation(Animation* animation); - void updateAnimation(unsigned int frame, int priority); - Animation* getAnimation() { return _animation.get(); } - - protected: - osg::ref_ptr _animation; - }; - - - // encapsulate animation with blend in blend out for classic usage - class OSGANIMATION_EXPORT StripAnimation : public Action - { - public: - META_Action(osgAnimation, StripAnimation); - StripAnimation() {} - StripAnimation(const StripAnimation& a, const osg::CopyOp& c); - StripAnimation(Animation* animation, double blendInDuration = 0.0, double blendOutDuration = 0.0, double blendInWeightTarget = 1.0 ); - ActionAnimation* getActionAnimation() { return _animation.get(); } - BlendIn* getBlendIn() { return _blendIn.get(); } - BlendOut* getBlendOut() { return _blendOut.second.get(); } - const ActionAnimation* getActionAnimation() const { return _animation.get(); } - const BlendIn* getBlendIn() const { return _blendIn.get(); } - const BlendOut* getBlendOut() const { return _blendOut.second.get(); } - unsigned int getBlendOutStartFrame() const { return _blendOut.first; } - - unsigned int getLoop() const { return _animation->getLoop(); } - void setLoop(unsigned int loop); - void traverse(ActionVisitor& visitor); - - protected: - typedef std::pair > FrameBlendOut; - osg::ref_ptr _blendIn; - FrameBlendOut _blendOut; - osg::ref_ptr _animation; - }; - - - } #endif diff --git a/include/osgAnimation/ActionAnimation b/include/osgAnimation/ActionAnimation new file mode 100644 index 000000000..ed4d8982e --- /dev/null +++ b/include/osgAnimation/ActionAnimation @@ -0,0 +1,41 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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_ACTION_ANIMATION_H +#define OSGANIMATION_ACTION_ANIMATION_H + +#include +#include + + +namespace osgAnimation { + + + class OSGANIMATION_EXPORT ActionAnimation : public Action + { + public: + META_Action(osgAnimation, ActionAnimation); + ActionAnimation(); + ActionAnimation(const ActionAnimation& a, const osg::CopyOp& c); + ActionAnimation(Animation* animation); + void updateAnimation(unsigned int frame, int priority); + Animation* getAnimation() { return _animation.get(); } + + protected: + osg::ref_ptr _animation; + }; + +} + +#endif diff --git a/include/osgAnimation/ActionBlendIn b/include/osgAnimation/ActionBlendIn new file mode 100644 index 000000000..5789a2c51 --- /dev/null +++ b/include/osgAnimation/ActionBlendIn @@ -0,0 +1,44 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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_ACTION_BLENDIN_H +#define OSGANIMATION_ACTION_BLENDIN_H + +#include +#include + + +namespace osgAnimation { + + + /// blend in from 0 to weight in duration + class OSGANIMATION_EXPORT ActionBlendIn : public Action + { + public: + META_Action(osgAnimation, ActionBlendIn); + ActionBlendIn(); + ActionBlendIn(const ActionBlendIn& a, const osg::CopyOp& c); + ActionBlendIn(Animation* animation, double duration, double weight); + double getWeight() const { return _weight;} + Animation* getAnimation() { return _animation.get(); } + void computeWeight(unsigned int frame); + + protected: + double _weight; + osg::ref_ptr _animation; + }; + +} + +#endif diff --git a/include/osgAnimation/ActionBlendOut b/include/osgAnimation/ActionBlendOut new file mode 100644 index 000000000..cc391739e --- /dev/null +++ b/include/osgAnimation/ActionBlendOut @@ -0,0 +1,45 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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_ACTION_BLENDOUT_H +#define OSGANIMATION_ACTION_BLENDOUT_H + +#include +#include + + +namespace osgAnimation { + + + /// blend out from weight to 0 in duration + class OSGANIMATION_EXPORT ActionBlendOut : public Action + { + public: + META_Action(osgAnimation, ActionBlendOut); + ActionBlendOut(); + ActionBlendOut(const ActionBlendOut& a, const osg::CopyOp& c); + ActionBlendOut(Animation* animation, double duration); + Animation* getAnimation() { return _animation.get(); } + double getWeight() const { return _weight;} + void computeWeight(unsigned int frame); + + protected: + double _weight; + osg::ref_ptr _animation; + + }; + +} + +#endif diff --git a/include/osgAnimation/ActionStripAnimation b/include/osgAnimation/ActionStripAnimation new file mode 100644 index 000000000..7ede4ae08 --- /dev/null +++ b/include/osgAnimation/ActionStripAnimation @@ -0,0 +1,57 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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_ACTION_STRIPANIMATION_H +#define OSGANIMATION_ACTION_STRIPANIMATION_H + +#include +#include +#include +#include +#include +#include + +namespace osgAnimation +{ + + // encapsulate animation with blend in blend out for classic usage + class OSGANIMATION_EXPORT ActionStripAnimation : public Action + { + public: + META_Action(osgAnimation, ActionStripAnimation); + ActionStripAnimation() {} + ActionStripAnimation(const ActionStripAnimation& a, const osg::CopyOp& c); + ActionStripAnimation(Animation* animation, double blendInDuration = 0.0, double blendOutDuration = 0.0, double blendInWeightTarget = 1.0 ); + ActionAnimation* getAnimation(); + ActionBlendIn* getBlendIn(); + ActionBlendOut* getBlendOut(); + const ActionAnimation* getAnimation() const; + const ActionBlendIn* getBlendIn() const; + const ActionBlendOut* getBlendOut() const; + unsigned int getBlendOutStartFrame() const; + + unsigned int getLoop() const; + void setLoop(unsigned int loop); + void traverse(ActionVisitor& visitor); + + protected: + typedef std::pair > FrameBlendOut; + osg::ref_ptr _blendIn; + FrameBlendOut _blendOut; + osg::ref_ptr _animation; + }; + +} + +#endif diff --git a/include/osgAnimation/ActionVisitor b/include/osgAnimation/ActionVisitor index 91a5dd242..cc1f542f5 100644 --- a/include/osgAnimation/ActionVisitor +++ b/include/osgAnimation/ActionVisitor @@ -25,10 +25,10 @@ namespace osgAnimation class Timeline; class Action; - class BlendIn; - class BlendOut; + class ActionBlendIn; + class ActionBlendOut; class ActionAnimation; - class StripAnimation; + class ActionStripAnimation; #define META_ActionVisitor(library,name) \ virtual const char* libraryName() const { return #library; }\ @@ -56,10 +56,10 @@ namespace osgAnimation virtual void apply(Action& action); virtual void apply(Timeline& tm); - virtual void apply(BlendIn& action); - virtual void apply(BlendOut& action); + virtual void apply(ActionBlendIn& action); + virtual void apply(ActionBlendOut& action); virtual void apply(ActionAnimation& action); - virtual void apply(StripAnimation& action); + virtual void apply(ActionStripAnimation& action); protected: std::vector _stackFrameAction; @@ -72,7 +72,7 @@ namespace osgAnimation { protected: unsigned int _frame; - + unsigned int _currentAnimationPriority; public: META_ActionVisitor(osgAnimation, UpdateActionVisitor); UpdateActionVisitor(); @@ -83,10 +83,10 @@ namespace osgAnimation void apply(Timeline& action); void apply(Action& action); - void apply(BlendIn& action); - void apply(BlendOut& action); + void apply(ActionBlendIn& action); + void apply(ActionBlendOut& action); void apply(ActionAnimation& action); - void apply(StripAnimation& action); + void apply(ActionStripAnimation& action); }; diff --git a/include/osgAnimation/RigGeometry b/include/osgAnimation/RigGeometry index 40bdb07a1..6469d5fc7 100644 --- a/include/osgAnimation/RigGeometry +++ b/include/osgAnimation/RigGeometry @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * 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 @@ -16,8 +16,8 @@ #define OSGANIMATION_RIGGEOMETRY_H #include -#include #include +#include #include namespace osgAnimation @@ -33,44 +33,51 @@ namespace osgAnimation META_Object(osgAnimation, RigGeometry); - void setInfluenceMap(osgAnimation::VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } - const osgAnimation::VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} - osgAnimation::VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} + void setInfluenceMap(VertexInfluenceMap* vertexInfluenceMap) { _vertexInfluenceMap = vertexInfluenceMap; } + const VertexInfluenceMap* getInfluenceMap() const { return _vertexInfluenceMap.get();} + VertexInfluenceMap* getInfluenceMap() { return _vertexInfluenceMap.get();} const Skeleton* getSkeleton() const; Skeleton* getSkeleton(); + // will be used by the update callback to init correctly the rig mesh + void setSkeleton(Skeleton*); void setNeedToComputeMatrix(bool state) { _needToComputeMatrix = state;} bool getNeedToComputeMatrix() const { return _needToComputeMatrix;} - void buildVertexSet(); - void buildTransformer(Skeleton* root); + + // this build the internal database about vertex influence and bones + void buildVertexInfluenceSet(); + const VertexInfluenceSet& getVertexInfluenceSet() const; + void computeMatrixFromRootSkeleton(); - virtual void transformSoftwareMethod(); - const osgAnimation::VertexInfluenceSet& getVertexInfluenceSet() const { return _vertexInfluenceSet;} - const std::vector& getPositionSource() const { return _positionSource;} - const std::vector& getNormalSource() const { return _normalSource;} + // set implementation of rig method + void setRigTransformImplementation(RigTransform*); + RigTransform* getRigTransformImplementation(); + + virtual void drawImplementation(osg::RenderInfo& renderInfo) const; + void update(); + + const osg::Matrix& getMatrixFromSkeletonToGeometry() const; + const osg::Matrix& getInvMatrixFromSkeletonToGeometry() const; protected: - std::vector _positionSource; - std::vector _normalSource; + osg::ref_ptr _rigTransformImplementation; - osgAnimation::VertexInfluenceSet _vertexInfluenceSet; - osg::ref_ptr _vertexInfluenceMap; - osgAnimation::TransformVertexFunctor _transformVertexes; + VertexInfluenceSet _vertexInfluenceSet; + osg::ref_ptr _vertexInfluenceMap; osg::Matrix _matrixFromSkeletonToGeometry; osg::Matrix _invMatrixFromSkeletonToGeometry; osg::observer_ptr _root; bool _needToComputeMatrix; - struct FindNearestParentSkeleton : public osg::NodeVisitor { - osg::ref_ptr _root; + osg::ref_ptr _root; FindNearestParentSkeleton() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS) {} void apply(osg::Transform& node) { @@ -98,8 +105,8 @@ namespace osgAnimation if (!finder._root.valid()) return; - geom->buildVertexSet(); - geom->buildTransformer(finder._root.get()); + geom->buildVertexInfluenceSet(); + geom->setSkeleton(finder._root.get()); } if (!geom->getSkeleton()) @@ -107,34 +114,10 @@ namespace osgAnimation if (geom->getNeedToComputeMatrix()) geom->computeMatrixFromRootSkeleton(); - geom->transformSoftwareMethod(); + + geom->update(); } }; - - /** BuildVertexTransformerVisitor is used to setup RigGeometry drawable - * throw a subgraph. - */ - struct BuildVertexTransformerVisitor : public osg::NodeVisitor - { - osg::ref_ptr _root; - BuildVertexTransformerVisitor(Skeleton* root): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { _root = root;} - - META_NodeVisitor("osgAnimation","BuildVertexTransformerVisitor") - - void apply(osg::Geode& node) - { - int num = node.getNumDrawables(); - for (int i = 0; i < num; i++) { - RigGeometry* geom = dynamic_cast(node.getDrawable(i)); - if (geom) - { - geom->buildVertexSet(); - geom->buildTransformer(_root.get()); - } - } - } - }; - }; } diff --git a/include/osgAnimation/RigTransform b/include/osgAnimation/RigTransform new file mode 100644 index 000000000..94c0aeba2 --- /dev/null +++ b/include/osgAnimation/RigTransform @@ -0,0 +1,40 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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_RIGTRANSFORM_H +#define OSGANIMATION_RIGTRANSFORM_H + +#include + +namespace osgAnimation +{ + + class RigGeometry; + + class RigTransform : public osg::Referenced + { + public: + RigTransform() : _needInit(true) {} + virtual ~RigTransform() {} + bool needInit() const { return _needInit; } + virtual bool init(RigGeometry&) = 0; + virtual void update(RigGeometry&) = 0; + + protected: + bool _needInit; + }; + +} + +#endif diff --git a/include/osgAnimation/RigTransformHardware b/include/osgAnimation/RigTransformHardware new file mode 100644 index 000000000..45c526dc2 --- /dev/null +++ b/include/osgAnimation/RigTransformHardware @@ -0,0 +1,82 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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_RIG_TRANSFORM_HARDWARE_H +#define OSGANIMATION_RIG_TRANSFORM_HARDWARE_H 1 + +#include +#include +#include +#include +#include +#include + +namespace osgAnimation +{ + class RigGeometry; + + /// This class manage format for hardware skinning + class OSGANIMATION_EXPORT RigTransformHardware : public RigTransform + { + public: + typedef osg::Matrix MatrixType; + typedef osgAnimation::Bone BoneType; + typedef Bone::BoneMap BoneMap; + typedef std::vector > BoneWeightAttribList; + typedef std::vector > BonePalette; + + typedef std::vector MatrixPalette; + struct IndexWeightEntry + { + int _boneIndex; + float _boneWeight; + IndexWeightEntry() { _boneIndex = 0; _boneWeight = 0;} + IndexWeightEntry(float index, float weight) { _boneIndex = index; _boneWeight = weight;} + int getIndex() const { return _boneIndex; } + float getWeight() const { return _boneWeight; } + }; + typedef std::vector > VertexIndexWeightList; + + osg::Vec4Array* getVertexAttrib(int index); + int getNumVertexAttrib(); + + osg::Uniform* getMatrixPaletteUniform(); + void computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry); + + int getNumBonesPerVertex() const; + int getNumVertexes() const; + + bool createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap); + + + virtual bool init(RigGeometry&); + virtual void update(RigGeometry&); + + void setShader(osg::Shader*); + protected: + + BoneWeightAttribList createVertexAttribList(); + osg::Uniform* createVertexUniform(); + + int _bonesPerVertex; + int _nbVertexes; + VertexIndexWeightList _vertexIndexMatrixWeightList; + BonePalette _bonePalette; + BoneWeightAttribList _boneWeightAttribArrays; + osg::ref_ptr _uniformMatrixPalette; + osg::ref_ptr _shader; + }; +} + +#endif diff --git a/include/osgAnimation/RigTransformSoftware b/include/osgAnimation/RigTransformSoftware new file mode 100644 index 000000000..76b76cca8 --- /dev/null +++ b/include/osgAnimation/RigTransformSoftware @@ -0,0 +1,168 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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_RIG_TRANSFORM_SOFTWARE_H +#define OSGANIMATION_RIG_TRANSFORM_SOFTWARE_H 1 + +#include +#include +#include + +namespace osgAnimation +{ + + class RigGeometry; + + /// This class manage format for hardware skinning + class OSGANIMATION_EXPORT RigTransformSoftware : public RigTransform + { + public: + + virtual bool init(RigGeometry&); + virtual void update(RigGeometry&); + + + class BoneWeight + { + public: + BoneWeight(Bone* bone, float weight) : _bone(bone), _weight(weight) {} + const Bone* getBone() const { return _bone.get(); } + float getWeight() const { return _weight; } + void setWeight(float w) { _weight = w; } + protected: + osg::observer_ptr _bone; + float _weight; + }; + + typedef std::vector BoneWeightList; + typedef std::vector 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) << "RigTransformSoftware::UniqBoneSetVertexSet no bones found" << std::endl; + _result = osg::Matrix::identity(); + return; + } + resetMatrix(); + + int size = _bones.size(); + for (int i = 0; i < size; i++) + { + const Bone* bone = _bones[i].getBone(); + const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); + const osg::Matrix& matrix = bone->getMatrixInSkeletonSpace(); + osg::Matrix::value_type w = _bones[i].getWeight(); + accummulateMatrix(invBindMatrix, matrix, w); + } + } + const osg::Matrix& getMatrix() const { return _result;} + protected: + BoneWeightList _bones; + VertexList _vertexes; + osg::Matrix _result; + }; + + + + template void compute(const osg::Matrix& transform, const osg::Matrix& 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(); + osg::Matrix 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 void computeNormal(const osg::Matrix& transform, const osg::Matrix& invTransform, const V* src, V* dst) + { + int size = _boneSetVertexSet.size(); + for (int i = 0; i < size; i++) + { + UniqBoneSetVertexSet& uniq = _boneSetVertexSet[i]; + uniq.computeMatrixForVertexSet(); + osg::Matrix 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] = osg::Matrix::transform3x3(src[idx],matrix); + } + } + } + + const std::vector& getPositionSource() const { return _positionSource;} + const std::vector& getNormalSource() const { return _normalSource;} + + protected: + + void initVertexSetFromBones(const Bone::BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence); + + std::vector _boneSetVertexSet; + std::vector _positionSource; + std::vector _normalSource; + + }; +} + +#endif diff --git a/include/osgAnimation/StatsVisitor b/include/osgAnimation/StatsVisitor index 5c6d60c54..8b3656265 100644 --- a/include/osgAnimation/StatsVisitor +++ b/include/osgAnimation/StatsVisitor @@ -41,10 +41,10 @@ namespace osgAnimation void setFrame(unsigned int frame) { _frame = frame; } void apply(Timeline& action); void apply(Action& action); - void apply(BlendIn& action); - void apply(BlendOut& action); + void apply(ActionBlendIn& action); + void apply(ActionBlendOut& action); void apply(ActionAnimation& action); - void apply(StripAnimation& action); + void apply(ActionStripAnimation& action); }; diff --git a/include/osgAnimation/Timeline b/include/osgAnimation/Timeline index 9de360497..42c0ae998 100644 --- a/include/osgAnimation/Timeline +++ b/include/osgAnimation/Timeline @@ -62,7 +62,7 @@ namespace osgAnimation virtual void addActionAt(unsigned int frame, Action* action, int priority = 0); virtual void addActionAt(double t, Action* action, int priority = 0); void addActionNow(Action* action, int priority = 0); - + void clearActions(); virtual void update(double simulationTime); diff --git a/include/osgAnimation/VertexInfluence b/include/osgAnimation/VertexInfluence index fa93d070b..a12f755d2 100644 --- a/include/osgAnimation/VertexInfluence +++ b/include/osgAnimation/VertexInfluence @@ -12,8 +12,8 @@ * OpenSceneGraph Public License for more details. */ -#ifndef OSGANIMATION_VERTEX_INFLUENCES_H -#define OSGANIMATION_VERTEX_INFLUENCES_H +#ifndef OSGANIMATION_VERTEX_INFLUENCE_H +#define OSGANIMATION_VERTEX_INFLUENCE_H 1 #include #include @@ -38,8 +38,6 @@ namespace osgAnimation std::string _name; }; - // typedef std::map VertexInfluenceMap; - class VertexInfluenceMap : public std::map , public osg::Object { public: @@ -73,7 +71,7 @@ namespace osgAnimation typedef std::vector BoneWeightList; typedef std::map VertexIndexToBoneWeightMap; - class UniqVertexSetToBoneSet + class UniqVertexSetToBoneSet { public: void setBones(BoneWeightList& bones) { _bones = bones;} @@ -88,14 +86,10 @@ namespace osgAnimation typedef std::vector UniqVertexSetToBoneSetList; const UniqVertexSetToBoneSetList& getUniqVertexSetToBoneSetList() const { return _uniqVertexSetToBoneSet;} - void addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); } + void addVertexInfluence(const VertexInfluence& v); void buildVertex2BoneList(); void buildUniqVertexSetToBoneSetList(); - void clear() - { - _bone2Vertexes.clear(); - _uniqVertexSetToBoneSet.clear(); - } + void clear(); const VertexIndexToBoneWeightMap& getVertexToBoneList() const; protected: diff --git a/src/osgAnimation/Action.cpp b/src/osgAnimation/Action.cpp index 62e89c6ac..fa28f7de8 100644 --- a/src/osgAnimation/Action.cpp +++ b/src/osgAnimation/Action.cpp @@ -14,15 +14,17 @@ #include -osgAnimation::Action::Action() +using namespace osgAnimation; + +Action::Action() { _numberFrame = 25; _fps = 25; _speed = 1.0; _loop = 1; } -osgAnimation::Action::Action(const Action&,const osg::CopyOp&) {} -osgAnimation::Action::Callback* osgAnimation::Action::getFrameCallback(unsigned int frame) +Action::Action(const Action&,const osg::CopyOp&) {} +Action::Callback* Action::getFrameCallback(unsigned int frame) { if (_framesCallback.find(frame) != _framesCallback.end()) { @@ -31,7 +33,30 @@ osgAnimation::Action::Callback* osgAnimation::Action::getFrameCallback(unsigned return 0; } -osgAnimation::Action::Callback* osgAnimation::Action::getFrameCallback(double time) +void Action::removeCallback(Callback* cb) +{ + std::vector keyToRemove; + for (FrameCallback::iterator it = _framesCallback.begin(); it != _framesCallback.end(); it++) + { + if (it->second.get()) + { + if (it->second.get() == cb) + { + it->second = it->second->getNestedCallback(); + if (!it->second.valid()) + keyToRemove.push_back(it->first); + } + else + { + it->second->removeCallback(cb); + } + } + } + for (std::vector::iterator it = keyToRemove.begin(); it != keyToRemove.end(); it++) + _framesCallback.erase(*it); +} + +Action::Callback* Action::getFrameCallback(double time) { unsigned int frame = static_cast(floor(time * _fps)); return getFrameCallback(frame); @@ -56,117 +81,3 @@ bool osgAnimation::Action::evaluateFrame(unsigned int frame, unsigned int& resul } return true; } - - -osgAnimation::BlendIn::BlendIn(Animation* animation, double duration, double weight) -{ - _animation = animation; - _weight = weight; - float d = duration * _fps; - setNumFrames(static_cast(floor(d)) + 1); - setName("BlendIn"); -} - -void osgAnimation::BlendIn::computeWeight(unsigned int frame) -{ - - // frame + 1 because the start is 0 and we want to start the blend in at the first - // frame. - double ratio = ( (frame+1) * 1.0 / (getNumFrames()) ); - double w = _weight * ratio; - - osg::notify(osg::DEBUG_INFO) << getName() << " BlendIn frame " << frame << " weight " << w << std::endl; - _animation->setWeight(w); -} - - -osgAnimation::BlendOut::BlendOut(Animation* animation, double duration) -{ - _animation = animation; - float d = duration * _fps; - setNumFrames(static_cast(floor(d) + 1)); - _weight = 1.0; - setName("BlendOut"); -} - -void osgAnimation::BlendOut::computeWeight(unsigned int frame) -{ - double ratio = ( (frame+1) * 1.0 / (getNumFrames()) ); - double w = _weight * (1.0-ratio); - osg::notify(osg::DEBUG_INFO) << getName() << " BlendOut frame " << frame << " weight " << w << std::endl; - _animation->setWeight(w); -} - - -osgAnimation::ActionAnimation::ActionAnimation(Animation* animation) : _animation(animation) -{ - Action::setDuration(animation->getDuration()); - setName(animation->getName()); -} -void osgAnimation::ActionAnimation::updateAnimation(unsigned int frame, int priority) -{ - _animation->update(frame * 1.0/_fps, priority); -} - - - - - -osgAnimation::StripAnimation::StripAnimation(const StripAnimation& a, const osg::CopyOp& c) : Action(a,c) -{ - _animation = a._animation; - _blendIn = a._blendIn; - _blendOut = a._blendOut; -} - -osgAnimation::StripAnimation::StripAnimation(Animation* animation, double blendInDuration, double blendOutDuration, double blendInWeightTarget) -{ - _blendIn = new BlendIn(animation, blendInDuration, blendInWeightTarget); - _animation = new ActionAnimation(animation); - unsigned int start = static_cast(floor((_animation->getDuration() - blendOutDuration) * _fps)); - _blendOut = FrameBlendOut(start, new BlendOut(animation, blendOutDuration)); - setName(animation->getName() + "_Strip"); - _blendIn->setName(_animation->getName() + "_" + _blendIn->getName()); - _blendOut.second->setName(_animation->getName() + "_" + _blendOut.second->getName()); - setDuration(animation->getDuration()); -} - - -void osgAnimation::StripAnimation::setLoop(unsigned int loop) -{ - _animation->setLoop(loop); - if (!loop) - setDuration(-1); - else - setDuration(loop * _animation->getDuration()); - - // duration changed re evaluate the blendout duration - unsigned int start = static_cast(floor((getDuration() - _blendOut.second->getDuration()) * _fps)); - _blendOut = FrameBlendOut(start, _blendOut.second); -} - -void osgAnimation::StripAnimation::traverse(ActionVisitor& visitor) -{ - if (_blendIn.valid()) - { - unsigned int f = visitor.getStackedFrameAction().back().first; - visitor.pushFrameActionOnStack(FrameAction(f,_blendIn.get())); - _blendIn->accept(visitor); - visitor.popFrameAction(); - } - if (_blendOut.second.valid()) - { - unsigned int f = visitor.getStackedFrameAction().back().first; - visitor.pushFrameActionOnStack(FrameAction(f + _blendOut.first,_blendOut.second.get())); - _blendOut.second.get()->accept(visitor); - visitor.popFrameAction(); - } - - if (_animation.valid()) - { - unsigned int f = visitor.getStackedFrameAction().back().first; - visitor.pushFrameActionOnStack(FrameAction(f,_animation.get())); - _animation->accept(visitor); - visitor.popFrameAction(); - } -} diff --git a/src/osgAnimation/ActionAnimation.cpp b/src/osgAnimation/ActionAnimation.cpp new file mode 100644 index 000000000..a57a073a0 --- /dev/null +++ b/src/osgAnimation/ActionAnimation.cpp @@ -0,0 +1,32 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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. + */ + +#include + +using namespace osgAnimation; + +ActionAnimation::ActionAnimation() {} + +ActionAnimation::ActionAnimation(const ActionAnimation& a, const osg::CopyOp& c) : Action(a,c) { _animation = a._animation;} + +ActionAnimation::ActionAnimation(Animation* animation) : _animation(animation) +{ + Action::setDuration(animation->getDuration()); + setName(animation->getName()); +} + +void ActionAnimation::updateAnimation(unsigned int frame, int priority) +{ + _animation->update(frame * 1.0/_fps, priority); +} diff --git a/src/osgAnimation/ActionBlendIn.cpp b/src/osgAnimation/ActionBlendIn.cpp new file mode 100644 index 000000000..74a532789 --- /dev/null +++ b/src/osgAnimation/ActionBlendIn.cpp @@ -0,0 +1,45 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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. +*/ + +#include + +using namespace osgAnimation; + +ActionBlendIn::ActionBlendIn() : _weight(0) {} +ActionBlendIn::ActionBlendIn(const ActionBlendIn& a, const osg::CopyOp& c) : Action(a,c) +{ + _weight = a._weight; + _animation = a._animation; +} + +ActionBlendIn::ActionBlendIn(Animation* animation, double duration, double weight) +{ + _animation = animation; + _weight = weight; + float d = duration * _fps; + setNumFrames(static_cast(floor(d)) + 1); + setName("BlendIn"); +} + +void ActionBlendIn::computeWeight(unsigned int frame) +{ + + // frame + 1 because the start is 0 and we want to start the blend in at the first + // frame. + double ratio = ( (frame+1) * 1.0 / (getNumFrames()) ); + double w = _weight * ratio; + + osg::notify(osg::DEBUG_INFO) << getName() << " BlendIn frame " << frame << " weight " << w << std::endl; + _animation->setWeight(w); +} diff --git a/src/osgAnimation/ActionBlendOut.cpp b/src/osgAnimation/ActionBlendOut.cpp new file mode 100644 index 000000000..beabcf632 --- /dev/null +++ b/src/osgAnimation/ActionBlendOut.cpp @@ -0,0 +1,41 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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. +*/ + +#include + +using namespace osgAnimation; + +ActionBlendOut::ActionBlendOut() : _weight(0) {} +ActionBlendOut::ActionBlendOut(const ActionBlendOut& a, const osg::CopyOp& c) : Action(a,c) +{ + _weight = a._weight; + _animation = a._animation; +} + +ActionBlendOut::ActionBlendOut(Animation* animation, double duration) +{ + _animation = animation; + float d = duration * _fps; + setNumFrames(static_cast(floor(d) + 1)); + _weight = 1.0; + setName("BlendOut"); +} + +void ActionBlendOut::computeWeight(unsigned int frame) +{ + double ratio = ( (frame+1) * 1.0 / (getNumFrames()) ); + double w = _weight * (1.0-ratio); + osg::notify(osg::DEBUG_INFO) << getName() << " BlendOut frame " << frame << " weight " << w << std::endl; + _animation->setWeight(w); +} diff --git a/src/osgAnimation/ActionStripAnimation.cpp b/src/osgAnimation/ActionStripAnimation.cpp new file mode 100644 index 000000000..fa2c7c448 --- /dev/null +++ b/src/osgAnimation/ActionStripAnimation.cpp @@ -0,0 +1,88 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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. + */ + + +#include + +using namespace osgAnimation; + +ActionAnimation* ActionStripAnimation::getAnimation() { return _animation.get(); } +ActionBlendIn* ActionStripAnimation::getBlendIn() { return _blendIn.get(); } +ActionBlendOut* ActionStripAnimation::getBlendOut() { return _blendOut.second.get(); } +const ActionAnimation* ActionStripAnimation::getAnimation() const { return _animation.get(); } +const ActionBlendIn* ActionStripAnimation::getBlendIn() const { return _blendIn.get(); } +const ActionBlendOut* ActionStripAnimation::getBlendOut() const { return _blendOut.second.get(); } +unsigned int ActionStripAnimation::getBlendOutStartFrame() const { return _blendOut.first; } + +unsigned int ActionStripAnimation::getLoop() const { return _animation->getLoop(); } + + +ActionStripAnimation::ActionStripAnimation(const ActionStripAnimation& a, const osg::CopyOp& c) : Action(a,c) +{ + _animation = a._animation; + _blendIn = a._blendIn; + _blendOut = a._blendOut; +} + +ActionStripAnimation::ActionStripAnimation(Animation* animation, double blendInDuration, double blendOutDuration, double blendInWeightTarget) +{ + _blendIn = new ActionBlendIn(animation, blendInDuration, blendInWeightTarget); + _animation = new ActionAnimation(animation); + unsigned int start = static_cast(floor((_animation->getDuration() - blendOutDuration) * _fps)); + _blendOut = FrameBlendOut(start, new ActionBlendOut(animation, blendOutDuration)); + setName(animation->getName() + "_Strip"); + _blendIn->setName(_animation->getName() + "_" + _blendIn->getName()); + _blendOut.second->setName(_animation->getName() + "_" + _blendOut.second->getName()); + setDuration(animation->getDuration()); +} + + +void ActionStripAnimation::setLoop(unsigned int loop) +{ + _animation->setLoop(loop); + if (!loop) + setDuration(-1); + else + setDuration(loop * _animation->getDuration()); + + // duration changed re evaluate the blendout duration + unsigned int start = static_cast(floor((getDuration() - _blendOut.second->getDuration()) * _fps)); + _blendOut = FrameBlendOut(start, _blendOut.second); +} + +void ActionStripAnimation::traverse(ActionVisitor& visitor) +{ + if (_blendIn.valid()) + { + unsigned int f = visitor.getStackedFrameAction().back().first; + visitor.pushFrameActionOnStack(FrameAction(f,_blendIn.get())); + _blendIn->accept(visitor); + visitor.popFrameAction(); + } + if (_blendOut.second.valid()) + { + unsigned int f = visitor.getStackedFrameAction().back().first; + visitor.pushFrameActionOnStack(FrameAction(f + _blendOut.first,_blendOut.second.get())); + _blendOut.second.get()->accept(visitor); + visitor.popFrameAction(); + } + + if (_animation.valid()) + { + unsigned int f = visitor.getStackedFrameAction().back().first; + visitor.pushFrameActionOnStack(FrameAction(f,_animation.get())); + _animation->accept(visitor); + visitor.popFrameAction(); + } +} diff --git a/src/osgAnimation/ActionVisitor.cpp b/src/osgAnimation/ActionVisitor.cpp index dd6395785..79ab54477 100644 --- a/src/osgAnimation/ActionVisitor.cpp +++ b/src/osgAnimation/ActionVisitor.cpp @@ -13,40 +13,52 @@ */ #include +#include +#include +#include +#include #include #include -osgAnimation::ActionVisitor::ActionVisitor() +using namespace osgAnimation; + +ActionVisitor::ActionVisitor() { _currentLayer = 0; } -void osgAnimation::ActionVisitor::pushFrameActionOnStack(const FrameAction& fa) { _stackFrameAction.push_back(fa); } -void osgAnimation::ActionVisitor::popFrameAction() { _stackFrameAction.pop_back(); } -void osgAnimation::ActionVisitor::pushTimelineOnStack(Timeline* tm) { _stackTimeline.push_back(tm); } -void osgAnimation::ActionVisitor::popTimeline() { _stackTimeline.pop_back(); } -void osgAnimation::ActionVisitor::apply(Action& action) { traverse(action); } -void osgAnimation::ActionVisitor::apply(Timeline& tm) { tm.traverse(*this); } -void osgAnimation::ActionVisitor::apply(BlendIn& action) { apply(static_cast(action));} -void osgAnimation::ActionVisitor::apply(BlendOut& action) { apply(static_cast(action)); } -void osgAnimation::ActionVisitor::apply(ActionAnimation& action) { apply(static_cast(action)); } -void osgAnimation::ActionVisitor::apply(StripAnimation& action) { apply(static_cast(action)); } -void osgAnimation::ActionVisitor::traverse(Action& action) +void ActionVisitor::pushFrameActionOnStack(const FrameAction& fa) { _stackFrameAction.push_back(fa); } +void ActionVisitor::popFrameAction() { _stackFrameAction.pop_back(); } +void ActionVisitor::pushTimelineOnStack(Timeline* tm) { _stackTimeline.push_back(tm); } +void ActionVisitor::popTimeline() { _stackTimeline.pop_back(); } +void ActionVisitor::apply(Action& action) { traverse(action); } +void ActionVisitor::apply(Timeline& tm) { tm.traverse(*this); } +void ActionVisitor::apply(ActionBlendIn& action) { apply(static_cast(action));} +void ActionVisitor::apply(ActionBlendOut& action) { apply(static_cast(action)); } +void ActionVisitor::apply(ActionAnimation& action) { apply(static_cast(action)); } +void ActionVisitor::apply(ActionStripAnimation& action) { apply(static_cast(action)); } +void ActionVisitor::traverse(Action& action) { action.traverse(*this); } -osgAnimation::Timeline* osgAnimation::ActionVisitor::getCurrentTimeline() +Timeline* ActionVisitor::getCurrentTimeline() { if (_stackTimeline.empty()) return 0; return _stackTimeline.back(); } -osgAnimation::UpdateActionVisitor::UpdateActionVisitor() { _frame = 0; } - - -void osgAnimation::UpdateActionVisitor::apply(Timeline& tm) +UpdateActionVisitor::UpdateActionVisitor() { + _frame = 0; + _currentAnimationPriority = 0; +} + + +void UpdateActionVisitor::apply(Timeline& tm) +{ + _currentAnimationPriority = 0; + tm.setEvaluating(true); tm.traverse(*this); @@ -56,7 +68,7 @@ void osgAnimation::UpdateActionVisitor::apply(Timeline& tm) tm.setLastFrameEvaluated(_frame); } -bool osgAnimation::UpdateActionVisitor::isActive(Action& action) const +bool UpdateActionVisitor::isActive(Action& action) const { FrameAction fa = _stackFrameAction.back(); if (_frame < fa.first) @@ -70,12 +82,12 @@ bool osgAnimation::UpdateActionVisitor::isActive(Action& action) const return action.evaluateFrame(f, frameInAction, loopDone); } -unsigned int osgAnimation::UpdateActionVisitor::getLocalFrame() const +unsigned int UpdateActionVisitor::getLocalFrame() const { return _frame - _stackFrameAction.back().first; } -void osgAnimation::UpdateActionVisitor::apply(Action& action) +void UpdateActionVisitor::apply(Action& action) { if (isActive(action)) { @@ -102,7 +114,7 @@ void osgAnimation::UpdateActionVisitor::apply(Action& action) } } -void osgAnimation::UpdateActionVisitor::apply(BlendIn& action) +void UpdateActionVisitor::apply(ActionBlendIn& action) { if (isActive(action)) { @@ -112,7 +124,7 @@ void osgAnimation::UpdateActionVisitor::apply(BlendIn& action) } } -void osgAnimation::UpdateActionVisitor::apply(BlendOut& action) +void UpdateActionVisitor::apply(ActionBlendOut& action) { if (isActive(action)) { @@ -122,17 +134,18 @@ void osgAnimation::UpdateActionVisitor::apply(BlendOut& action) } } -void osgAnimation::UpdateActionVisitor::apply(ActionAnimation& action) +void UpdateActionVisitor::apply(ActionAnimation& action) { - if (isActive(action)) + if (isActive(action)) { unsigned int frame = getLocalFrame(); apply(static_cast(action)); - action.updateAnimation(frame, getCurrentLayer()); +// action.updateAnimation(frame, getCurrentLayer()); + action.updateAnimation(frame, -_currentAnimationPriority++); } } -void osgAnimation::UpdateActionVisitor::apply(StripAnimation& action) +void UpdateActionVisitor::apply(ActionStripAnimation& action) { if (isActive(action)) { @@ -143,18 +156,18 @@ void osgAnimation::UpdateActionVisitor::apply(StripAnimation& action) -osgAnimation::ClearActionVisitor::ClearActionVisitor(ClearType type) : _clearType(type) +ClearActionVisitor::ClearActionVisitor(ClearType type) : _clearType(type) { } -void osgAnimation::ClearActionVisitor::apply(Timeline& tm) +void ClearActionVisitor::apply(Timeline& tm) { _remove.clear(); tm.traverse(*this); for (int i = 0; i < (int)_remove.size(); i++) tm.removeAction(_remove[i].get()); } -void osgAnimation::ClearActionVisitor::apply(Action& action) +void ClearActionVisitor::apply(Action& action) { FrameAction fa = _stackFrameAction.back(); switch( _clearType) { diff --git a/src/osgAnimation/Bone.cpp b/src/osgAnimation/Bone.cpp index cbd664dbd..1617d4c9c 100644 --- a/src/osgAnimation/Bone.cpp +++ b/src/osgAnimation/Bone.cpp @@ -12,7 +12,6 @@ * OpenSceneGraph Public License for more details. */ -#include #include #include #include diff --git a/src/osgAnimation/CMakeLists.txt b/src/osgAnimation/CMakeLists.txt index 9aff2a5e5..7fe99dcfc 100644 --- a/src/osgAnimation/CMakeLists.txt +++ b/src/osgAnimation/CMakeLists.txt @@ -11,7 +11,11 @@ SET(LIB_NAME osgAnimation) SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(LIB_PUBLIC_HEADERS ${HEADER_PATH}/Action + ${HEADER_PATH}/ActionAnimation + ${HEADER_PATH}/ActionBlendIn + ${HEADER_PATH}/ActionBlendOut ${HEADER_PATH}/ActionCallback + ${HEADER_PATH}/ActionStripAnimation ${HEADER_PATH}/ActionVisitor ${HEADER_PATH}/Animation ${HEADER_PATH}/AnimationManagerBase @@ -31,9 +35,11 @@ SET(LIB_PUBLIC_HEADERS ${HEADER_PATH}/LinkVisitor ${HEADER_PATH}/MorphGeometry ${HEADER_PATH}/RigGeometry + ${HEADER_PATH}/RigTransform + ${HEADER_PATH}/RigTransformHardware + ${HEADER_PATH}/RigTransformSoftware ${HEADER_PATH}/Sampler ${HEADER_PATH}/Skeleton - ${HEADER_PATH}/Skinning ${HEADER_PATH}/StatsVisitor ${HEADER_PATH}/StatsHandler ${HEADER_PATH}/Target @@ -49,7 +55,11 @@ ADD_LIBRARY(${LIB_NAME} ${OPENSCENEGRAPH_USER_DEFINED_DYNAMIC_OR_STATIC} ${LIB_PUBLIC_HEADERS} Action.cpp + ActionAnimation.cpp + ActionBlendIn.cpp + ActionBlendOut.cpp ActionCallback.cpp + ActionStripAnimation.cpp ActionVisitor.cpp Animation.cpp AnimationManagerBase.cpp @@ -61,6 +71,8 @@ ADD_LIBRARY(${LIB_NAME} LinkVisitor.cpp MorphGeometry.cpp RigGeometry.cpp + RigTransformHardware.cpp + RigTransformSoftware.cpp Skeleton.cpp StatsVisitor.cpp StatsHandler.cpp diff --git a/src/osgAnimation/RigGeometry.cpp b/src/osgAnimation/RigGeometry.cpp index 293ab5e52..bc23e51b0 100644 --- a/src/osgAnimation/RigGeometry.cpp +++ b/src/osgAnimation/RigGeometry.cpp @@ -1,70 +1,75 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: + * 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. * - * Cedric Pinson - * + * 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. */ + #include +#include +#include +#include using namespace osgAnimation; RigGeometry::RigGeometry() { - setUseDisplayList(false); + _supportsDisplayList = false; + setUseVertexBufferObjects(true); setUpdateCallback(new UpdateVertex); setDataVariance(osg::Object::DYNAMIC); _needToComputeMatrix = true; _matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity(); + + // disable the computation of boundingbox for the rig mesh + setComputeBoundingBoxCallback(new ComputeBoundingBoxCallback); } RigGeometry::RigGeometry(const osg::Geometry& b) : osg::Geometry(b, osg::CopyOp::SHALLOW_COPY) { - setUseDisplayList(false); + _supportsDisplayList = false; + setUseVertexBufferObjects(true); setUpdateCallback(new UpdateVertex); setDataVariance(osg::Object::DYNAMIC); _needToComputeMatrix = true; _matrixFromSkeletonToGeometry = _invMatrixFromSkeletonToGeometry = osg::Matrix::identity(); + + // disable the computation of boundingbox for the rig mesh + setComputeBoundingBoxCallback(new ComputeBoundingBoxCallback); } -RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : +RigGeometry::RigGeometry(const RigGeometry& b, const osg::CopyOp& copyop) : osg::Geometry(b,copyop), - _positionSource(b._positionSource), - _normalSource(b._normalSource), _vertexInfluenceSet(b._vertexInfluenceSet), _vertexInfluenceMap(b._vertexInfluenceMap), - _transformVertexes(b._transformVertexes), - _needToComputeMatrix(b._needToComputeMatrix) + _needToComputeMatrix(b._needToComputeMatrix) { + // we dont copy the RigImplementation yet. because the RigImplementation need to be initialized in a valid graph, with a skeleton ... + // dont know yet what to do with a clone of a RigGeometry } -void RigGeometry::buildTransformer(Skeleton* root) + +const osg::Matrix& RigGeometry::getMatrixFromSkeletonToGeometry() const { return _matrixFromSkeletonToGeometry; } +const osg::Matrix& RigGeometry::getInvMatrixFromSkeletonToGeometry() const { return _invMatrixFromSkeletonToGeometry;} + + +void RigGeometry::drawImplementation(osg::RenderInfo& renderInfo) const { - Bone::BoneMap bm = root->getBoneMap(); - _transformVertexes.init(bm, _vertexInfluenceSet.getUniqVertexSetToBoneSetList()); - _root = root; + osg::Geometry::drawImplementation(renderInfo); } -void RigGeometry::buildVertexSet() +void RigGeometry::buildVertexInfluenceSet() { - if (!_vertexInfluenceMap.valid()) + if (!_vertexInfluenceMap.valid()) { - osg::notify(osg::WARN) << "buildVertexSet can't be called without VertexInfluence already set to the RigGeometry ( " << getName() << " ) " << std::endl; + osg::notify(osg::WARN) << "buildVertexInfluenceSet can't be called without VertexInfluence already set to the RigGeometry ( " << getName() << " ) " << std::endl; return; } _vertexInfluenceSet.clear(); @@ -75,12 +80,12 @@ void RigGeometry::buildVertexSet() _vertexInfluenceSet.buildVertex2BoneList(); _vertexInfluenceSet.buildUniqVertexSetToBoneSetList(); - std::cout << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl; + osg::notify(osg::NOTICE) << "uniq groups " << _vertexInfluenceSet.getUniqVertexSetToBoneSetList().size() << " for " << getName() << std::endl; } -void RigGeometry::computeMatrixFromRootSkeleton() +void RigGeometry::computeMatrixFromRootSkeleton() { - if (!_root.valid()) + if (!_root.valid()) { osg::notify(osg::WARN) << "Warning " << className() <<"::computeMatrixFromRootSkeleton if you have this message it means you miss to call buildTransformer(Skeleton* root), or your RigGeometry (" << getName() <<") is not attached to a Skeleton subgraph" << std::endl; return; @@ -91,39 +96,23 @@ void RigGeometry::computeMatrixFromRootSkeleton() _needToComputeMatrix = false; } -void RigGeometry::transformSoftwareMethod() +void RigGeometry::update() { - setUseDisplayList(false); - setUseVertexBufferObjects(true); - - // std::cout << getName() << " _matrixFromSkeletonToGeometry" << _matrixFromSkeletonToGeometry << std::endl; - osg::Vec3Array* pos = dynamic_cast(getVertexArray()); - if (pos && _positionSource.size() != pos->size()) + if (!getRigTransformImplementation()) { - _positionSource = std::vector(pos->begin(),pos->end()); - getVertexArray()->setDataVariance(osg::Object::DYNAMIC); - } - osg::Vec3Array* normal = dynamic_cast(getNormalArray()); - if (normal && _normalSource.size() != normal->size()) - { - _normalSource = std::vector(normal->begin(),normal->end()); - getNormalArray()->setDataVariance(osg::Object::DYNAMIC); + _rigTransformImplementation = new RigTransformSoftware; } - if (!_positionSource.empty()) - { - _transformVertexes.compute(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_positionSource.front(), &pos->front()); - pos->dirty(); - } - if (!_normalSource.empty()) - { - _transformVertexes.computeNormal(_matrixFromSkeletonToGeometry, _invMatrixFromSkeletonToGeometry, &_normalSource.front(), &normal->front()); - normal->dirty(); - } - if (getUseDisplayList()) - dirtyDisplayList(); - dirtyBound(); + if (getRigTransformImplementation()->needInit()) + if (!getRigTransformImplementation()->init(*this)) + return; + getRigTransformImplementation()->update(*this); } -const osgAnimation::Skeleton* RigGeometry::getSkeleton() const { return _root.get(); } -osgAnimation::Skeleton* RigGeometry::getSkeleton() { return _root.get(); } +const VertexInfluenceSet& RigGeometry::getVertexInfluenceSet() const { return _vertexInfluenceSet;} + +const Skeleton* RigGeometry::getSkeleton() const { return _root.get(); } +Skeleton* RigGeometry::getSkeleton() { return _root.get(); } +void RigGeometry::setSkeleton(Skeleton* root) { _root = root;} +RigTransform* RigGeometry::getRigTransformImplementation() { return _rigTransformImplementation.get(); } +void RigGeometry::setRigTransformImplementation(RigTransform* rig) { _rigTransformImplementation = rig; } diff --git a/src/osgAnimation/RigTransformHardware.cpp b/src/osgAnimation/RigTransformHardware.cpp new file mode 100644 index 000000000..3b1a23b43 --- /dev/null +++ b/src/osgAnimation/RigTransformHardware.cpp @@ -0,0 +1,250 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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. + */ + +#include +#include +#include + +using namespace osgAnimation; + +osg::Vec4Array* RigTransformHardware::getVertexAttrib(int index) +{ + if (index >= (int)_boneWeightAttribArrays.size()) + return 0; + return _boneWeightAttribArrays[index].get(); +} + +int RigTransformHardware::getNumVertexAttrib() +{ + return _boneWeightAttribArrays.size(); +} + +osg::Uniform* RigTransformHardware::getMatrixPaletteUniform() +{ + return _uniformMatrixPalette.get(); +} + + +void RigTransformHardware::computeMatrixPaletteUniform(const osg::Matrix& transformFromSkeletonToGeometry, const osg::Matrix& invTransformFromSkeletonToGeometry) +{ + for (int i = 0; i < (int)_bonePalette.size(); i++) + { + osg::ref_ptr bone = _bonePalette[i].get(); + const osg::Matrix& invBindMatrix = bone->getInvBindMatrixInSkeletonSpace(); + const osg::Matrix& boneMatrix = bone->getMatrixInSkeletonSpace(); + osg::Matrix resultBoneMatrix = invBindMatrix * boneMatrix; + osg::Matrix result = transformFromSkeletonToGeometry * resultBoneMatrix * invTransformFromSkeletonToGeometry; + if (!_uniformMatrixPalette->setElement(i, result)) + osg::notify(osg::WARN) << "RigTransformHardware::computeUniformMatrixPalette can't set uniform at " << i << " elements" << std::endl; + } +} + + +int RigTransformHardware::getNumBonesPerVertex() const { return _bonesPerVertex;} +int RigTransformHardware::getNumVertexes() const { return _nbVertexes;} + +bool RigTransformHardware::createPalette(int nbVertexes, BoneMap boneMap, const VertexInfluenceSet::VertexIndexToBoneWeightMap& vertexIndexToBoneWeightMap) +{ + typedef std::map BoneNameCountMap; + typedef std::map BoneNamePaletteIndex; + BoneNamePaletteIndex bname2palette; + BonePalette palette; + BoneNameCountMap boneNameCountMap; + + // init vertex attribute data + VertexIndexWeightList vertexIndexWeight; + vertexIndexWeight.resize(nbVertexes); + + int maxBonePerVertex = 0; + for (VertexInfluenceSet::VertexIndexToBoneWeightMap::const_iterator it = vertexIndexToBoneWeightMap.begin(); it != vertexIndexToBoneWeightMap.end(); it++) + { + int vertexIndex = it->first; + const VertexInfluenceSet::BoneWeightList& boneWeightList = it->second; + int bonesForThisVertex = 0; + for (VertexInfluenceSet::BoneWeightList::const_iterator it = boneWeightList.begin(); it != boneWeightList.end(); it++) + { + const VertexInfluenceSet::BoneWeight& bw = *it; + if (boneNameCountMap.find(bw.getBoneName()) != boneNameCountMap.end()) + { + boneNameCountMap[bw.getBoneName()]++; + bonesForThisVertex++; // count max number of bones per vertexes + vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(bname2palette[bw.getBoneName()],bw.getWeight())); + } + else if (fabs(bw.getWeight()) > 1e-2) // dont use bone with weight too small + { + if (boneMap.find(bw.getBoneName()) == boneMap.end()) + { + osg::notify(osg::WARN) << "RigTransformHardware::createPalette can't find bone " << bw.getBoneName() << " skip this influence" << std::endl; + continue; + } + boneNameCountMap[bw.getBoneName()] = 1; // for stats + bonesForThisVertex++; + palette.push_back(boneMap[bw.getBoneName()]); + bname2palette[bw.getBoneName()] = palette.size()-1; + vertexIndexWeight[vertexIndex].push_back(IndexWeightEntry(bname2palette[bw.getBoneName()],bw.getWeight())); + } + else + { + osg::notify(osg::WARN) << "RigTransformHardware::createPalette Bone " << bw.getBoneName() << " has a weight " << bw.getWeight() << " for vertex " << vertexIndex << " this bone will not be in the palette" << std::endl; + } + } + maxBonePerVertex = osg::maximum(maxBonePerVertex, bonesForThisVertex); + } + osg::notify(osg::INFO) << "RigTransformHardware::createPalette maximum number of bone per vertex is " << maxBonePerVertex << std::endl; + osg::notify(osg::INFO) << "RigTransformHardware::createPalette matrix palette has " << boneNameCountMap.size() << " entries" << std::endl; + + for (BoneNameCountMap::iterator it = boneNameCountMap.begin(); it != boneNameCountMap.end(); it++) + { + osg::notify(osg::INFO) << "RigTransformHardware::createPalette Bone " << it->first << " is used " << it->second << " times" << std::endl; + } + + osg::notify(osg::INFO) << "RigTransformHardware::createPalette will use " << boneNameCountMap.size() * 4 << " uniforms" << std::endl; + + + for (int i = 0 ; i < (int)vertexIndexWeight.size(); i++) + vertexIndexWeight[i].resize(maxBonePerVertex); + + _nbVertexes = nbVertexes; + _bonesPerVertex = maxBonePerVertex; + _bonePalette = palette; + _vertexIndexMatrixWeightList = vertexIndexWeight; + _uniformMatrixPalette = createVertexUniform(); + _boneWeightAttribArrays = createVertexAttribList(); + return true; +} + + +// +// create vertex attribute by 2 bones +// vec4(boneIndex0, weight0, boneIndex1, weight1) +// if more bones are needed then other attributes are created +// vec4(boneIndex2, weight2, boneIndex3, weight3) +// the idea is to use this format to have a granularity smaller +// than the 4 bones using two vertex attributes +// +RigTransformHardware::BoneWeightAttribList RigTransformHardware::createVertexAttribList() +{ + BoneWeightAttribList arrayList; + int nbArray = static_cast(ceilf(getNumBonesPerVertex() * 0.5)); + if (!nbArray) + return arrayList; + + arrayList.resize(nbArray); + for (int i = 0; i < nbArray; i++) + { + osg::ref_ptr array = new osg::Vec4Array; + arrayList[i] = array; + int nbVertexes = getNumVertexes(); + array->resize(nbVertexes); + for (int j = 0; j < nbVertexes; j++) + { + for (int b = 0; b < 2; b++) + { + // the granularity is 2 so if we have only one bone + // it's convenient to init the second with a weight 0 + int boneIndexInList = i*2 + b; + int boneIndexInVec4 = b*2; + (*array)[j][0 + boneIndexInVec4] = 0; + (*array)[j][1 + boneIndexInVec4] = 0; + if (boneIndexInList < getNumBonesPerVertex()) + { + float boneIndex = static_cast(_vertexIndexMatrixWeightList[j][boneIndexInList].getIndex()); + float boneWeight = _vertexIndexMatrixWeightList[j][boneIndexInList].getWeight(); + // fill the vec4 + (*array)[j][0 + boneIndexInVec4] = boneIndex; + (*array)[j][1 + boneIndexInVec4] = boneWeight; + } + } + } + } + return arrayList; +} + + +osg::Uniform* RigTransformHardware::createVertexUniform() +{ + osg::Uniform* uniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "matrixPalette", _bonePalette.size()); + return uniform; +} + + +void RigTransformHardware::setShader(osg::Shader* shader) +{ + _shader = shader; +} + +bool RigTransformHardware::init(RigGeometry& geom) +{ + osg::Vec3Array* pos = dynamic_cast(geom.getVertexArray()); + if (!pos) { + osg::notify(osg::WARN) << "RigTransformHardware no vertex array in the geometry " << geom.getName() << std::endl; + return false; + } + + if (!geom.getSkeleton()) { + osg::notify(osg::WARN) << "RigTransformHardware no skeleting set in geometry " << geom.getName() << std::endl; + return false; + } + + Bone::BoneMap bm = geom.getSkeleton()->getBoneMap(); + + if (!createPalette(pos->size(),bm, geom.getVertexInfluenceSet().getVertexToBoneList())) + return false; + + osg::ref_ptr program = new osg::Program; + program->setName("HardwareSkinning"); + if (!_shader.valid()) + _shader = osg::Shader::readShaderFile(osg::Shader::VERTEX,"skinning.vert"); + + if (!_shader.valid()) { + osg::notify(osg::WARN) << "RigTransformHardware can't load VertexShader" << std::endl; + return false; + } + + // replace max matrix by the value from uniform + { + std::string str = _shader->getShaderSource(); + std::string toreplace = std::string("MAX_MATRIX"); + std::size_t start = str.find(toreplace); + std::stringstream ss; + ss << getMatrixPaletteUniform()->getNumElements(); + str.replace(start, toreplace.size(), ss.str()); + _shader->setShaderSource(str); + osg::notify(osg::INFO) << "Shader " << str << std::endl; + } + + int attribIndex = 11; + int nbAttribs = getNumVertexAttrib(); + for (int i = 0; i < nbAttribs; i++) + { + std::stringstream ss; + ss << "boneWeight" << i; + program->addBindAttribLocation(ss.str(), attribIndex + i); + geom.setVertexAttribData(attribIndex + i, osg::Geometry::ArrayData(getVertexAttrib(i),osg::Geometry::BIND_PER_VERTEX)); + osg::notify(osg::INFO) << "set vertex attrib " << ss.str() << std::endl; + } + program->addShader(_shader.get()); + + osg::ref_ptr ss = new osg::StateSet; + ss->addUniform(getMatrixPaletteUniform()); + ss->addUniform(new osg::Uniform("nbBonesPerVertex", getNumBonesPerVertex())); + ss->setAttributeAndModes(program.get()); + geom.setStateSet(ss.get()); + _needInit = false; + return true; +} +void RigTransformHardware::update(RigGeometry& geom) +{ + computeMatrixPaletteUniform(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry()); +} diff --git a/src/osgAnimation/RigTransformSoftware.cpp b/src/osgAnimation/RigTransformSoftware.cpp new file mode 100644 index 000000000..853457679 --- /dev/null +++ b/src/osgAnimation/RigTransformSoftware.cpp @@ -0,0 +1,96 @@ +/* -*-c++-*- + * Copyright (C) 2009 Cedric Pinson + * + * 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. + */ + + +#include +#include + +using namespace osgAnimation; + +bool RigTransformSoftware::init(RigGeometry& geom) +{ + if (!geom.getSkeleton()) + return false; + Bone::BoneMap bm = geom.getSkeleton()->getBoneMap(); + initVertexSetFromBones(bm, geom.getVertexInfluenceSet().getUniqVertexSetToBoneSetList()); + _needInit = false; + return true; +} + +void RigTransformSoftware::update(RigGeometry& geom) +{ + osg::Vec3Array* pos = dynamic_cast(geom.getVertexArray()); + if (pos && _positionSource.size() != pos->size()) + { + _positionSource = std::vector(pos->begin(),pos->end()); + geom.getVertexArray()->setDataVariance(osg::Object::DYNAMIC); + } + osg::Vec3Array* normal = dynamic_cast(geom.getNormalArray()); + if (normal && _normalSource.size() != normal->size()) + { + _normalSource = std::vector(normal->begin(),normal->end()); + geom.getNormalArray()->setDataVariance(osg::Object::DYNAMIC); + } + + if (!_positionSource.empty()) + { + compute(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry(), &_positionSource.front(), &pos->front()); + pos->dirty(); + } + if (!_normalSource.empty()) + { + computeNormal(geom.getMatrixFromSkeletonToGeometry(), geom.getInvMatrixFromSkeletonToGeometry(), &_normalSource.front(), &normal->front()); + normal->dirty(); + } +} + +void RigTransformSoftware::initVertexSetFromBones(const Bone::BoneMap& map, const VertexInfluenceSet::UniqVertexSetToBoneSetList& influence) +{ + _boneSetVertexSet.clear(); + + int size = influence.size(); + _boneSetVertexSet.resize(size); + for (int i = 0; i < size; i++) + { + const 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(); + Bone::BoneMap::const_iterator it = map.find(bname); + if (it == map.end()) + { + osg::notify(osg::WARN) << "RigTransformSoftware Bone " << bname << " not found, skip the influence group " <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(); + } +} diff --git a/src/osgAnimation/StatsVisitor.cpp b/src/osgAnimation/StatsVisitor.cpp index c95a3e0bc..bd7ff0114 100644 --- a/src/osgAnimation/StatsVisitor.cpp +++ b/src/osgAnimation/StatsVisitor.cpp @@ -14,23 +14,29 @@ #include #include +#include +#include +#include +#include -osgAnimation::StatsActionVisitor::StatsActionVisitor() {} -void osgAnimation::StatsActionVisitor::reset() { _channels.clear(); } +using namespace osgAnimation; -osgAnimation::StatsActionVisitor::StatsActionVisitor(osg::Stats* stats,unsigned int frame) +StatsActionVisitor::StatsActionVisitor() {} +void StatsActionVisitor::reset() { _channels.clear(); } + +StatsActionVisitor::StatsActionVisitor(osg::Stats* stats,unsigned int frame) { _frame = frame; _stats = stats; } -void osgAnimation::StatsActionVisitor::apply(Timeline& tm) +void StatsActionVisitor::apply(Timeline& tm) { _stats->setAttribute(_frame,"Timeline", tm.getCurrentTime()); tm.traverse(*this); } -void osgAnimation::StatsActionVisitor::apply(Action& action) +void StatsActionVisitor::apply(Action& action) { if (isActive(action)) { @@ -39,7 +45,7 @@ void osgAnimation::StatsActionVisitor::apply(Action& action) } } -void osgAnimation::StatsActionVisitor::apply(BlendIn& action) +void StatsActionVisitor::apply(ActionBlendIn& action) { if (isActive(action)) { @@ -48,7 +54,7 @@ void osgAnimation::StatsActionVisitor::apply(BlendIn& action) } } -void osgAnimation::StatsActionVisitor::apply(BlendOut& action) +void StatsActionVisitor::apply(ActionBlendOut& action) { if (isActive(action)) { @@ -57,7 +63,7 @@ void osgAnimation::StatsActionVisitor::apply(BlendOut& action) } } -void osgAnimation::StatsActionVisitor::apply(ActionAnimation& action) +void StatsActionVisitor::apply(ActionAnimation& action) { if (isActive(action)) { @@ -66,11 +72,11 @@ void osgAnimation::StatsActionVisitor::apply(ActionAnimation& action) } } -void osgAnimation::StatsActionVisitor::apply(StripAnimation& action) +void StatsActionVisitor::apply(ActionStripAnimation& action) { if (isActive(action)) { _channels.push_back(action.getName()); - _stats->setAttribute(_frame,action.getName(), action.getActionAnimation()->getAnimation()->getWeight()); + _stats->setAttribute(_frame,action.getName(), action.getAnimation()->getAnimation()->getWeight()); } } diff --git a/src/osgAnimation/VertexInfluence.cpp b/src/osgAnimation/VertexInfluence.cpp index c3d1d84fc..d523a9623 100644 --- a/src/osgAnimation/VertexInfluence.cpp +++ b/src/osgAnimation/VertexInfluence.cpp @@ -1,5 +1,5 @@ /* -*-c++-*- - * Copyright (C) 2008 Cedric Pinson + * Copyright (C) 2008 Cedric Pinson * * 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 @@ -10,7 +10,7 @@ * 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. -*/ + */ #include #include @@ -19,10 +19,11 @@ using namespace osgAnimation; -const osgAnimation::VertexInfluenceSet::VertexIndexToBoneWeightMap& osgAnimation::VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;} +void VertexInfluenceSet::addVertexInfluence(const VertexInfluence& v) { _bone2Vertexes.push_back(v); } +const VertexInfluenceSet::VertexIndexToBoneWeightMap& VertexInfluenceSet::getVertexToBoneList() const { return _vertex2Bones;} // this class manage VertexInfluence database by mesh // reference bones per vertex ... -void osgAnimation::VertexInfluenceSet::buildVertex2BoneList() +void VertexInfluenceSet::buildVertex2BoneList() { _vertex2Bones.clear(); for (BoneToVertexList::const_iterator it = _bone2Vertexes.begin(); it != _bone2Vertexes.end(); it++) @@ -35,7 +36,7 @@ void osgAnimation::VertexInfluenceSet::buildVertex2BoneList() int index = viw.first; float weight = viw.second; if (vi.getName().empty()) - osg::notify(osg::WARN) << "osgAnimation::VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; + osg::notify(osg::WARN) << "VertexInfluenceSet::buildVertex2BoneList warning vertex " << index << " is not assigned to a bone" << std::endl; _vertex2Bones[index].push_back(BoneWeight(vi.getName(), weight)); } } @@ -64,10 +65,10 @@ void osgAnimation::VertexInfluenceSet::buildVertex2BoneList() // sort by name and weight -struct SortByNameAndWeight : public std::less +struct SortByNameAndWeight : public std::less { - bool operator()(const osgAnimation::VertexInfluenceSet::BoneWeight& b0, - const osgAnimation::VertexInfluenceSet::BoneWeight& b1) const + bool operator()(const VertexInfluenceSet::BoneWeight& b0, + const VertexInfluenceSet::BoneWeight& b1) const { if (b0.getBoneName() < b1.getBoneName()) return true; @@ -79,10 +80,10 @@ struct SortByNameAndWeight : public std::less +struct SortByBoneWeightList : public std::less { - bool operator()(const osgAnimation::VertexInfluenceSet::BoneWeightList& b0, - const osgAnimation::VertexInfluenceSet::BoneWeightList& b1) const + bool operator()(const VertexInfluenceSet::BoneWeightList& b0, + const VertexInfluenceSet::BoneWeightList& b1) const { if (b0.size() < b1.size()) return true; @@ -102,7 +103,13 @@ struct SortByBoneWeightList : public std::lesssecond); } } +