Index: /OpenSceneGraph/trunk/applications/present3D/ReaderWriterPaths.cpp
===================================================================
--- /OpenSceneGraph/trunk/applications/present3D/ReaderWriterPaths.cpp (revision 10207)
+++ /OpenSceneGraph/trunk/applications/present3D/ReaderWriterPaths.cpp (revision 10207)
@@ -0,0 +1,252 @@
+/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield 
+ *
+ * This software is open source and may be redistributed and/or modified under  
+ * the terms of the GNU General Public License (GPL) version 2.0.
+ * The full license is in LICENSE.txt file included with this distribution,.
+ * 
+ * This software 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 
+ * include LICENSE.txt for more details.
+*/
+
+#include <osg/Notify>
+#include <osg/io_utils>
+
+#include <osgDB/ReaderWriter>
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+#include <osgDB/Registry>
+
+#include <osgWidget/PdfReader>
+
+#include "SlideShowConstructor.h"
+#include "AnimationMaterial.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <osgDB/XmlParser>
+
+#include <sstream>
+#include <iostream>
+
+
+/**
+ * OpenSceneGraph plugin wrapper/converter.
+ */
+class ReaderWriterPaths : public osgDB::ReaderWriter
+{
+public:
+    ReaderWriterPaths()
+    {
+        supportsExtension("material","Material animation Ascii file format");
+        supportsExtension("path","Animation path Ascii file format");
+        supportsExtension("pivot_path","Animation pivot path Ascii file format");
+        supportsExtension("rotation_path","Animation rotation path Ascii file format");
+    }
+    
+    virtual const char* className() const
+    {
+        return "Path Reader/Writer";
+    }
+
+    virtual bool acceptsExtension(const std::string& extension) const
+    { 
+        return osgDB::equalCaseInsensitive(extension,"material") ||
+               osgDB::equalCaseInsensitive(extension,"path") ||
+               osgDB::equalCaseInsensitive(extension,"pivot_path") ||
+               osgDB::equalCaseInsensitive(extension,"rotation_path");
+    }
+
+    virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& fileName, const osgDB::Options* options) const;
+
+    virtual osgDB::ReaderWriter::ReadResult readObject(std::istream& fin, const osgDB::Options* options) const;
+
+    virtual osgDB::ReaderWriter::ReadResult read_material(std::istream& fin, const osgDB::Options* options) const;
+    virtual osgDB::ReaderWriter::ReadResult read_path(std::istream& fin, const osgDB::Options* options) const;
+    virtual osgDB::ReaderWriter::ReadResult read_pivot_path(std::istream& fin, const osgDB::Options* options) const;
+    virtual osgDB::ReaderWriter::ReadResult read_rotation_path(std::istream& fin, const osgDB::Options* options) const;
+};
+
+// Register with Registry to instantiate the above reader/writer.
+osgDB::RegisterReaderWriterProxy<ReaderWriterPaths> g_readerWriter_PathsL_Proxy;
+
+osgDB::ReaderWriter::ReadResult ReaderWriterPaths::readObject(const std::string& file, const osgDB::Options* options) const
+{
+
+
+    std::string ext = osgDB::getLowerCaseFileExtension(file);
+    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
+
+    osg::notify(osg::INFO)<<"ReaderWriterPaths::readObject("<<file<<")"<<std::endl;
+
+    std::string fileName = osgDB::findDataFile( file, options );
+    if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
+
+    osg::notify(osg::INFO)<<"  Found path file :"<<fileName<<std::endl;
+
+    // code for setting up the database path so that internally referenced file are searched for on relative paths.
+    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
+    local_opt->setPluginStringData("filename",fileName);
+
+    std::ifstream input(fileName.c_str());
+
+    return readObject(input, local_opt);
+}
+
+osgDB::ReaderWriter::ReadResult ReaderWriterPaths::readObject(std::istream& fin, const osgDB::Options* options) const
+{
+    osg::notify(osg::INFO)<<"ReaderWriterPaths::readObject(std::istream& fin"<<std::endl;
+
+    if (!options) return ReadResult::FILE_NOT_HANDLED;
+    if (!fin) return ReadResult::ERROR_IN_READING_FILE;
+
+
+    std::string filename = options->getPluginStringData("filename");
+
+    std::string ext = osgDB::getLowerCaseFileExtension(filename);
+
+    osg::notify(osg::INFO)<<"   filename found in options: "<<filename<<"  extension="<<ext<<std::endl;
+
+
+    if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
+
+
+    if      (ext=="path") return read_path(fin, options);
+    else if (ext=="material") return read_material(fin, options);
+    else if (ext=="pivot_path") return read_pivot_path(fin, options);
+    else if (ext=="rotation_path") return read_rotation_path(fin, options);
+
+    return ReadResult::FILE_NOT_HANDLED;
+}
+
+osgDB::ReaderWriter::ReadResult ReaderWriterPaths::read_material(std::istream& fin, const osgDB::Options* options) const
+{
+    osg::ref_ptr<ss3d::AnimationMaterial> animationMaterial = new ss3d::AnimationMaterial;
+    animationMaterial->read(fin);
+
+    return animationMaterial.get();
+}
+
+osgDB::ReaderWriter::ReadResult ReaderWriterPaths::read_path(std::istream& fin, const osgDB::Options* options) const
+{
+    osg::ref_ptr<osg::AnimationPath> animation = new osg::AnimationPath;
+    animation->read(fin);
+    return animation.get();
+}
+
+osgDB::ReaderWriter::ReadResult ReaderWriterPaths::read_pivot_path(std::istream& fin, const osgDB::Options* options) const
+{
+    osg::ref_ptr<osg::AnimationPath> animation = new osg::AnimationPath;
+
+    while (!fin.eof())
+    {
+        double time;
+        osg::Vec3 pivot;
+        osg::Vec3 position;
+        float scale;
+        osg::Quat rotation;
+        fin >> time >> pivot.x() >> pivot.y() >> pivot.z() >> position.x() >> position.y() >> position.z() >> rotation.x() >> rotation.y() >> rotation.z() >> rotation.w() >> scale;
+        if(!fin.eof())
+        {
+            osg::Matrix SR = osg::Matrix::scale(scale,scale,scale)*
+                                osg::Matrixf::rotate(rotation);
+
+            osg::Matrix invSR;
+            invSR.invert(SR);
+
+            position += (invSR*pivot)*SR;
+
+            animation->insert(time,osg::AnimationPath::ControlPoint(position,rotation,osg::Vec3(scale,scale,scale)));
+        }
+    }
+
+    return animation.get();
+}
+
+struct RotationPathData
+{
+    RotationPathData():
+        time(0.0),
+        scale(1.0f),
+        azim(0.0f),
+        elevation(0.0f) {}
+
+    double time;
+    osg::Vec3 pivot;
+    osg::Vec3 position;
+    float scale;
+    float azim;
+    float elevation;
+
+    void addToPath(osg::AnimationPath* animation) const
+    {
+        osg::Quat Rx, Rz, rotation;
+
+        Rx.makeRotate(osg::DegreesToRadians(elevation),1.0f,0.0f,0.0f);
+        Rz.makeRotate(osg::DegreesToRadians(azim),0.0f,0.0f,1.0f);
+        rotation = Rz * Rx; // note, I believe this is the wrong way round, but I had to put it in this order to fix the Quat properly.
+
+        osg::Matrix SR = osg::Matrix::scale(scale,scale,scale)*
+                         osg::Matrixf::rotate(rotation);
+
+        osg::Matrix invSR;
+        invSR.invert(SR);
+
+        osg::Vec3 local_position = position + (invSR*pivot)*SR;
+
+        animation->insert(time,osg::AnimationPath::ControlPoint(local_position,rotation,osg::Vec3(scale,scale,scale)));
+    }
+
+};
+
+osgDB::ReaderWriter::ReadResult ReaderWriterPaths::read_rotation_path(std::istream& fin, const osgDB::Options* options) const
+{
+    osg::ref_ptr<osg::AnimationPath> animation = new osg::AnimationPath;
+
+    RotationPathData prevValue;
+    bool first = true;
+    while (!fin.eof())
+    {
+        RotationPathData currValue;
+        fin >> currValue.time >> currValue.pivot.x() >> currValue.pivot.y() >> currValue.pivot.z() >> currValue.position.x() >> currValue.position.y() >> currValue.position.z() >> currValue.azim >> currValue.elevation >> currValue.scale;
+
+        if(!fin.eof())
+        {
+
+            if (!first)
+            {
+
+                unsigned int num = 20;
+                float dr = 1.0f/(float)num;
+                float r=dr;
+                for(unsigned int i=0;
+                    i<num;
+                    ++i, r+=dr)
+                {
+                    RotationPathData localValue;
+                    localValue.time = currValue.time *r + prevValue.time * (1.0f-r);
+                    localValue.pivot = currValue.pivot *r + prevValue.pivot * (1.0f-r);
+                    localValue.position = currValue.position *r + prevValue.position * (1.0f-r);
+                    localValue.scale = currValue.scale *r + prevValue.scale * (1.0f-r);
+                    localValue.azim = currValue.azim *r + prevValue.azim * (1.0f-r);
+                    localValue.elevation = currValue.elevation *r + prevValue.elevation * (1.0f-r);
+
+                    localValue.addToPath(animation);
+                }
+            }
+            else
+            {
+                currValue.addToPath(animation);
+            }
+            prevValue = currValue;
+            first = false;
+        }
+
+    }
+    osg::notify(osg::NOTICE)<<"finished"<<std::endl;
+
+    return animation.get();
+}
Index: /OpenSceneGraph/trunk/applications/present3D/SlideEventHandler.cpp
===================================================================
--- /OpenSceneGraph/trunk/applications/present3D/SlideEventHandler.cpp (revision 10132)
+++ /OpenSceneGraph/trunk/applications/present3D/SlideEventHandler.cpp (revision 10207)
@@ -137,42 +137,42 @@
     virtual void setPause(bool pause)
     {
-	osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
-	osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
-	ss3d::AnimationMaterialCallback* amc = dynamic_cast<ss3d::AnimationMaterialCallback*>(_callback.get());
-	if (apc)
-	{
+        osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
+        osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
+        ss3d::AnimationMaterialCallback* amc = dynamic_cast<ss3d::AnimationMaterialCallback*>(_callback.get());
+        if (apc)
+        {
             osg::notify(osg::INFO)<<"apc->setPause("<<pause<<")"<<std::endl;
             apc->setPause(pause);
-	}
-	if (tc)
-	{
+        }
+        if (tc)
+        {
             osg::notify(osg::INFO)<<"tc->setPause("<<pause<<")"<<std::endl;
             tc->setPause(pause);
-	}
-	if (amc)
-	{
+        }
+        if (amc)
+        {
             osg::notify(osg::INFO)<<"amc->setPause("<<pause<<")"<<std::endl;
             amc->setPause(pause);
-	}
+        }
     }
 
     virtual void reset()
     {
-	osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
-	osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
-	ss3d::AnimationMaterialCallback* amc = dynamic_cast<ss3d::AnimationMaterialCallback*>(_callback.get());
-	if (apc)
-	{
+        osg::AnimationPathCallback* apc = dynamic_cast<osg::AnimationPathCallback*>(_callback.get());
+        osgUtil::TransformCallback* tc = dynamic_cast<osgUtil::TransformCallback*>(_callback.get());
+        ss3d::AnimationMaterialCallback* amc = dynamic_cast<ss3d::AnimationMaterialCallback*>(_callback.get());
+        if (apc)
+        {
             apc->reset();
             apc->update(*_node);
-	}
-	if (tc)
-	{
-	}
-	if (amc)
-	{
+        }
+        if (tc)
+        {
+        }
+        if (amc)
+        {
             amc->reset();
             amc->update(*_node);
-	}
+        }
     }
 
@@ -221,5 +221,5 @@
                 int result = system(itr->c_str());
 
-	        osg::notify(osg::INFO)<<"system("<<*itr<<") result "<<result<<std::endl;
+                osg::notify(osg::INFO)<<"system("<<*itr<<") result "<<result<<std::endl;
 
                 double timeForRun = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
@@ -267,13 +267,13 @@
         osg::NodeVisitor(tm),
         _operatorList(operatorList) {}
-		
-    void apply(osg::Node& node)    
-    {
-    	if (node.getStateSet()) process(node.getStateSet());
-
-	if (node.getUpdateCallback())
-	{
+
+    void apply(osg::Node& node)
+    {
+        if (node.getStateSet()) process(node.getStateSet());
+
+        if (node.getUpdateCallback())
+        {
             _operatorList.insert(new CallbackOperator(&node, node.getUpdateCallback()));
-	}
+        }
 
         LayerAttributes* la = dynamic_cast<LayerAttributes*>(node.getUserData());
@@ -282,5 +282,5 @@
             _operatorList.insert(new LayerAttributesOperator(&node, la));
         }
-        
+
         traverse(node);
     }
@@ -289,5 +289,4 @@
     {
         apply((osg::Node&)node);
-        
         for(unsigned int i=0;i<node.getNumDrawables();++i)
         {
@@ -309,6 +308,6 @@
             }
         }
-    }	
-    
+    }
+
     ActiveOperators::OperatorList& _operatorList;
 };
Index: /OpenSceneGraph/trunk/applications/present3D/ReaderWriterP3D.cpp
===================================================================
--- /OpenSceneGraph/trunk/applications/present3D/ReaderWriterP3D.cpp (revision 10125)
+++ /OpenSceneGraph/trunk/applications/present3D/ReaderWriterP3D.cpp (revision 10207)
@@ -114,5 +114,5 @@
     virtual ReadResult readNode(std::istream& fin, const Options* options) const;
 
-    ReadResult readNode(osgDB::XmlNode::Input& input, const osgDB::ReaderWriter::Options* options) const;
+    ReadResult readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const;
 
     void parseModel(osgPresentation::SlideShowConstructor& constructor, osgDB::XmlNode*cur) const;
@@ -871,8 +871,8 @@
         }
     }
-    
+
     if (!filenameLeft.empty() && !filenameRight.empty()) 
         constructor.addStereoImagePair(filenameLeft,imageDataLeft,
-				       filenameRight, imageDataRight,
+                                       filenameRight, imageDataRight,
                                        positionRead ? positionData : constructor.getImagePositionData());
 
@@ -1386,4 +1386,310 @@
 #include <iostream>
 
+
+struct MyFindFileCallback : public osgDB::FindFileCallback
+{
+    virtual std::string findDataFile(const std::string& filename, const osgDB::Options* options, osgDB::CaseSensitivity caseSensitivity)
+    {
+        osg::notify(osg::NOTICE)<<std::endl<<std::endl<<"find file "<<filename<<std::endl;
+
+        const osgDB::FilePathList& paths = options ? options->getDatabasePathList() : osgDB::getDataFilePathList();
+
+        for(osgDB::FilePathList::const_iterator itr = paths.begin();
+            itr != paths.end();
+            ++itr)
+        {
+            const std::string& path = *itr;
+            std::string newpath = osgDB::concatPaths(path, filename);
+            if (osgDB::containsServerAddress(path))
+            {
+                osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
+                osg::notify(osg::NOTICE)<<"  file on server "<<*itr<<", try path "<<newpath<<std::endl;
+                osg::notify(osg::NOTICE)<<"  we have curl rw= "<<rw<<std::endl;
+                if (rw && rw->fileExists(newpath, options))
+                {
+                    osg::notify(osg::NOTICE)<<"  FOUND on server "<<newpath<<std::endl;
+                    return newpath;
+                }
+            }
+            else
+            {
+                if(osgDB::fileExists(newpath))
+                {
+                    osg::notify(osg::NOTICE)<<" FOUND "<<newpath<<std::endl;
+                    return newpath;
+                }
+            }
+        }
+
+        return osgDB::Registry::instance()->findDataFileImplementation(filename, options, caseSensitivity);
+    }
+};
+
+class OSGDB_EXPORT MyReadFileCallback : public virtual osgDB::ReadFileCallback
+{
+    public:
+
+        osgDB::FilePathList _paths;
+
+        typedef std::map< std::string, osg::ref_ptr<osg::Object> >  ObjectCache;
+
+        enum ObjectType
+        {
+            OBJECT,
+            IMAGE,
+            HEIGHT_FIELD,
+            NODE,
+            SHADER
+        };
+
+        osgDB::ReaderWriter::ReadResult readLocal(ObjectType type, const std::string& filename, const osgDB::Options* options)
+        {
+            osg::notify(osg::INFO)<<"Trying local file "<<filename<<std::endl;
+
+            switch(type)
+            {
+                case(OBJECT): return osgDB::Registry::instance()->readObjectImplementation(filename,options);
+                case(IMAGE): return osgDB::Registry::instance()->readImageImplementation(filename,options);
+                case(HEIGHT_FIELD): return osgDB::Registry::instance()->readHeightFieldImplementation(filename,options);
+                case(NODE): return osgDB::Registry::instance()->readNodeImplementation(filename,options);
+                case(SHADER): return osgDB::Registry::instance()->readShaderImplementation(filename,options);
+            }
+            return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
+        }
+
+        
+        osgDB::ReaderWriter::ReadResult readFileCache(ObjectType type, const std::string& filename, const osgDB::Options* options)
+        {
+
+            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
+            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
+            if (!fileCache) return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
+
+            osg::notify(osg::INFO)<<"Trying fileCache "<<filename<<std::endl;
+
+            osgDB::ReaderWriter::ReadResult result;
+            if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
+            {
+                if (fileCache->existsInCache(filename))
+                {
+                    switch(type)
+                    {
+                        case(OBJECT):
+                            result = fileCache->readObject(filename, 0);
+                            break;
+                        case(IMAGE):
+                            result = fileCache->readImage(filename, 0);
+                            break;
+                        case(HEIGHT_FIELD):
+                            result = fileCache->readHeightField(filename, 0);
+                            break;
+                        case(NODE):
+                            result = fileCache->readNode(filename,0);
+                            break;
+                        case(SHADER):
+                            result = fileCache->readShader(filename, 0);
+                            break;
+                    }
+
+                    if (result.success())
+                    {
+                        osg::notify(osg::INFO)<<"   File read from FileCache."<<std::endl;
+                        return result;
+                    }
+
+                    osg::notify(osg::NOTICE)<<"   File in FileCache, but not successfully read"<<std::endl;
+                }
+                else
+                {
+                    osg::notify(osg::INFO)<<"   File does not exist in FileCache: "<<fileCache->createCacheFileName(filename)<<std::endl;
+                }
+            }
+
+            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
+
+        }
+
+        osgDB::ReaderWriter::ReadResult readServer(ObjectType type, const std::string& filename, const osgDB::Options* options)
+        {
+            osg::notify(osg::INFO)<<"Trying server file "<<filename<<std::endl;
+
+            osgDB::ReaderWriter::ReadResult result;
+            osgDB::ReaderWriter* rw = osgDB::Registry::instance()->getReaderWriterForExtension("curl");
+            if (!rw) return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
+
+            switch(type)
+            {
+                case(OBJECT):
+                    result = rw->readObject(filename,options);
+                    break;
+                case(IMAGE):
+                    result = rw->readImage(filename,options);
+                    break;
+                case(HEIGHT_FIELD):
+                    result = rw->readHeightField(filename,options);
+                    break;
+                case(NODE):
+                    result = rw->readNode(filename,options);
+                    break;
+                case(SHADER):
+                    result = rw->readShader(filename,options);
+                    break;
+            }
+
+            if (result.success())
+            {
+                osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
+                if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
+
+                if (fileCache && fileCache->isFileAppropriateForFileCache(filename))
+                {
+                    switch(type)
+                    {
+                        case(OBJECT):
+                            fileCache->writeObject(*result.getObject(),filename,options);
+                            break;
+                        case(IMAGE):
+                            result.getImage()->setFileName(filename);
+                            fileCache->writeImage(*result.getImage(),filename,options);
+                            break;
+                        case(HEIGHT_FIELD):
+                            fileCache->writeHeightField(*result.getHeightField(),filename,options);
+                            break;
+                        case(NODE):
+                            fileCache->writeNode(*result.getNode(),filename,options);
+                            break;
+                        case(SHADER):
+                            fileCache->writeShader(*result.getShader(),filename,options);
+                            break;
+                    }
+                }
+
+                return result;
+            }
+            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
+        }
+
+
+        osgDB::ReaderWriter::ReadResult read(const osgDB::FilePathList& filePathList, ObjectType type, const std::string& filename, const osgDB::Options* options, bool checkLocalFiles)
+        {
+            // go look in http paths
+            for(osgDB::FilePathList::const_iterator itr = filePathList.begin();
+                itr != filePathList.end();
+                ++itr)
+            {
+                const std::string& path = *itr;
+                std::string newpath = path.empty() ? filename : osgDB::concatPaths(path, filename);
+                osgDB::ReaderWriter::ReadResult result;
+                if (osgDB::containsServerAddress(newpath))
+                {
+                    if (checkLocalFiles) result = readFileCache(type, newpath, options);
+                    else result = readServer(type, newpath, options);
+                }
+                else if (checkLocalFiles && osgDB::fileExists(newpath))
+                {
+                    result = readLocal(type, newpath, options);
+                }
+
+                if (result.success())
+                {
+                    osg::notify(osg::INFO)<<"   inserting object into file cache "<<filename<<", "<<result.getObject()<<std::endl;
+                    _objectCache[filename] = result.getObject();
+
+                    options->setPluginStringData("filename",newpath);
+                    return result;
+                }
+            }
+            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
+        }
+
+        osgDB::ReaderWriter::ReadResult read(ObjectType type, const std::string& filename, const osgDB::Options* options)
+        {
+            osgDB::FileCache* fileCache = options ? options->getFileCache() : 0;
+            if (!fileCache) fileCache = osgDB::Registry::instance()->getFileCache();
+            if (fileCache && !fileCache->isFileAppropriateForFileCache(filename)) fileCache = 0;
+
+            osg::notify(osg::INFO)<<"reading file "<<filename<<std::endl;
+            ObjectCache::iterator itr = _objectCache.find(filename);
+            if (itr != _objectCache.end())
+            {
+                // object is in cache, just retrieve it.
+                if (itr->second.valid())
+                {
+                    osg::notify(osg::INFO)<<"File retrieved from cache, filename="<<filename<<std::endl;
+                    return itr->second.get();
+                }
+                else
+                {
+                    osg::notify(osg::INFO)<<"File failed to load previously, won't attempt a second time "<<filename<<std::endl;
+                    return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
+                }
+            }
+
+            {
+                bool checkLocalFiles = true;
+                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
+                if (result.success()) return result;
+
+                if (options && !(options->getDatabasePathList().empty()))
+                {
+                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
+                    if (result.success()) return result;
+                }
+
+                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
+                if (result.success()) return result;
+            }
+
+            {
+                bool checkLocalFiles = false;
+                osgDB::ReaderWriter::ReadResult result = read(_paths, type, filename, options, checkLocalFiles);
+                if (result.success()) return result;
+
+                if (options && !(options->getDatabasePathList().empty()))
+                {
+                    result = read(options->getDatabasePathList(), type, filename, options, checkLocalFiles);
+                    if (result.success()) return result;
+                }
+
+                result = read(osgDB::Registry::instance()->getDataFilePathList(), type, filename, options, checkLocalFiles);
+                if (result.success()) return result;
+            }
+
+            _objectCache[filename] = 0;
+
+            return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
+        }
+
+        virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& filename, const osgDB::Options* options)
+        {
+            return read(OBJECT, filename, options);
+        }
+
+        virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options)
+        {
+            return read(IMAGE, filename, options);
+        }
+
+        virtual osgDB::ReaderWriter::ReadResult readHeightField(const std::string& filename, const osgDB::Options* options)
+        {
+            return read(HEIGHT_FIELD, filename, options);
+        }
+
+        virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::Options* options)
+        {
+            return read(NODE, filename, options);
+        }
+
+        virtual osgDB::ReaderWriter::ReadResult readShader(const std::string& filename, const osgDB::Options* options)
+        {
+            return read(SHADER, filename, options);
+        }
+
+    protected:
+        virtual ~MyReadFileCallback() {}
+
+        ObjectCache _objectCache;
+};
+
 osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(const std::string& file,
                                                            const osgDB::ReaderWriter::Options* options) const
@@ -1394,4 +1700,10 @@
     std::string fileName = osgDB::findDataFile( file );
     if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
+
+    // code for setting up the database path so that internally referenced file are searched for on relative paths.
+    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
+    local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName));
+    //local_opt->setFindFileCallback(new MyFindFileCallback);
+    local_opt->setReadFileCallback(new MyReadFileCallback);
 
     osgDB::XmlNode::Input input;
@@ -1399,5 +1711,5 @@
     input.readAllDataIntoBuffer();
 
-    return readNode(input, options);
+    return readNode(input, local_opt);
 }
 
@@ -1408,8 +1720,12 @@
     input.readAllDataIntoBuffer();
 
-    return readNode(input, options);
-}
-
-osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, const osgDB::ReaderWriter::Options* options) const
+    osg::ref_ptr<osgDB::ReaderWriter::Options> local_opt = options ? static_cast<osgDB::ReaderWriter::Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
+    //local_opt->setFindFileCallback(new MyFindFileCallback);
+    local_opt->setReadFileCallback(new MyReadFileCallback);
+
+    return readNode(input, local_opt);
+}
+
+osgDB::ReaderWriter::ReadResult ReaderWriterP3DXML::readNode(osgDB::XmlNode::Input& input, osgDB::ReaderWriter::Options* options) const
 {
     bool readOnlyHoldingPage = options ? options->getOptionString()=="holding_slide" : false;
@@ -1423,4 +1739,7 @@
 
     doc->read(input);
+
+
+    osg::notify(osg::NOTICE)<<"P3D parsing"<<std::endl;
 
     // doc->write(std::cout);
@@ -1451,9 +1770,69 @@
     }
 
-    osgPresentation::SlideShowConstructor constructor;
+    osgPresentation::SlideShowConstructor constructor(options);
 
     osgDB::FilePathList previousPaths = osgDB::getDataFilePathList();
 
     bool readSlide = false;
+
+
+    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
+        itr != root->children.end();
+        ++itr)
+    {
+        osgDB::XmlNode* cur = itr->get();
+
+        if (cur->name=="env")
+        {
+            char* str = strdup(cur->contents.c_str());
+            osg::notify(osg::INFO)<<"putenv("<<str<<")"<<std::endl;
+            putenv(str);
+        }
+    }
+
+    std::string pathToPresentation;
+    MyReadFileCallback* readFileCallback = options ? dynamic_cast<MyReadFileCallback*>(options->getReadFileCallback()) : 0;
+
+    if (options && !(options->getDatabasePathList().empty()))
+    {
+        pathToPresentation = options->getDatabasePathList().front();
+
+       if (readFileCallback) readFileCallback->_paths.push_front(pathToPresentation);
+    }
+
+
+    for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
+        itr != root->children.end();
+        ++itr)
+    {
+        osgDB::XmlNode* cur = itr->get();
+
+        if (cur->name == "path")
+        {
+            std::string newpath = expandEnvVarsInFileName(cur->contents);
+
+            // now check if an absolue or http path
+            std::string::size_type colonPos = newpath.find_first_of(':');
+            std::string::size_type backslashPos = newpath.find_first_of('/');
+            std::string::size_type forwardslashPos = newpath.find_first_of('\\');
+            bool relativePath = colonPos == std::string::npos &&
+                                backslashPos != 0 &&
+                                forwardslashPos != 0;
+
+            if (relativePath && !pathToPresentation.empty())
+            {
+                newpath = osgDB::concatPaths(pathToPresentation, newpath);
+                osg::notify(osg::NOTICE)<<"relative path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
+            }
+            else
+            {
+                osg::notify(osg::NOTICE)<<"absolute path = "<<cur->contents<<", newpath="<<newpath<<std::endl;
+            }
+
+            if (readFileCallback) readFileCallback->_paths.push_back(newpath);
+            else options->getDatabasePathList().push_back(newpath);
+        }
+    }
+
 
     for(osgDB::XmlNode::Children::iterator itr = root->children.begin();
Index: /OpenSceneGraph/trunk/applications/present3D/SlideShowConstructor.cpp
===================================================================
--- /OpenSceneGraph/trunk/applications/present3D/SlideShowConstructor.cpp (revision 10117)
+++ /OpenSceneGraph/trunk/applications/present3D/SlideShowConstructor.cpp (revision 10207)
@@ -87,5 +87,6 @@
 };
 
-SlideShowConstructor::SlideShowConstructor()
+SlideShowConstructor::SlideShowConstructor(const osgDB::ReaderWriter::Options* options):
+    _options(options)
 {
     _slideDistance = osg::DisplaySettings::instance()->getScreenDistance();
@@ -322,5 +323,5 @@
 
         osg::ref_ptr<osg::Image> image = !_slideBackgroundImageFileName.empty() ?
-            osgDB::readImageFile(_slideBackgroundImageFileName) :
+            osgDB::readImageFile(_slideBackgroundImageFileName, _options.get()) :
             0;
 
@@ -636,21 +637,21 @@
     FindImageStreamsVisitor():
         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
-        
+
     virtual void apply(osg::Node& node)
     {
-	if (node.getStateSet())
-	{
-	     process(node.getStateSet());
-	}
-	traverse(node);
-    }    	
+        if (node.getStateSet())
+        {
+                process(node.getStateSet());
+        }
+        traverse(node);
+    }
 
     virtual void apply(osg::Geode& node)
     {
-	if (node.getStateSet())
-	{
-	     process(node.getStateSet());
-	}
-    	
+        if (node.getStateSet())
+        {
+                process(node.getStateSet());
+        }
+
         for(unsigned int i=0;i<node.getNumDrawables();++i)
         {
@@ -681,5 +682,5 @@
         }
     }
-    
+
 };
 
@@ -775,6 +776,7 @@
     if (!_currentLayer) addLayer();
 
-    osg::Image* image = osgDB::readImageFile(filename);
-    
+    osg::Image* image = osgDB::readImageFile(filename, _options.get());
+    if (image) recordOptionsFilePath(_options.get());
+
     if (!image) return;
 
@@ -889,6 +891,9 @@
 
 
-    osg::ref_ptr<osg::Image> imageLeft = osgDB::readImageFile(filenameLeft);
-    osg::ref_ptr<osg::Image> imageRight = (filenameRight==filenameLeft) ? imageLeft.get() : osgDB::readImageFile(filenameRight);
+    osg::ref_ptr<osg::Image> imageLeft = osgDB::readImageFile(filenameLeft, _options.get());
+    if (imageLeft.valid()) recordOptionsFilePath(_options.get());
+
+    osg::ref_ptr<osg::Image> imageRight = (filenameRight==filenameLeft) ? imageLeft.get() : osgDB::readImageFile(filenameRight, _options.get());
+    if (imageRight.valid()) recordOptionsFilePath(_options.get());
 
     if (!imageLeft && !imageRight) return;
@@ -962,5 +967,5 @@
         }
 
-	attachTexMat(pictureLeftStateSet, imageDataLeft, s, t, usedTextureRectangle);
+        attachTexMat(pictureLeftStateSet, imageDataLeft, s, t, usedTextureRectangle);
 
         pictureLeft->addDrawable(pictureLeftQuad);
@@ -980,5 +985,5 @@
         }
 
-	attachTexMat(pictureRightStateSet, imageDataRight, s, t, usedTextureRectangle);
+        attachTexMat(pictureRightStateSet, imageDataRight, s, t, usedTextureRectangle);
 
         pictureRight->addDrawable(pictureRightQuad);
@@ -1084,5 +1089,5 @@
     if (!_currentLayer) addLayer();
 
-    osg::Image* image = osgDB::readImageFile(filename);
+    osg::Image* image = osgDB::readImageFile(filename, _options.get());
     
     osg::notify(osg::INFO)<<"addInteractiveImage("<<filename<<") "<<image<<std::endl;
@@ -1203,5 +1208,5 @@
 std::string SlideShowConstructor::findFileAndRecordPath(const std::string& filename)
 {
-    std::string foundFile = osgDB::findDataFile(filename);
+    std::string foundFile = osgDB::findDataFile(filename, _options.get());
     if (foundFile.empty()) return foundFile;
 
@@ -1225,4 +1230,6 @@
 void SlideShowConstructor::addModel(const std::string& filename, const PositionData& positionData, const ModelData& modelData)
 {
+    osg::notify(osg::INFO)<<"SlideShowConstructor::addModel("<<filename<<")"<<std::endl;
+
     osg::Node* subgraph = 0;
 
@@ -1243,13 +1250,15 @@
     else
     {
-        std::string foundFile = findFileAndRecordPath(filename);
-        if (foundFile.empty()) return;
-
-        subgraph = osgDB::readNodeFile(foundFile);
-    }
-    
-    if (!subgraph) return;
-
-    addModel(subgraph, positionData, modelData);
+        subgraph = osgDB::readNodeFile(filename, _options.get());
+        if (subgraph) recordOptionsFilePath(_options.get());
+    }
+    
+    if (subgraph)
+    {
+        addModel(subgraph, positionData, modelData);
+    }
+
+    osg::notify(osg::INFO)<<"end of SlideShowConstructor::addModel("<<filename<<")"<<std::endl<<std::endl;
+
 }
 
@@ -1315,5 +1324,4 @@
         subgraph = attachMaterialAnimation(subgraph,positionData);
 
-
     // attached any rotation
     if (positionData.rotation[0]!=0.0)
@@ -1325,7 +1333,7 @@
                                            osg::Vec3(positionData.rotation[1],positionData.rotation[2],positionData.rotation[3]),
                                            osg::DegreesToRadians(positionData.rotation[0])));
-                                           
+
         animation_transform->addChild(subgraph);
-        
+
         osg::notify(osg::INFO)<<"Rotation Matrix "<<animation_transform->getMatrix()<<std::endl;
 
@@ -1339,7 +1347,7 @@
     {
         osg::notify(osg::INFO)<<"Have animation path for model"<<std::endl;
-        
+
         osg::Vec3 pivot = positionData.absolute_path ? osg::Vec3(0.0f,0.0f,0.0f) : subgraph->getBound().center();
-                
+
         osg::AnimationPath* path = animation->getAnimationPath();
         if (positionData.animation_name=="wheel" && (path->getTimeControlPointMap()).size()>=2)
@@ -1439,9 +1447,15 @@
     if (fileType == osgDB::DIRECTORY)
     {
-       image = osgDB::readImageFile(foundFile+".dicom");
+       image = osgDB::readImageFile(foundFile+".dicom", _options.get());
     }
     else if (fileType == osgDB::REGULAR_FILE)
     {
-        image = osgDB::readImageFile( foundFile );
+        image = osgDB::readImageFile( foundFile, _options.get() );
+    }
+    else
+    {
+        // not found image, so fallback to plguins/callbacks to find the model.
+        image = osgDB::readImageFile( filename, _options.get() );
+        if (image) recordOptionsFilePath(_options.get() );
     }
 
@@ -1562,5 +1576,6 @@
     if (!positionData.animation_material_filename.empty())
     {
-        std::string absolute_animation_file_path = osgDB::findDataFile(positionData.animation_material_filename);
+#if 0
+        std::string absolute_animation_file_path = osgDB::findDataFile(positionData.animation_material_filename, _options.get());
         if (!absolute_animation_file_path.empty())
         {        
@@ -1572,4 +1587,9 @@
             }
         }
+#else
+        osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(positionData.animation_material_filename, _options.get());
+        animationMaterial = dynamic_cast<ss3d::AnimationMaterial*>(object.get());
+#endif
+
     }
     else if (!positionData.fade.empty())
@@ -1617,201 +1637,40 @@
 }
 
-osg::AnimationPath* SlideShowConstructor::readPivotPath(const std::string& filename) const
-{
-    std::ifstream in(filename.c_str());
-    if (!in.eof())
-    {
-        osg::AnimationPath* animation = new osg::AnimationPath;
-
-        while (!in.eof())
-        {
-            double time;
-            osg::Vec3 pivot;
-            osg::Vec3 position;
-            float scale;
-            osg::Quat rotation;
-            in >> time >> pivot.x() >> pivot.y() >> pivot.z() >> position.x() >> position.y() >> position.z() >> rotation.x() >> rotation.y() >> rotation.z() >> rotation.w() >> scale;
-            if(!in.eof())
+osg::AnimationPathCallback* SlideShowConstructor::getAnimationPathCallback(const PositionData& positionData)
+{
+    if (!positionData.path.empty()) 
+    {
+        osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(positionData.path, _options.get());
+        osg::AnimationPath* animation = dynamic_cast<osg::AnimationPath*>(object.get());
+        if (animation)
+        {
+            if (positionData.frame==SlideShowConstructor::SLIDE)
             {
-                osg::Matrix SR = osg::Matrix::scale(scale,scale,scale)*
-                                 osg::Matrixf::rotate(rotation);
-            
-                osg::Matrix invSR;
-                invSR.invert(SR);
-                
-                position += (invSR*pivot)*SR;
-            
-                animation->insert(time,osg::AnimationPath::ControlPoint(position,rotation,osg::Vec3(scale,scale,scale)));
-            }
-        }
-        
-        return animation;
-    }
-    return 0;
-}
-
-struct RotationPathData
-{
-    RotationPathData():
-        time(0.0),
-        scale(1.0f),
-        azim(0.0f),
-        elevation(0.0f) {}
-
-    double time;
-    osg::Vec3 pivot;
-    osg::Vec3 position;
-    float scale;
-    float azim;
-    float elevation;
-
-    void addToPath(osg::AnimationPath* animation) const
-    {
-        osg::Quat Rx, Rz, rotation;
-
-        Rx.makeRotate(osg::DegreesToRadians(elevation),1.0f,0.0f,0.0f);
-        Rz.makeRotate(osg::DegreesToRadians(azim),0.0f,0.0f,1.0f);
-        rotation = Rz * Rx; // note, I believe this is the wrong way round, but I had to put it in this order to fix the Quat properly.
-
-        osg::Matrix SR = osg::Matrix::scale(scale,scale,scale)*
-                         osg::Matrixf::rotate(rotation);
-
-        osg::Matrix invSR;
-        invSR.invert(SR);
-
-        osg::Vec3 local_position = position + (invSR*pivot)*SR;
-
-        animation->insert(time,osg::AnimationPath::ControlPoint(local_position,rotation,osg::Vec3(scale,scale,scale)));
-    }
-    
-};
-osg::AnimationPath* SlideShowConstructor::readRotationPath(const std::string& filename) const
-{
-    std::ifstream in(filename.c_str());
-    if (!in.eof())
-    {
-        osg::AnimationPath* animation = new osg::AnimationPath;
-
-        RotationPathData prevValue;
-        bool first = true;
-        while (!in.eof())
-        {
-            RotationPathData currValue;
-            in >> currValue.time >> currValue.pivot.x() >> currValue.pivot.y() >> currValue.pivot.z() >> currValue.position.x() >> currValue.position.y() >> currValue.position.z() >> currValue.azim >> currValue.elevation >> currValue.scale;
-            if(!in.eof())
-            {
-            
-                if (!first)
+                osg::AnimationPath::TimeControlPointMap& controlPoints = animation->getTimeControlPointMap();
+                for(osg::AnimationPath::TimeControlPointMap::iterator itr=controlPoints.begin();
+                    itr!=controlPoints.end();
+                    ++itr)
                 {
-            
-                    unsigned int num = 20;
-                    float dr = 1.0f/(float)num;
-                    float r=dr;
-                    for(unsigned int i=0;
-                        i<num;
-                        ++i, r+=dr)
-                    {
-                        RotationPathData localValue;
-                        localValue.time = currValue.time *r + prevValue.time * (1.0f-r);
-                        localValue.pivot = currValue.pivot *r + prevValue.pivot * (1.0f-r);
-                        localValue.position = currValue.position *r + prevValue.position * (1.0f-r);
-                        localValue.scale = currValue.scale *r + prevValue.scale * (1.0f-r);
-                        localValue.azim = currValue.azim *r + prevValue.azim * (1.0f-r);
-                        localValue.elevation = currValue.elevation *r + prevValue.elevation * (1.0f-r);
-
-                        localValue.addToPath(animation);
-                    }
-                }
-                else
-                {
-                    currValue.addToPath(animation);
-                }
-                prevValue = currValue;
-                first = false;
-            }
-            
-        }
-        
-        return animation;
-    }
-    return 0;
-}
-
-osg::AnimationPathCallback* SlideShowConstructor::getAnimationPathCallback(const PositionData& positionData)
-{
-    if (!positionData.path.empty()) 
-    {
-        std::string absolute_animation_file_path = osgDB::findDataFile(positionData.path);
-        if (!absolute_animation_file_path.empty())
-        {        
-
-            osg::AnimationPath* animation = 0;
-
-            std::string extension = osgDB::getLowerCaseFileExtension(absolute_animation_file_path);
-            if (osgDB::equalCaseInsensitive(extension,"pivot_path"))
-            {
-                animation = readPivotPath(absolute_animation_file_path);
-            }
-            else if (osgDB::equalCaseInsensitive(extension,"rotation_path"))
-            {
-                animation = readRotationPath(absolute_animation_file_path);
-            }
-            else if (osgDB::equalCaseInsensitive(extension,"path"))
-            {            
-                std::ifstream animation_filestream(absolute_animation_file_path.c_str());
-                if (!animation_filestream.eof())
-                {
-                    animation = new osg::AnimationPath;
-                    animation->read(animation_filestream);
+                    osg::AnimationPath::ControlPoint& cp = itr->second;
+                    cp.setPosition(convertSlideToModel(cp.getPosition()+positionData.position));
                 }
             }
-            else
-            {
-                std::ifstream animation_filestream(absolute_animation_file_path.c_str());
-
-                osgDB::Input fr;
-                fr.attach(&animation_filestream);
-
-                static osg::ref_ptr<osg::AnimationPath> s_path = new osg::AnimationPath;
-                osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(absolute_animation_file_path); // fr.readObjectOfType(*s_path);
-                object = fr.readObject(); // fr.readObjectOfType(*s_path);
-                if (object.valid())
-                {
-                    animation = dynamic_cast<osg::AnimationPath*>(object.get());
-                }
-            }
-            
-            if (animation)
-            {
-                if (positionData.frame==SlideShowConstructor::SLIDE)
-                {
-                    osg::AnimationPath::TimeControlPointMap& controlPoints = animation->getTimeControlPointMap();
-                    for(osg::AnimationPath::TimeControlPointMap::iterator itr=controlPoints.begin();
-                        itr!=controlPoints.end();
-                        ++itr)
-                    {
-                        osg::AnimationPath::ControlPoint& cp = itr->second;
-                        cp.setPosition(convertSlideToModel(cp.getPosition()+positionData.position));
-                    }
-                }
-
-                animation->setLoopMode(positionData.path_loop_mode);
-
-                osg::AnimationPathCallback* apc = new osg::AnimationPathCallback(animation);
-                apc->setTimeOffset(positionData.path_time_offset);
-                apc->setTimeMultiplier(positionData.path_time_multiplier);
-                apc->setUseInverseMatrix(positionData.inverse_path);
-                
-                osg::notify(osg::INFO)<<"UseInverseMatrix "<<positionData.inverse_path<<std::endl;
-
-                return apc;
-                
-            }
-        }
+
+            animation->setLoopMode(positionData.path_loop_mode);
+
+            osg::AnimationPathCallback* apc = new osg::AnimationPathCallback(animation);
+            apc->setTimeOffset(positionData.path_time_offset);
+            apc->setTimeMultiplier(positionData.path_time_multiplier);
+            apc->setUseInverseMatrix(positionData.inverse_path);
+
+            osg::notify(osg::INFO)<<"UseInverseMatrix "<<positionData.inverse_path<<std::endl;
+
+            return apc;
+
+        }
+
     }
     return 0;
 }
-
-
 
 osg::Vec3 SlideShowConstructor::computePositionInModelCoords(const PositionData& positionData) const
@@ -1852,2 +1711,21 @@
     }
 }
+
+void SlideShowConstructor::recordOptionsFilePath(const osgDB::Options* options)
+{
+    if (options)
+    {
+        std::string filename_used = _options->getPluginStringData("filename");
+        std::string path = osgDB::getFilePath(filename_used);
+        if (!path.empty() && _filePathData.valid())
+        {
+            osgDB::FilePathList::iterator itr = std::find(_filePathData->filePathList.begin(),_filePathData->filePathList.end(),path);
+            if (itr==_filePathData->filePathList.end())
+            {
+                osg::notify(osg::INFO)<<"SlideShowConstructor::recordOptionsFilePath(..) - new path to record path="<<path<<" filename_used="<<filename_used<<std::endl;
+                _filePathData->filePathList.push_front(path);
+            }
+        }
+    }
+}
+
Index: /OpenSceneGraph/trunk/applications/present3D/SlideShowConstructor.h
===================================================================
--- /OpenSceneGraph/trunk/applications/present3D/SlideShowConstructor.h (revision 10117)
+++ /OpenSceneGraph/trunk/applications/present3D/SlideShowConstructor.h (revision 10207)
@@ -115,5 +115,5 @@
     struct PositionData
     {
-	PositionData():
+        PositionData():
             frame(SlideShowConstructor::SLIDE),
             position(0.0f,1.0f,0.0f),
@@ -123,5 +123,5 @@
             rotation(0.0f,0.0f,1.0f,0.0f),
             absolute_path(false),
-	    inverse_path(false),
+            inverse_path(false),
             path_time_offset(0.0),
             path_time_multiplier(1.0f),
@@ -156,21 +156,21 @@
         }
 
-	CoordinateFrame                         frame;
-	osg::Vec3                               position;
-	osg::Vec3                               scale;
-	osg::Vec4                               rotate;
-	osg::Vec4                               rotation;
+        CoordinateFrame                         frame;
+        osg::Vec3                               position;
+        osg::Vec3                               scale;
+        osg::Vec4                               rotate;
+        osg::Vec4                               rotation;
         std::string                             animation_name;
-	bool                                    absolute_path;
-	bool                                    inverse_path;
+        bool                                    absolute_path;
+        bool                                    inverse_path;
         double                                  path_time_offset;
         double                                  path_time_multiplier;
         osg::AnimationPath::LoopMode            path_loop_mode;
-	std::string                             path;
+        std::string                             path;
         double                                  animation_material_time_offset;
         double                                  animation_material_time_multiplier;
         ss3d::AnimationMaterial::LoopMode       animation_material_loop_mode;
-	std::string                             animation_material_filename;
-	std::string                             fade;
+        std::string                             animation_material_filename;
+        std::string                             fade;
     };
 
@@ -207,26 +207,26 @@
     struct FontData
     {
-    	FontData():
-	    font("fonts/arial.ttf"),
-	    layout(osgText::Text::LEFT_TO_RIGHT),
-	    alignment(osgText::Text::LEFT_BASE_LINE),
-	    axisAlignment(osgText::Text::XZ_PLANE),
-	    characterSize(0.04f),
-	    maximumHeight(1.0f),
-	    maximumWidth(1.0f),
-	    color(1.0f,1.0f,1.0f,1.0f) {}
-    
-    	std::string 	    	    	font;
-	osgText::Text::Layout 	        layout;
-	osgText::Text::AlignmentType 	alignment;
-	osgText::Text::AxisAlignment 	axisAlignment;
-	float	    	    	    	characterSize;
-	float	    	    	    	maximumHeight;
-	float	    	    	    	maximumWidth;
-	osg::Vec4   	    	    	color;
+        FontData():
+            font("fonts/arial.ttf"),
+            layout(osgText::Text::LEFT_TO_RIGHT),
+            alignment(osgText::Text::LEFT_BASE_LINE),
+            axisAlignment(osgText::Text::XZ_PLANE),
+            characterSize(0.04f),
+            maximumHeight(1.0f),
+            maximumWidth(1.0f),
+            color(1.0f,1.0f,1.0f,1.0f) {}
+
+        std::string                     font;
+        osgText::Text::Layout           layout;
+        osgText::Text::AlignmentType    alignment;
+        osgText::Text::AxisAlignment    axisAlignment;
+        float                           characterSize;
+        float                           maximumHeight;
+        float                           maximumWidth;
+        osg::Vec4                       color;
     };
 
 
-    SlideShowConstructor();
+    SlideShowConstructor(const osgDB::ReaderWriter::Options* options);
 
     void createPresentation();
@@ -347,7 +347,4 @@
     osg::Vec3 convertModelToSlide(const osg::Vec3& position) const;
 
-    osg::AnimationPath* readPivotPath(const std::string& filename) const;
-    osg::AnimationPath* readRotationPath(const std::string& filename) const;
-
     osg::AnimationPathCallback* getAnimationPathCallback(const PositionData& positionData);
     
@@ -361,4 +358,6 @@
         return stateset;
     }
+
+    osg::ref_ptr<const osgDB::ReaderWriter::Options> _options;
 
     osg::Vec3   _slideOrigin;
@@ -412,4 +411,6 @@
     std::string findFileAndRecordPath(const std::string& filename);
     
+    void recordOptionsFilePath(const osgDB::Options* options);
+
 };
 
Index: /OpenSceneGraph/trunk/applications/present3D/PickEventHandler.cpp
===================================================================
--- /OpenSceneGraph/trunk/applications/present3D/PickEventHandler.cpp (revision 10117)
+++ /OpenSceneGraph/trunk/applications/present3D/PickEventHandler.cpp (revision 10207)
@@ -131,5 +131,5 @@
             #endif
                 std::string filepath("OSG_FILE_PATH=");
-                
+
                 bool needDeliminator = false;
                 for(osgDB::FilePathList::iterator itr = paths.begin();
@@ -146,5 +146,5 @@
                 char* path = getenv("PATH");
                 if (path) binpath += path;
-                
+
                 needDeliminator = true;
                 for(osgDB::FilePathList::iterator itr = paths.begin();
@@ -159,8 +159,8 @@
 
             }
-#endif                                    
+#endif
             int result = system(_command.c_str());
-	    
-	    osg::notify(osg::INFO)<<"system("<<_command<<") result "<<result<<std::endl;
+
+            osg::notify(osg::INFO)<<"system("<<_command<<") result "<<result<<std::endl;
 
             break;
@@ -187,5 +187,5 @@
     {
         osg::notify(osg::NOTICE)<<"Requires jump "<<_relativeJump<<", "<<_slideNum<<", "<<_layerNum<<std::endl;
-        
+
         if (_relativeJump)
         {
@@ -198,5 +198,5 @@
                 newLayer = 0;
             }
-        
+
             osg::notify(osg::NOTICE)<<"   jump to "<<newSlide<<", "<<newLayer<<std::endl;
 
Index: /OpenSceneGraph/trunk/applications/present3D/CMakeLists.txt
===================================================================
--- /OpenSceneGraph/trunk/applications/present3D/CMakeLists.txt (revision 10165)
+++ /OpenSceneGraph/trunk/applications/present3D/CMakeLists.txt (revision 10207)
@@ -8,4 +8,5 @@
     present3D.cpp
     ReaderWriterP3D.cpp
+    ReaderWriterPaths.cpp
     ReadShowFile.cpp
     ShowEventHandler.cpp
