From f02ccbfc05aa4c2b6c8b61e11f7ae1f88b8c3894 Mon Sep 17 00:00:00 2001
From: buti <buti@bux.at>
Date: Tue, 26 Feb 2008 22:15:33 +0100
Subject: [PATCH] model-paging v0.1 (beta)

---
 simgear/scene/model/SGPagedLOD.cxx               |  145 ++++++++++++++++++++++
 simgear/scene/model/SGPagedLOD.hxx               |   42 ++++++
 simgear/scene/model/SGReaderWriterXML.cxx        |   90 +++++++++++++
 simgear/scene/model/SGReaderWriterXML.hxx        |   37 ++++++
 simgear/scene/model/SGReaderWriterXMLOptions.hxx |   84 +++++++++++++
 5 files changed, 398 insertions(+), 0 deletions(-)
 create mode 100644 simgear/scene/model/SGPagedLOD.cxx
 create mode 100644 simgear/scene/model/SGPagedLOD.hxx
 create mode 100644 simgear/scene/model/SGReaderWriterXML.cxx
 create mode 100644 simgear/scene/model/SGReaderWriterXML.hxx
 create mode 100644 simgear/scene/model/SGReaderWriterXMLOptions.hxx

diff --git a/simgear/scene/model/SGPagedLOD.cxx b/simgear/scene/model/SGPagedLOD.cxx
new file mode 100644
index 0000000..c03ec17
--- /dev/null
+++ b/simgear/scene/model/SGPagedLOD.cxx
@@ -0,0 +1,145 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
+ *
+ * This library is open source and may be redistributed and/or modified under
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * OpenSceneGraph Public License for more details.
+*/
+
+#include <osg/CullStack>
+#include <osg/Notify>
+#include <osgDB/DatabasePager>
+
+#include <algorithm>
+#include <SGPagedLOD.hxx>
+
+using namespace osg;
+
+SGPagedLOD::SGPagedLOD()
+{
+    _frameNumberOfLastTraversal = 0;
+    _centerMode = USER_DEFINED_CENTER;
+    _radius = -1;
+    _numChildrenThatCannotBeExpired = 0;
+}
+
+SGPagedLOD::SGPagedLOD(const SGPagedLOD& plod,const CopyOp& copyop):
+    osg::PagedLOD(plod, copyop),
+    _readerWriterOptions(plod._readerWriterOptions)
+{
+}
+
+void SGPagedLOD::traverse(osg::NodeVisitor& nv)
+{
+    // set the frame number of the traversal so that external nodes can find out how active this
+    // node is.
+    if (nv.getFrameStamp()) setFrameNumberOfLastTraversal(nv.getFrameStamp()->getFrameNumber());
+
+    double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
+    bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;
+
+    switch(nv.getTraversalMode())
+    {
+        case(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN):
+            std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
+            break;
+        case(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
+        {
+            float required_range = 0;
+            if (_rangeMode==DISTANCE_FROM_EYE_POINT)
+            {
+                required_range = nv.getDistanceToViewPoint(getCenter(),true);
+            }
+            else
+            {
+                osg::CullStack* cullStack = dynamic_cast<osg::CullStack*>(&nv);
+                if (cullStack && cullStack->getLODScale()>0.0f)
+                {
+                    required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale();
+                }
+                else
+                {
+                    // fallback to selecting the highest res tile by
+                    // finding out the max range
+                    for(unsigned int i=0;i<_rangeList.size();++i)
+                    {
+                        required_range = osg::maximum(required_range,_rangeList[i].first);
+                    }
+                }
+            }
+
+            int lastChildTraversed = -1;
+            bool needToLoadChild = false;
+            for(unsigned int i=0;i<_rangeList.size();++i)
+            {
+                if (_rangeList[i].first<=required_range && required_range<_rangeList[i].second)
+                {
+                    if (i<_children.size())
+                    {
+                        if (updateTimeStamp) _perRangeDataList[i]._timeStamp=timeStamp;
+
+                        _children[i]->accept(nv);
+                        lastChildTraversed = (int)i;
+                    }
+                    else
+                    {
+                        needToLoadChild = true;
+                    }
+                }
+            }
+
+            if (needToLoadChild)
+            {
+                unsigned int numChildren = _children.size();
+
+                // select the last valid child.
+                if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
+                {
+                    if (updateTimeStamp) _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
+                    _children[numChildren-1]->accept(nv);
+                }
+
+		osgDB::DatabasePager *dbp = dynamic_cast<osgDB::DatabasePager *>(nv.getDatabaseRequestHandler());
+		
+                // now request the loading of the next unloaded child.
+                if (dbp && numChildren<_perRangeDataList.size())
+                {
+                    // compute priority from where abouts in the required range the distance falls.
+                    float priority = (_rangeList[numChildren].second-required_range)/(_rangeList[numChildren].second-_rangeList[numChildren].first);
+
+                    // invert priority for PIXEL_SIZE_ON_SCREEN mode
+                    if(_rangeMode==PIXEL_SIZE_ON_SCREEN)
+                    {
+                        priority = -priority;
+                    }
+
+                    // modify the priority according to the child's priority offset and scale.
+                    priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale;
+
+                    if (_databasePath.empty())
+                    {
+                        dbp->requestNodeFile(_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp(), _readerWriterOptions.get());
+                    }
+                    else
+                    {
+                        // prepend the databasePath to the child's filename.
+                        dbp->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp(),_readerWriterOptions.get());
+                    }
+                }
+
+
+            }
+
+
+           break;
+        }
+        default:
+            break;
+    }
+}
+
diff --git a/simgear/scene/model/SGPagedLOD.hxx b/simgear/scene/model/SGPagedLOD.hxx
new file mode 100644
index 0000000..1398cf9
--- /dev/null
+++ b/simgear/scene/model/SGPagedLOD.hxx
@@ -0,0 +1,42 @@
+/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
+ *
+ * This library is open source and may be redistributed and/or modified under  
+ * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
+ * (at your option) any later version.  The full license is in LICENSE file
+ * included with this distribution, and on the openscenegraph.org website.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * OpenSceneGraph Public License for more details.
+*/
+
+#ifndef SGPAGEDLOD_HXX
+#define SGPAGEDLOD_HXX 1
+
+#include <osg/PagedLOD>
+#include <osgDB/ReaderWriter>
+
+class SGPagedLOD : public osg::PagedLOD
+{
+    public :
+    
+        SGPagedLOD();
+
+        /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
+        SGPagedLOD(const SGPagedLOD&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+        META_Node(osg, PagedLOD);
+        
+        virtual void traverse(osg::NodeVisitor& nv);
+
+	void setReaderWriterOptions(osgDB::ReaderWriter::Options *o)
+            { _readerWriterOptions=o; }
+
+    protected :
+    
+        virtual ~SGPagedLOD() {}
+        osg::ref_ptr<osgDB::ReaderWriter::Options> _readerWriterOptions;
+};
+
+#endif
diff --git a/simgear/scene/model/SGReaderWriterXML.cxx b/simgear/scene/model/SGReaderWriterXML.cxx
new file mode 100644
index 0000000..eca81d0
--- /dev/null
+++ b/simgear/scene/model/SGReaderWriterXML.cxx
@@ -0,0 +1,90 @@
+// Copyright (C) 2007 Tim Moore timoore@redhat.com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#include <osgDB/FileNameUtils>
+#include <osgDB/Registry>
+#include <simgear/scene/model/model.hxx>
+#include <simgear/scene/model/ModelRegistry.hxx>
+
+#include "SGReaderWriterXMLOptions.hxx"
+#include "SGReaderWriterXML.hxx"
+
+osg::Node *
+sgLoad3DModel_internal( const string &fg_root, const string &path,
+               SGPropertyNode *prop_root,
+               double sim_time_sec, osg::Node *(*load_panel)(SGPropertyNode *),
+               SGModelData *data,
+               const SGPath& externalTexturePath );
+
+using namespace simgear;
+
+const char* SGReaderWriterXML::className() const
+{
+    return "XML database reader";
+}
+
+bool SGReaderWriterXML::acceptsExtension(const std::string& extension) const
+{
+    return (osgDB::equalCaseInsensitive(extension, "xml"));
+}
+
+osgDB::ReaderWriter::ReadResult
+SGReaderWriterXML::readNode(const std::string& fileName,
+                            const osgDB::ReaderWriter::Options* options) const
+{
+    std::string ext = osgDB::getLowerCaseFileExtension(fileName);
+    if(!acceptsExtension(ext))
+        return ReadResult::FILE_NOT_HANDLED;
+
+    const SGReaderWriterXMLOptions* xmlOptions
+        = dynamic_cast<const SGReaderWriterXMLOptions*>(options);
+
+    string fg_root;
+    SGPropertyNode *prop_root=0;
+    osg::Node *(*load_panel)(SGPropertyNode *)=0;
+    SGModelData *model_data=0;
+    SGPath externalTexturePath;
+
+    if (xmlOptions) {
+        fg_root = xmlOptions->getFGRoot();
+        cerr << "fg_root=" << fg_root << endl;
+        prop_root = xmlOptions->getPropRoot();
+
+        load_panel = xmlOptions->getLoadPanel();
+        model_data = xmlOptions->getModelData();
+        externalTexturePath = xmlOptions->getExternalTexturePath();
+    }
+
+    osg::Node *result=
+        sgLoad3DModel_internal(fg_root, fileName, prop_root, 0.0, load_panel,
+            model_data, externalTexturePath);
+/*
+    osg::Node* result = SGLoadBTG(fileName, matlib, calcLights,
+                                  useRandomObjects,
+                                  useRandomVegetation);
+*/
+    if (result)
+        return result;
+    else
+        return ReadResult::FILE_NOT_HANDLED;
+}
+
+namespace
+{
+ModelRegistryCallbackProxy<LoadOnlyCallback> g_xmlCallbackProxy("xml");
+}
+
diff --git a/simgear/scene/model/SGReaderWriterXML.hxx b/simgear/scene/model/SGReaderWriterXML.hxx
new file mode 100644
index 0000000..e7ce8b7
--- /dev/null
+++ b/simgear/scene/model/SGReaderWriterXML.hxx
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006-2007 Tim Moore timoore@redhat.com
+ * Copyright (C) 2008 Till Busch buti@bux.at
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+#ifndef SGREADERWRITERXML_HXX
+#define SGREADERWRITERXML_HXX 1
+#include <osgDB/Registry>
+
+class SGReaderWriterXML : public osgDB::ReaderWriter {
+public:
+    virtual const char* className() const;
+ 
+    virtual bool acceptsExtension(const std::string& extension) const;
+
+    virtual ReadResult readNode(const std::string& fileName,
+                                const osgDB::ReaderWriter::Options* options)
+        const;
+};
+
+#endif
+    
diff --git a/simgear/scene/model/SGReaderWriterXMLOptions.hxx b/simgear/scene/model/SGReaderWriterXMLOptions.hxx
new file mode 100644
index 0000000..311a226
--- /dev/null
+++ b/simgear/scene/model/SGReaderWriterXMLOptions.hxx
@@ -0,0 +1,84 @@
+// Copyright (C) 2007 Tim Moore timoore@redhat.com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+#ifndef SGREADERWRITERXMLOPTIONS_HXX
+#define SGREADERWRITERXMLOPTIONS_HXX 1
+
+#include <osgDB/ReaderWriter>
+#include <simgear/misc/sg_path.hxx>
+
+class SGPropertyNode;
+class SGModelData;
+
+class SGReaderWriterXMLOptions : public osgDB::ReaderWriter::Options {
+public:
+    SGReaderWriterXMLOptions():
+        osgDB::ReaderWriter::Options(),
+        _prop_root(0),
+        _load_panel(0),
+        _model_data(0)
+    {}
+
+    SGReaderWriterXMLOptions(const std::string& str):
+        osgDB::ReaderWriter::Options(str),
+        _prop_root(0),
+        _load_panel(0),
+        _model_data(0),
+        _external_texture_path(0)
+    {}
+    
+    SGReaderWriterXMLOptions(const SGReaderWriterXMLOptions& options,
+            const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
+        osgDB::ReaderWriter::Options(options, copyop),
+        _fg_root(options._fg_root),
+        _prop_root(options._prop_root),
+        _load_panel(options._load_panel),
+        _model_data(options._model_data),
+        _external_texture_path(options._external_texture_path)
+    {
+    }
+
+/*
+‘getFGRoot’
+SGReaderWriterXML.cxx:56: error: ‘const class SGReaderWriterXMLOptions’ has no member named ‘getPropRoot’
+SGReaderWriterXML.cxx:58: error: ‘const class SGReaderWriterXMLOptions’ has no member named ‘getLoadPanel’
+SGReaderWriterXML.cxx:59: error: ‘const class SGReaderWriterXMLOptions’ has no member named ‘getModelData’
+SGReaderWriterXML.cxx:60: error: ‘const class SGReaderWriterXMLOptions’ has no member named ‘getExternalTexturePath’
+*/
+    typedef osg::Node *(*panel_func)(SGPropertyNode *);
+
+    std::string getFGRoot() const { return _fg_root; }
+    SGPropertyNode *getPropRoot() const { return _prop_root; }
+    panel_func getLoadPanel() const { return _load_panel; }
+    SGModelData *getModelData() const { return _model_data; }
+    const SGPath &getExternalTexturePath() const { return _external_texture_path; }
+
+    void setFGRoot(const std::string& p) { _fg_root=p; }
+    void setPropRoot(SGPropertyNode *p) { _prop_root=p; }
+    void setLoadPanel(panel_func pf) { _load_panel=pf; }
+    void setModelData(SGModelData *d) { _model_data=d;}
+    void setExternalTexturePath(const SGPath &p) { _external_texture_path=p;}
+
+protected:
+    virtual ~SGReaderWriterXMLOptions() {}
+
+    std::string _fg_root;
+    SGPropertyNode *_prop_root;
+    osg::Node *(*_load_panel)(SGPropertyNode *);
+    SGModelData *_model_data;
+    SGPath _external_texture_path;
+};
+#endif
-- 
1.5.2.5


