From c005e6997ce15d0dd1dc5d33c75a83e52061f85f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 16 Nov 2012 15:40:41 +0000 Subject: [PATCH] Added first cut implememtation of PropertyAnimation class --- include/osgPresentation/PropertyManager | 49 ++++++ src/osgPresentation/PropertyManager.cpp | 219 ++++++++++++++++++++++++ 2 files changed, 268 insertions(+) diff --git a/include/osgPresentation/PropertyManager b/include/osgPresentation/PropertyManager index 93bcc5f27..26e001140 100644 --- a/include/osgPresentation/PropertyManager +++ b/include/osgPresentation/PropertyManager @@ -13,6 +13,7 @@ #ifndef PROPERTYMANAGER #define PROPERTYMANAGER 1 +#include #include #include #include @@ -61,6 +62,54 @@ protected: }; +class PropertyAnimation : public osg::NodeCallback +{ +public: + PropertyAnimation(): + _firstTime(DBL_MAX), + _latestTime(0.0), + _pause(false), + _pauseTime(0.0) {} + + void setPropertyManager(PropertyManager* pm) { _pm = pm; } + PropertyManager* getPropertyManager() const { return _pm.get(); } + + typedef std::map > KeyFrameMap; + + KeyFrameMap& getKeyFrameMap() { return _keyFrameMap; } + const KeyFrameMap& getKeyFrameMap() const { return _keyFrameMap; } + + void addKeyFrame(double time, osg::UserDataContainer* udc) + { + _keyFrameMap[time] = udc; + } + + virtual void reset(); + + void setPause(bool pause); + bool getPause() const { return _pause; } + + double getAnimationTime() const; + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + + virtual void update(); + +protected: + + osg::ref_ptr _pm; + + KeyFrameMap _keyFrameMap; + + double _firstTime; + double _latestTime; + bool _pause; + double _pauseTime; + +}; + + + struct OSGPRESENTATION_EXPORT ImageSequenceUpdateCallback : public osg::NodeCallback { ImageSequenceUpdateCallback(osg::ImageSequence* is, PropertyManager* pm, const std::string& propertyName): diff --git a/src/osgPresentation/PropertyManager.cpp b/src/osgPresentation/PropertyManager.cpp index 2e27be6fe..92ed5c25e 100644 --- a/src/osgPresentation/PropertyManager.cpp +++ b/src/osgPresentation/PropertyManager.cpp @@ -14,6 +14,225 @@ using namespace osgPresentation; + + +void PropertyAnimation::reset() +{ + _firstTime = DBL_MAX; + _pauseTime = DBL_MAX; +} + +void PropertyAnimation::setPause(bool pause) +{ + if (_pause==pause) + { + return; + } + + _pause = pause; + + if (_firstTime==DBL_MAX) return; + + if (_pause) + { + _pauseTime = _latestTime; + } + else + { + _firstTime += (_latestTime-_pauseTime); + } +} + +double PropertyAnimation::getAnimationTime() const +{ + return _latestTime-_firstTime; +} + + +void PropertyAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv) +{ + if (nv->getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR && + nv->getFrameStamp()) + { + double time = nv->getFrameStamp()->getSimulationTime(); + _latestTime = time; + + if (!_pause) + { + // Only update _firstTime the first time, when its value is still DBL_MAX + if (_firstTime==DBL_MAX) _firstTime = time; + update(); + } + } + + traverse(node, nv); +} + +class MySetValueVisitor : public osg::ValueObject::SetValueVisitor +{ +public: + + MySetValueVisitor(double r1, double r2, osg::ValueObject* object2) + { + } + + template + void combineRealUserValue(T& value) const + { + typedef osg::TemplateValueObject UserValueObject; + const UserValueObject* uvo = object2 ? dynamic_cast(object2) : 0; + if (uvo) + { + value = value*_r1 + uvo->getValue()*_r2; + } + } + + template + void combineIntegerUserValue(T& value) const + { + typedef osg::TemplateValueObject UserValueObject; + const UserValueObject* uvo = object2 ? dynamic_cast(object2) : 0; + if (uvo) + { + value = static_cast(static_cast(value)*_r1 + static_cast(uvo->getValue())*_r2); + } + } + + template + void combineDiscretUserValue(T& value) const + { + if (_r1<_r2) // choose value2 if possible + { + typedef osg::TemplateValueObject UserValueObject; + const UserValueObject* uvo = object2 ? dynamic_cast(object2) : 0; + if (uvo) + { + value = uvo->getValue(); + } + } + } + + template + void combineRotationUserValue(T& value) const + { + OSG_NOTICE<<"combineRotationUserValue TODO - do slerp"< + void combinePlaneUserValue(T& value) const + { + OSG_NOTICE<<"combinePlaneUserValue TODO"< + void combineMatrixUserValue(T& value) const + { + OSG_NOTICE<<"combineMatrixUserValue TODO - decomposs into translate, rotation and scale and then interpolate."< result; + + if (_keyFrameMap.empty()) return; + + KeyFrameMap::const_iterator itr = _keyFrameMap.lower_bound(time); + if (itr==_keyFrameMap.begin()) + { + // need to copy first UserDataContainer + OSG_NOTICE<<"PropertyAnimation::update() : copy first UserDataContainer"<second.get(), osg::CopyOp::DEEP_COPY_ALL); + } + else if (itr!=_keyFrameMap.end()) + { + KeyFrameMap::const_iterator itr_1 = itr; --itr_1; + KeyFrameMap::const_iterator itr_2 = itr; + + // delta_time = second.time - first.time + double delta_time = itr_2->first - itr_1->first; + double r1, r2; + if (delta_time==0.0) + { + r1 = 0.5; + r2 = 0.5; + } + else + { + r1 = (time - itr_1->first)/delta_time; + r2 = 1.0-r1; + } + + osg::UserDataContainer* p1 = itr_1->second.get(); + osg::UserDataContainer* p2 = itr_2->second.get(); + + // clone all the properties from p1; + result = osg::clone(p1, osg::CopyOp::DEEP_COPY_ALL); + + for(unsigned int i2=0; i2getNumUserObjects(); ++i2) + { + osg::Object* obj_2 = p2->getUserObject(i2); + unsigned int i1 = result->getUserObjectIndex(obj_2->getName()); + if (i1getNumUserObjects()) + { + osg::Object* obj_1 = result->getUserObject(i1); + osg::ValueObject* valueobject_1 = dynamic_cast(obj_1); + osg::ValueObject* valueobject_2 = dynamic_cast(obj_2); + if (valueobject_1) + { + MySetValueVisitor mySetValue(r1, r2, valueobject_2); + valueobject_1->set(mySetValue); + } + } + else + { + // need to insert property; + result->addUserObject(obj_2->clone(osg::CopyOp::DEEP_COPY_ALL)); + } + + } + + + OSG_NOTICE<<"PropertyAnimation::update() : Need to interpolate between two UserDataContainer, r1="<second.get(), osg::CopyOp::DEEP_COPY_ALL); + } + +} + + + void ImageSequenceUpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) { float x;