diff --git a/examples/slideshow3D/ReaderWriterXML.cpp b/examples/slideshow3D/ReaderWriterXML.cpp index 105d78e36..61c385aa0 100644 --- a/examples/slideshow3D/ReaderWriterXML.cpp +++ b/examples/slideshow3D/ReaderWriterXML.cpp @@ -10,6 +10,8 @@ #include #include +#include + /** * OpenSceneGraph plugin wrapper/converter. @@ -57,7 +59,23 @@ public: return _colorMap[str]; } + inline bool read(const char* str, float& value) const; + inline bool read(const char* str, osg::Vec2& value) const; + inline bool read(const char* str, osg::Vec3& value) const; + inline bool read(const char* str, osg::Vec4& value) const; + inline bool read(const std::string& str, float& value) const; + inline bool read(const std::string& str, osg::Vec2& value) const; + inline bool read(const std::string& str, osg::Vec3& value) const; + inline bool read(const std::string& str, osg::Vec4& value) const; + + bool getProperty(xmlNodePtr cur, const char* token) const; + bool getProperty(xmlNodePtr cur, const char* token, float& value) const; + bool getProperty(xmlNodePtr cur, const char* token, osg::Vec2& value) const; + bool getProperty(xmlNodePtr cur, const char* token, osg::Vec3& value) const; + bool getProperty(xmlNodePtr cur, const char* token, osg::Vec4& value) const; + bool getProperty(xmlNodePtr cur, const char* token, std::string& value) const; + std::map _colorMap; }; @@ -65,46 +83,206 @@ public: // Register with Registry to instantiate the above reader/writer. osgDB::RegisterReaderWriterProxy g_readerWriter_SS3D_Proxy; +bool ReaderWriterSS3D::read(const char* str, float& value) const +{ + if (!str) return false; + std::istringstream iss((const char*)str); + iss >> value; + return !iss.fail(); +} + +bool ReaderWriterSS3D::read(const char* str, osg::Vec2& value) const +{ + if (!str) return false; + std::istringstream iss((const char*)str); + iss >> value.x() >> value.y(); + return !iss.fail(); +} + +bool ReaderWriterSS3D::read(const char* str, osg::Vec3& value) const +{ + if (!str) return false; + std::istringstream iss((const char*)str); + iss >> value.x() >> value.y() >> value.z(); + return !iss.fail(); +} + +bool ReaderWriterSS3D::read(const char* str, osg::Vec4& value) const +{ + if (!str) return false; + std::istringstream iss((const char*)str); + iss >> value.x() >> value.y() >> value.z() >> value.w(); + return !iss.fail(); +} + + +bool ReaderWriterSS3D::read(const std::string& str, float& value) const +{ + std::istringstream iss(str); + iss >> value; + return !iss.fail(); +} + +bool ReaderWriterSS3D::read(const std::string& str, osg::Vec2& value) const +{ + std::istringstream iss(str); + iss >> value.x() >> value.y(); + return !iss.fail(); +} + +bool ReaderWriterSS3D::read(const std::string& str, osg::Vec3& value) const +{ + std::istringstream iss(str); + iss >> value.x() >> value.y() >> value.z(); + return !iss.fail(); +} + +bool ReaderWriterSS3D::read(const std::string& str, osg::Vec4& value) const +{ + std::istringstream iss(str); + iss >> value.x() >> value.y() >> value.z() >> value.w(); + return !iss.fail(); +} + +bool ReaderWriterSS3D::getProperty(xmlNodePtr cur, const char* token) const +{ + bool success = false; + xmlChar *key; + key = xmlGetProp (cur, (const xmlChar *)token); + if (key) success=true; + xmlFree(key); + return success; +} + +bool ReaderWriterSS3D::getProperty(xmlNodePtr cur, const char* token, float& value) const +{ + xmlChar *key; + key = xmlGetProp (cur, (const xmlChar *)token); + bool success = read((const char*)key,value); + xmlFree(key); + return success; +} + +bool ReaderWriterSS3D::getProperty(xmlNodePtr cur, const char* token, osg::Vec2& value) const +{ + xmlChar *key; + key = xmlGetProp (cur, (const xmlChar *)token); + bool success = read((const char*)key,value); + xmlFree(key); + return success; +} + +bool ReaderWriterSS3D::getProperty(xmlNodePtr cur, const char* token, osg::Vec3& value) const +{ + xmlChar *key; + key = xmlGetProp (cur, (const xmlChar *)token); + bool success = read((const char*)key,value); + xmlFree(key); + return success; +} + +bool ReaderWriterSS3D::getProperty(xmlNodePtr cur, const char* token, osg::Vec4& value) const +{ + xmlChar *key; + key = xmlGetProp (cur, (const xmlChar *)token); + bool success = read((const char*)key,value); + xmlFree(key); + return success; +} + +bool ReaderWriterSS3D::getProperty(xmlNodePtr cur, const char* token, std::string& value) const +{ + bool success = false; + xmlChar *key; + key = xmlGetProp (cur, (const xmlChar *)token); + if (key) + { + success = true; + value = (const char*)key; + } + xmlFree(key); + return success; +} + void ReaderWriterSS3D::parseModel(SlideShowConstructor& constructor, xmlDocPtr doc, xmlNodePtr cur) { std::string filename; - float scale = 1.0f; - float rotation = 0.0f; - float position = 0.5f; - xmlChar *key; - cur = cur->xmlChildrenNode; - while (cur != NULL) + SlideShowConstructor::CoordinateFrame coordinate_frame = SlideShowConstructor::SLIDE; + osg::Vec3 position(0.0f,1.0f,0.0f); + osg::Vec4 rotate(0.0f,0.0f,0.0f,1.0f); + float scale = 1.0f; + + osg::Vec4 rotation(0.0f,0.0f,0.0f,1.0f); + std::string animation_path; + std::string camera_path; + + // temporary + std::string str; + + if (getProperty(cur, "coordinate_frame", str)) { - if ((!xmlStrcmp(cur->name, (const xmlChar *)"filename"))) - { - key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (key) filename = (const char*)key; - xmlFree(key); - } - else if ((!xmlStrcmp(cur->name, (const xmlChar *)"scale"))) - { - key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (key) scale = atoi((const char*)key); - xmlFree(key); - } - else if ((!xmlStrcmp(cur->name, (const xmlChar *)"rotation"))) - { - key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (key) rotation = atoi((const char*)key); - xmlFree(key); - } - else if ((!xmlStrcmp(cur->name, (const xmlChar *)"position"))) - { - key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - if (key) position = atoi((const char*)key)/100.0f; - xmlFree(key); - } - cur = cur->next; + if (str=="model") coordinate_frame = SlideShowConstructor::MODEL; + else if (str=="slide") coordinate_frame = SlideShowConstructor::SLIDE; + else std::cout<<"Parser error - coordinate_frame=\""<xmlChildrenNode, 1); + if (key) filename = (const char*)key; + xmlFree(key); + + if (!filename.empty()) + { + if (!camera_path.empty()) + { + constructor.addModelWithCameraPath(filename,coordinate_frame,position,scale,rotate,camera_path); + } + else if (!animation_path.empty()) + { + constructor.addModelWithPath(filename,coordinate_frame,position,scale,rotate,animation_path); + } + else + { + constructor.addModel(filename,coordinate_frame,position,scale,rotate,rotation); + } + } } void ReaderWriterSS3D::parseStereoPair(SlideShowConstructor& constructor, xmlDocPtr doc, xmlNodePtr cur) @@ -115,7 +293,7 @@ void ReaderWriterSS3D::parseStereoPair(SlideShowConstructor& constructor, xmlDoc float height = 1.0f; xmlChar *key; key = xmlGetProp (cur, (const xmlChar *)"height"); - if (key) height = atoi((const char*)key); + if (key) height = atof((const char*)key); xmlFree(key); cur = cur->xmlChildrenNode; diff --git a/examples/slideshow3D/SlideEventHandler.cpp b/examples/slideshow3D/SlideEventHandler.cpp index bf2a7abdb..f99798a38 100644 --- a/examples/slideshow3D/SlideEventHandler.cpp +++ b/examples/slideshow3D/SlideEventHandler.cpp @@ -1,6 +1,9 @@ #include "SlideEventHandler.h" #include "SlideShowConstructor.h" +#include +#include + class FindNamedSwitchVisitor : public osg::NodeVisitor { public: @@ -109,7 +112,7 @@ bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction { case(osgGA::GUIEventAdapter::FRAME): { - if (_autoSteppingActive) + if (_autoSteppingActive && !_pause) { double time = ea.time(); @@ -183,12 +186,17 @@ bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction previousSlide(); return true; } - else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Pause) + else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Pause || + ea.getKey()=='p') { _pause = !_pause; - if (_pause) std::cout<<"Pause"<0) return selectLayer(_activeLayer-1); else return false; } + + +class ResetUpdateCallbacksVisitor : public osg::NodeVisitor +{ +public: + ResetUpdateCallbacksVisitor(bool pause): +// osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), + _pause(pause) {} + + + void apply(osg::Node& node) + { + osg::AnimationPathCallback* apc = dynamic_cast(node.getUpdateCallback()); + osgUtil::TransformCallback* tc = dynamic_cast(node.getUpdateCallback()); + if (apc) + { + apc->reset(); + apc->update(node); + } + if (tc) + { + //tc->reset(); + } + traverse(node); + } + + bool _pause; +}; + +void SlideEventHandler::resetUpdateCallbacks() +{ + ResetUpdateCallbacksVisitor rucv(_pause); + _presentationSwitch->accept(rucv); +} + +class ActivityUpdateCallbacksVisitor : public osg::NodeVisitor +{ +public: + ActivityUpdateCallbacksVisitor(bool pause): +// osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), + _pause(pause) {} + + + void apply(osg::Node& node) + { + osg::AnimationPathCallback* apc = dynamic_cast(node.getUpdateCallback()); + osgUtil::TransformCallback* tc = dynamic_cast(node.getUpdateCallback()); + if (apc) + { + apc->setPause(_pause); + } + if (tc) + { + tc->setPause(_pause); + } + traverse(node); + } + + bool _pause; +}; + +void SlideEventHandler::resetUpdateCallbackActivity() +{ + ActivityUpdateCallbacksVisitor aucv(_pause); + _presentationSwitch->accept(aucv); +} diff --git a/examples/slideshow3D/SlideEventHandler.h b/examples/slideshow3D/SlideEventHandler.h index 306c3ce29..8bf55f6fe 100644 --- a/examples/slideshow3D/SlideEventHandler.h +++ b/examples/slideshow3D/SlideEventHandler.h @@ -77,6 +77,9 @@ protected: bool _autoSteppingActive; bool _loopPresentation; bool _pause; + + void resetUpdateCallbacks(); + void resetUpdateCallbackActivity(); }; diff --git a/examples/slideshow3D/SlideShowConstructor.cpp b/examples/slideshow3D/SlideShowConstructor.cpp index 9dc324dce..06829cbd0 100644 --- a/examples/slideshow3D/SlideShowConstructor.cpp +++ b/examples/slideshow3D/SlideShowConstructor.cpp @@ -6,19 +6,23 @@ #include #include +#include + #include +#include #include SlideShowConstructor::SlideShowConstructor() { - _slideOrigin.set(0.0f,0.0f,0.0f); - + _slideDistance = osg::DisplaySettings::instance()->getScreenDistance(); _slideHeight = osg::DisplaySettings::instance()->getScreenHeight(); - _slideWidth = _slideHeight*1280.0f/1024.f; + _slideOrigin.set(-_slideWidth*0.5f,_slideDistance,-_slideHeight*0.5f); + + _backgroundColor.set(0.0f,0.0f,0.0f,1.0f); _textColor.set(1.0f,1.0f,1.0f,1.0f); _textFont = "fonts/arial.ttf"; @@ -77,11 +81,9 @@ void SlideShowConstructor::createPresentation() _root->addChild(_presentationSwitch.get()); osg::Vec3 slideCenter = _slideOrigin + osg::Vec3(_slideWidth*0.5f,0.0f,_slideHeight*0.5f); - - float distanceToHeightRatio = osg::DisplaySettings::instance()->getScreenDistance()/osg::DisplaySettings::instance()->getScreenHeight(); - + HomePosition* hp = new HomePosition; - hp->eye = slideCenter+osg::Vec3(0.0f,-distanceToHeightRatio*_slideHeight,0.0f); + hp->eye.set(0.0f,0.0f,0.0f); hp->center = slideCenter; hp->up.set(0.0f,0.0f,1.0f); @@ -374,7 +376,7 @@ void SlideShowConstructor::addStereoImagePair(const std::string& filenameLeft,co _currentLayer->addChild(stereopair); } -void SlideShowConstructor::addModel(const std::string& filename,float scale,float rotation,float position) +void SlideShowConstructor::addModel(const std::string& filename, CoordinateFrame coordinate_frame, const osg::Vec3& position, float scale, const osg::Vec4& rotate, const osg::Vec4& rotation) { if (!_currentLayer) addLayer(); @@ -382,24 +384,232 @@ void SlideShowConstructor::addModel(const std::string& filename,float scale,floa if (!model) return; - osg::Vec3 pos = _modelLeft*(1.0f-position) + _modelRight*position; - float radius = scale*_slideHeight*0.7f; - osg::Quat quat; - quat.makeRotate(osg::DegreesToRadians(rotation),0.0f,0.0f,1.0f); + if (coordinate_frame==SLIDE) + { + osg::Vec3 pos(_slideWidth*position.x(), + _slideDistance*position.y(), + _slideHeight*position.z()); + + const osg::BoundingSphere& bs = model->getBound(); + float model_scale = scale*_slideHeight*0.7f/bs.radius(); - osg::MatrixTransform* transform = new osg::MatrixTransform; - - const osg::BoundingSphere& bs = model->getBound(); - - transform->setDataVariance(osg::Object::STATIC); - transform->setMatrix(osg::Matrix::translate(-bs.center())* - osg::Matrix::scale(radius/bs.radius(),radius/bs.radius(),radius/bs.radius())* - osg::Matrix::rotate(quat)* - osg::Matrix::translate(pos)); - - transform->addChild(model); - - _currentLayer->addChild(transform); + osg::MatrixTransform* transform = new osg::MatrixTransform; + transform->setDataVariance(osg::Object::STATIC); + transform->setMatrix(osg::Matrix::translate(-bs.center())* + osg::Matrix::scale(model_scale,model_scale,model_scale)* + osg::Matrix::rotate(osg::DegreesToRadians(rotate[0]),rotate[1],rotate[2],rotate[3])* + osg::Matrix::translate(pos)); + transform->addChild(model); + + if (rotation[0]!=0.0) + { + osg::MatrixTransform* animation_transform = new osg::MatrixTransform; + animation_transform->setDataVariance(osg::Object::DYNAMIC); + animation_transform->setUpdateCallback(new osgUtil::TransformCallback(pos,osg::Vec3(rotation[1],rotation[2],rotation[3]),osg::DegreesToRadians(rotation[0]))); + animation_transform->addChild(transform); + + _currentLayer->addChild(animation_transform); + } + else + { + _currentLayer->addChild(transform); + } + + } + else + { + osg::MatrixTransform* transform = new osg::MatrixTransform; + transform->setDataVariance(osg::Object::STATIC); + transform->setMatrix(osg::Matrix::translate(-position)* + osg::Matrix::scale(scale,scale,scale)* + osg::Matrix::rotate(osg::DegreesToRadians(rotate[0]),rotate[1],rotate[2],rotate[3])); + + transform->addChild(model); + + if (rotation[0]!=0.0) + { + osg::MatrixTransform* animation_transform = new osg::MatrixTransform; + animation_transform->setDataVariance(osg::Object::DYNAMIC); + animation_transform->setUpdateCallback(new osgUtil::TransformCallback(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(rotation[1],rotation[2],rotation[3]),osg::DegreesToRadians(rotation[0]))); + animation_transform->addChild(transform); + + _currentLayer->addChild(animation_transform); + } + else + { + _currentLayer->addChild(transform); + } + + } } +void SlideShowConstructor::addModelWithPath(const std::string& filename, CoordinateFrame coordinate_frame, const osg::Vec3& position, float scale, const osg::Vec4& rotate, const std::string& animation_path) +{ + if (!_currentLayer) addLayer(); + + osg::Node* model = osgDB::readNodeFile(filename); + + if (!model) return; + + osg::AnimationPath* animation = 0; + if (!animation_path.empty()) + { + std::string absolute_animation_file_path = osgDB::findDataFile(animation_path); + if (!absolute_animation_file_path.empty()) + { + std::ifstream animation_filestream(absolute_animation_file_path.c_str()); + if (!animation_filestream.eof()) + { + animation = new osg::AnimationPath; + animation->read(animation_filestream); + } + } + } + + + if (coordinate_frame==SLIDE) + { + osg::Vec3 pos(_slideWidth*position.x(), + _slideDistance*position.y(), + _slideHeight*position.z()); + + const osg::BoundingSphere& bs = model->getBound(); + float model_scale = scale*_slideHeight*0.7f/bs.radius(); + + osg::MatrixTransform* transform = new osg::MatrixTransform; + transform->setDataVariance(osg::Object::STATIC); + transform->setMatrix(osg::Matrix::translate(-bs.center())* + osg::Matrix::scale(model_scale,model_scale,model_scale)* + osg::Matrix::rotate(osg::DegreesToRadians(rotate[0]),rotate[1],rotate[2],rotate[3])* + osg::Matrix::translate(pos)); + + transform->addChild(model); + + _currentLayer->addChild(transform); + + } + else + { + osg::MatrixTransform* transform = new osg::MatrixTransform; + transform->setDataVariance(osg::Object::STATIC); + transform->setMatrix(osg::Matrix::translate(-position)* + osg::Matrix::scale(scale,scale,scale)* + osg::Matrix::rotate(osg::DegreesToRadians(rotate[0]),rotate[1],rotate[2],rotate[3])); + + transform->addChild(model); + + if (animation) + { + osg::MatrixTransform* animation_transform = new osg::MatrixTransform; + animation_transform->setDataVariance(osg::Object::DYNAMIC); + + osg::AnimationPathCallback* apc = new osg::AnimationPathCallback(animation); + + animation_transform->setUpdateCallback(apc); + animation_transform->addChild(transform); + + _currentLayer->addChild(animation_transform); + +// +// osg::MatrixTransform* orientation_transform = new osg::MatrixTransform; +// orientation_transform->setDataVariance(osg::Object::STATIC); +// orientation_transform->addChild(animation_transform); +// +// //orientation_transform->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(-00.0f),0.0f,1.0f,0.0f)); +// //orientation_transform->setMatrix(osg::Matrix::inverse(osg::Matrix::lookAt(osg::Vec3(0.0,0.0,0.0),osg::Vec3(0.0,1.0,0.0),osg::Vec3(0.0,0.0,1.0)))); +// +// _currentLayer->addChild(orientation_transform); + + } + else + { + _currentLayer->addChild(transform); + } + + } +} + +void SlideShowConstructor::addModelWithCameraPath(const std::string& filename, CoordinateFrame coordinate_frame, const osg::Vec3& position, float scale, const osg::Vec4& rotate, const std::string& animation_path) +{ + if (!_currentLayer) addLayer(); + + osg::Node* model = osgDB::readNodeFile(filename); + + if (!model) return; + + osg::AnimationPath* animation = 0; + if (!animation_path.empty()) + { + std::string absolute_animation_file_path = osgDB::findDataFile(animation_path); + if (!absolute_animation_file_path.empty()) + { + std::ifstream animation_filestream(absolute_animation_file_path.c_str()); + if (!animation_filestream.eof()) + { + animation = new osg::AnimationPath; + animation->read(animation_filestream); + } + } + } + + + if (coordinate_frame==SLIDE) + { + osg::Vec3 pos(_slideWidth*position.x(), + _slideDistance*position.y(), + _slideHeight*position.z()); + + const osg::BoundingSphere& bs = model->getBound(); + float model_scale = scale*_slideHeight*0.7f/bs.radius(); + + osg::MatrixTransform* transform = new osg::MatrixTransform; + transform->setDataVariance(osg::Object::STATIC); + transform->setMatrix(osg::Matrix::translate(-bs.center())* + osg::Matrix::scale(model_scale,model_scale,model_scale)* + osg::Matrix::rotate(osg::DegreesToRadians(rotate[0]),rotate[1],rotate[2],rotate[3])* + osg::Matrix::translate(pos)); + + transform->addChild(model); + + _currentLayer->addChild(transform); + + } + else + { + osg::MatrixTransform* transform = new osg::MatrixTransform; + transform->setDataVariance(osg::Object::STATIC); + transform->setMatrix(osg::Matrix::translate(-position)* + osg::Matrix::scale(scale,scale,scale)* + osg::Matrix::rotate(osg::DegreesToRadians(rotate[0]),rotate[1],rotate[2],rotate[3])); + + transform->addChild(model); + + if (animation) + { + osg::MatrixTransform* animation_transform = new osg::MatrixTransform; + animation_transform->setDataVariance(osg::Object::DYNAMIC); + + osg::AnimationPathCallback* apc = new osg::AnimationPathCallback(animation); + apc->setUseInverseMatrix(true); + + animation_transform->setUpdateCallback(apc); + animation_transform->addChild(transform); + + osg::MatrixTransform* orientation_transform = new osg::MatrixTransform; + orientation_transform->setDataVariance(osg::Object::STATIC); + orientation_transform->addChild(animation_transform); + + //orientation_transform->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(-00.0f),0.0f,1.0f,0.0f)); + orientation_transform->setMatrix(osg::Matrix::inverse(osg::Matrix::lookAt(osg::Vec3(0.0,0.0,0.0),osg::Vec3(0.0,1.0,0.0),osg::Vec3(0.0,0.0,1.0)))); + + _currentLayer->addChild(orientation_transform); + + } + else + { + _currentLayer->addChild(transform); + } + + } +} diff --git a/examples/slideshow3D/SlideShowConstructor.h b/examples/slideshow3D/SlideShowConstructor.h index 27955219e..63c15f52c 100644 --- a/examples/slideshow3D/SlideShowConstructor.h +++ b/examples/slideshow3D/SlideShowConstructor.h @@ -71,7 +71,11 @@ public: void addStereoImagePair(const std::string& filenameLeft,const std::string& filenameRight,float height); - void addModel(const std::string& filename,float scale,float rotation,float position); + enum CoordinateFrame { SLIDE, MODEL }; + + void addModel(const std::string& filename, CoordinateFrame coordinate_frame, const osg::Vec3& position, float scale, const osg::Vec4& rotate, const osg::Vec4& rotation); + void addModelWithPath(const std::string& filename, CoordinateFrame coordinate_frame, const osg::Vec3& position, float scale, const osg::Vec4& rotate, const std::string& animation_path); + void addModelWithCameraPath(const std::string& filename, CoordinateFrame coordinate_frame, const osg::Vec3& position, float scale, const osg::Vec4& rotate, const std::string& animation_path); osg::ClearNode* takePresentation() { return _root.release(); } @@ -88,6 +92,7 @@ protected: osg::Vec3 _slideOrigin; float _slideWidth; float _slideHeight; + float _slideDistance; osg::Vec4 _backgroundColor; osg::Vec4 _textColor; diff --git a/include/osg/AnimationPath b/include/osg/AnimationPath index fefb29269..166bd0232 100644 --- a/include/osg/AnimationPath +++ b/include/osg/AnimationPath @@ -63,7 +63,8 @@ class SG_EXPORT AnimationPath : public virtual osg::Object osg::Vec3 _position; osg::Quat _rotation; osg::Vec3 _scale; - + + inline void interpolate(float ratio,const ControlPoint& first, const ControlPoint& second) { float one_minus_ratio = 1.0f-ratio; @@ -89,15 +90,15 @@ class SG_EXPORT AnimationPath : public virtual osg::Object inline void getInverse(Matrixf& matrix) const { matrix.makeScale(1.0f/_scale.x(),1.0f/_scale.y(),1.0f/_scale.y()); - matrix.postMult(osg::Matrixf::rotate(_rotation.inverse())); - matrix.postMult(osg::Matrixf::translate(-_position)); + matrix.preMult(osg::Matrixf::rotate(_rotation.inverse())); + matrix.preMult(osg::Matrixf::translate(-_position)); } inline void getInverse(Matrixd& matrix) const { matrix.makeScale(1.0f/_scale.x(),1.0f/_scale.y(),1.0f/_scale.y()); - matrix.postMult(osg::Matrixd::rotate(_rotation.inverse())); - matrix.postMult(osg::Matrixd::translate(-_position)); + matrix.preMult(osg::Matrixd::rotate(_rotation.inverse())); + matrix.preMult(osg::Matrixd::translate(-_position)); } }; @@ -163,6 +164,12 @@ class SG_EXPORT AnimationPath : public virtual osg::Object TimeControlPointMap& getTimeControlPointMap() { return _timeControlPointMap; } const TimeControlPointMap& getTimeControlPointMap() const { return _timeControlPointMap; } + + /** read the anumation path from a flat ascii file stream.*/ + void read(std::istream& in); + + /** write the anumation path to a flat ascii file stream.*/ + void write(std::ostream& out); protected: @@ -182,47 +189,63 @@ class SG_EXPORT AnimationPathCallback : public NodeCallback _timeOffset(0.0), _timeMultiplier(1.0), _firstTime(0.0), - _animationTime(0.0) {} + _latestTime(0.0), + _pause(false), + _pauseTime(0.0) {} AnimationPathCallback(const AnimationPathCallback& apc,const CopyOp& copyop): NodeCallback(apc,copyop), _animationPath(apc._animationPath), + _useInverseMatrix(apc._useInverseMatrix), _timeOffset(apc._timeOffset), _timeMultiplier(apc._timeMultiplier), _firstTime(apc._firstTime), - _animationTime(apc._animationTime) {} + _latestTime(apc._latestTime), + _pause(apc._pause), + _pauseTime(apc._pauseTime) {} META_Object(osg,AnimationPathCallback); AnimationPathCallback(AnimationPath* ap,double timeOffset=0.0f,double timeMultiplier=1.0f): _animationPath(ap), + _useInverseMatrix(false), _timeOffset(timeOffset), _timeMultiplier(timeMultiplier), _firstTime(0.0), - _animationTime(0.0) {} - - + _latestTime(0.0), + _pause(false), + _pauseTime(0.0) {} void setAnimationPath(AnimationPath* path) { _animationPath = path; } AnimationPath* getAnimationPath() { return _animationPath.get(); } const AnimationPath* getAnimationPath() const { return _animationPath.get(); } + + void setUseInverseMatrix(bool useInverseMatrix) { _useInverseMatrix = useInverseMatrix; } + bool getUseInverseMatrix() const { return _useInverseMatrix; } + void reset(); + + void setPause(bool pause); /** implements the callback*/ virtual void operator()(Node* node, NodeVisitor* nv); + void update(osg::Node& node); public: ref_ptr _animationPath; + bool _useInverseMatrix; double _timeOffset; double _timeMultiplier; double _firstTime; - mutable double _animationTime; + double _latestTime; + bool _pause; + double _pauseTime; protected: diff --git a/include/osgUtil/TransformCallback b/include/osgUtil/TransformCallback index 7af5e6700..f957506c4 100644 --- a/include/osgUtil/TransformCallback +++ b/include/osgUtil/TransformCallback @@ -28,8 +28,11 @@ class OSGUTIL_EXPORT TransformCallback : public osg::NodeCallback TransformCallback(const osg::Vec3& pivot,const osg::Vec3& axis,float angularVelocity); - virtual void operator() (osg::Node* node, osg::NodeVisitor* nv); - + void setPause(bool pause) { _pause = pause; } + + /** implements the callback*/ + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + protected: float _angular_velocity; @@ -38,6 +41,7 @@ class OSGUTIL_EXPORT TransformCallback : public osg::NodeCallback int _previousTraversalNumber; double _previousTime; + bool _pause; }; diff --git a/src/osg/AnimationPath.cpp b/src/osg/AnimationPath.cpp index 85237ad9e..6fd073bb0 100644 --- a/src/osg/AnimationPath.cpp +++ b/src/osg/AnimationPath.cpp @@ -82,30 +82,72 @@ bool AnimationPath::getInterpolatedControlPoint(double time,ControlPoint& contro } +void AnimationPath::read(std::istream& in) +{ + while (!in.eof()) + { + double time; + osg::Vec3 position; + osg::Quat rotation; + in >> time >> position.x() >> position.y() >> position.z() >> rotation.x() >> rotation.y() >> rotation.z() >> rotation.w(); + if(!in.eof()) + insert(time,osg::AnimationPath::ControlPoint(position,rotation)); + } +} + +void AnimationPath::write(std::ostream& fout) +{ + const TimeControlPointMap& tcpm = getTimeControlPointMap(); + for(TimeControlPointMap::const_iterator tcpmitr=tcpm.begin(); + tcpmitr!=tcpm.end(); + ++tcpmitr) + { + const ControlPoint& cp = tcpmitr->second; + fout<first<<" "<getFrameStamp()) { double time = nv->getFrameStamp()->getReferenceTime(); - if (_firstTime==0.0) _firstTime = time; - - _animationTime = ((time-_firstTime)-_timeOffset)*_timeMultiplier; - - AnimationPath::ControlPoint cp; - if (_animationPath->getInterpolatedControlPoint(_animationTime,cp)) + _latestTime = time; + + if (!_pause) { - AnimationPathCallbackVisitor apcv(cp); - node->accept(apcv); + if (_firstTime==0.0) _firstTime = time; + update(*node); } - } - + // must call any nested node callbacks and continue subgraph traversal. NodeCallback::traverse(node,nv); } + +void AnimationPathCallback::update(osg::Node& node) +{ + double animationTime = ((_latestTime-_firstTime)-_timeOffset)*_timeMultiplier; + + AnimationPath::ControlPoint cp; + if (_animationPath->getInterpolatedControlPoint(animationTime,cp)) + { + AnimationPathCallbackVisitor apcv(cp,_useInverseMatrix); + node.accept(apcv); + } +} + + +void AnimationPathCallback::reset() +{ + _firstTime = _latestTime; + _pauseTime = _latestTime; +} + +void AnimationPathCallback::setPause(bool pause) +{ + if (_pause==pause) + { + return; + } + + _pause = pause; + if (_pause) + { + _pauseTime = _latestTime; + } + else + { + _firstTime += (_latestTime-_pauseTime); + } +} diff --git a/src/osgDB/Registry.cpp b/src/osgDB/Registry.cpp index 52ee52119..465262b13 100644 --- a/src/osgDB/Registry.cpp +++ b/src/osgDB/Registry.cpp @@ -91,7 +91,7 @@ Registry::Registry() // comment out because it was causing problems under OSX - causing it to crash osgconv when constucting ostream in osg::notify(). // notify(INFO) << "Constructing osg::Registry"<> time >> position.x() >> position.y() >> position.z() >> rotation.x() >> rotation.y() >> rotation.z() >> rotation.w(); - if(!in.eof()) - _animationPath->insert(time,osg::AnimationPath::ControlPoint(position,rotation)); - } + _animationPath->read(in); in.close(); diff --git a/src/osgPlugins/ive/AnimationPathCallback.cpp b/src/osgPlugins/ive/AnimationPathCallback.cpp index ebf80fef5..3b5465e2f 100644 --- a/src/osgPlugins/ive/AnimationPathCallback.cpp +++ b/src/osgPlugins/ive/AnimationPathCallback.cpp @@ -34,7 +34,7 @@ void AnimationPathCallback::write(DataOutputStream* out){ out->writeDouble(_timeOffset); out->writeDouble(_timeMultiplier); out->writeDouble(_firstTime); - out->writeDouble(_animationTime); + out->writeDouble(_pauseTime); // Write animationpath if any if(getAnimationPath()) { @@ -64,7 +64,7 @@ void AnimationPathCallback::read(DataInputStream* in){ _timeOffset = in->readDouble(); _timeMultiplier = in->readDouble(); _firstTime = in->readDouble(); - _animationTime = in->readDouble(); + _pauseTime = in->readDouble(); // Read animationpath if any if(in->readInt()) { diff --git a/src/osgProducer/ViewerEventHandler.cpp b/src/osgProducer/ViewerEventHandler.cpp index 145cf00a1..cbdbdf433 100644 --- a/src/osgProducer/ViewerEventHandler.cpp +++ b/src/osgProducer/ViewerEventHandler.cpp @@ -829,14 +829,7 @@ bool ViewerEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActio if (viewer->getAnimationPath()) { std::ofstream fout("saved_animation.path"); - const osg::AnimationPath::TimeControlPointMap& tcpm = viewer->getAnimationPath()->getTimeControlPointMap(); - for(osg::AnimationPath::TimeControlPointMap::const_iterator tcpmitr=tcpm.begin(); - tcpmitr!=tcpm.end(); - ++tcpmitr) - { - const osg::AnimationPath::ControlPoint& cp = tcpmitr->second; - fout<first<<" "<getAnimationPath()->write(fout); fout.close(); osg::notify(osg::NOTICE) << "Saved camera animation to 'saved_animation.path'"<< std::endl; diff --git a/src/osgUtil/TransformCallback.cpp b/src/osgUtil/TransformCallback.cpp index 62ca74f47..66f00cfcc 100644 --- a/src/osgUtil/TransformCallback.cpp +++ b/src/osgUtil/TransformCallback.cpp @@ -24,6 +24,8 @@ TransformCallback::TransformCallback(const osg::Vec3& pivot,const osg::Vec3& axi _previousTraversalNumber = -1; _previousTime = -1.0; + + _pause = false; } void TransformCallback::operator() (osg::Node* node, osg::NodeVisitor* nv) @@ -34,14 +36,14 @@ void TransformCallback::operator() (osg::Node* node, osg::NodeVisitor* nv) const osg::FrameStamp* fs = nv->getFrameStamp(); if (!fs) return; // not frame stamp, no handle on the time so can't move. - + double newTime = fs->getReferenceTime(); + // ensure that we do not operate on this node more than // once during this traversal. This is an issue since node // can be shared between multiple parents. - if (nv->getTraversalNumber()!=_previousTraversalNumber) + if (!_pause && nv->getTraversalNumber()!=_previousTraversalNumber) { - double newTime = fs->getReferenceTime(); float delta_angle = _angular_velocity*(newTime-_previousTime); osg::Matrix mat = osg::Matrix::translate(-_pivot)* @@ -53,8 +55,10 @@ void TransformCallback::operator() (osg::Node* node, osg::NodeVisitor* nv) transform->preMult(mat); _previousTraversalNumber = nv->getTraversalNumber(); - _previousTime = newTime; } + + _previousTime = newTime; + } // must call any nested node callbacks and continue subgraph traversal.