* 6378.165 but this is probably close enough */
#define SG_EARTH_RAD 6378.155
+// Maximum terrain elevation from sea level
+#define SG_MAX_ELEVATION_M 9000.0
// Earth parameters for WGS 84, taken from LaRCsim/ls_constants.h
#include "matmodel.hxx"
+using namespace simgear;
+
\f
////////////////////////////////////////////////////////////////////////
// Local static functions.
}
int
-SGMatModel::get_model_count( SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+SGMatModel::get_model_count( SGPropertyNode *prop_root )
{
- load_models( modellib, fg_root, prop_root, sim_time_sec );
+ load_models( prop_root );
return _models.size();
}
inline void
-SGMatModel::load_models ( SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+SGMatModel::load_models( SGPropertyNode *prop_root )
{
// Load model only on demand
if (!_models_loaded) {
for (unsigned int i = 0; i < _paths.size(); i++) {
- osg::Node *entity = modellib->load_model( fg_root, _paths[i],
- prop_root, sim_time_sec,
- /*cache_object*/ true );
+ osg::Node *entity = SGModelLib::loadModel(_paths[i], prop_root);
if (entity != 0) {
// FIXME: this stuff can be handled
// in the XML wrapper as well (at least,
osg::Node*
SGMatModel::get_model( int index,
- SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+ SGPropertyNode *prop_root )
{
- load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
+ load_models( prop_root ); // comment this out if preloading models
return _models[index].get();
}
osg::Node*
-SGMatModel::get_random_model( SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec )
+SGMatModel::get_random_model( SGPropertyNode *prop_root )
{
- load_models( modellib, fg_root, prop_root, sim_time_sec ); // comment this out if preloading models
+ load_models( prop_root ); // comment this out if preloading models
int nModels = _models.size();
int index = int(sg_random() * nModels);
if (index >= nModels)
class SGMatModelGroup;
-class SGModelLib;
/**
*
* @return The number of variant models.
*/
- int get_model_count( SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec );
+ int get_model_count( SGPropertyNode *prop_root );
/**
* @param index The index of the model.
* @return The model.
*/
- osg::Node *get_model( int index,
- SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec );
+ osg::Node *get_model( int index, SGPropertyNode *prop_root );
/**
*
* @return A randomly select model from the variants.
*/
- osg::Node *get_random_model( SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec );
+ osg::Node *get_random_model( SGPropertyNode *prop_root );
/**
* This class uses lazy loading so that models won't be held
* in memory for materials that are never referenced.
*/
- void load_models( SGModelLib *modellib,
- const string &fg_root,
- SGPropertyNode *prop_root,
- double sim_time_sec );
+ void load_models( SGPropertyNode *prop_root );
vector<string> _paths;
mutable vector<osg::ref_ptr<osg::Node> > _models;
--- /dev/null
+// 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.
+
+#include <osg/Transform>
+
+#include <simgear/debug/logstream.hxx>
+
+#include "CheckSceneryVisitor.hxx"
+#include "SGPagedLOD.hxx"
+
+using namespace simgear;
+
+CheckSceneryVisitor::CheckSceneryVisitor(osgDB::DatabasePager* dbp, osg::Vec3 &position, double range)
+:osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
+ osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
+_loaded(true), _position(position), _range(range), _dbp(dbp)
+{
+ _viewMatrices.push_back(osg::Matrix::identity());
+}
+
+void CheckSceneryVisitor::apply(osg::Node& node)
+{
+ traverse(node);
+}
+
+void CheckSceneryVisitor::apply(osg::PagedLOD& node)
+{
+ SGPagedLOD *sgplod = dynamic_cast<SGPagedLOD*>(&node);
+ if (sgplod) {
+ osg::Vec3 pos = sgplod->getCenter() * _viewMatrices.back();
+ double dist = (pos-_position).length();
+ if (dist < _range) {
+ if (sgplod->getNumChildren() < 1) {
+ // if the DatabasePager would load LODs while the splashscreen
+ // is there, we could just wait for the models to be loaded
+ // by only setting setLoaded(false) here
+ sgplod->forceLoad(_dbp);
+ setLoaded(false);
+ }
+ }
+ }
+ traverse(node);
+}
+
+void CheckSceneryVisitor::apply(osg::Transform &node)
+{
+ osg::Matrix currMatrix = _viewMatrices.back();
+ bool pushMatrix = node.computeLocalToWorldMatrix(currMatrix, this);
+
+ if (pushMatrix) {
+ _viewMatrices.push_back(currMatrix);
+ }
+ traverse(node);
+ if (pushMatrix) {
+ _viewMatrices.pop_back();
+ }
+}
--- /dev/null
+// 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 CHECKSCENERYVISITOR_HXX
+#define CHECKSCENERYVISITOR_HXX
+
+#include <osg/NodeVisitor>
+#include <osg/fast_back_stack>
+
+namespace osgDB {
+class DatabasePager;
+}
+
+
+namespace simgear
+{
+
+class SGPagedLOD;
+
+// Checks the scene graph for SGPagedLODs that are within range
+// (compared to postion) and injects them into the DatabasePager.
+// After visiting, isLoaded() returns true if all models in range
+// are available.
+
+class CheckSceneryVisitor : public osg::NodeVisitor
+{
+public:
+ CheckSceneryVisitor(osgDB::DatabasePager* dbp, osg::Vec3 &position, double range);
+
+ virtual void apply(osg::Node& node);
+ virtual void apply(osg::PagedLOD& node);
+ virtual void apply(osg::Transform& node);
+
+ bool isLoaded() const {
+ return _loaded;
+ }
+ void setLoaded(bool l) {
+ _loaded=l;
+ }
+ const osg::Vec3 &getPosition() const {
+ return _position;
+ }
+
+private:
+ osg::Vec3 _position;
+ double _range;
+ bool _loaded;
+ osgDB::DatabasePager* _dbp;
+
+ osg::fast_back_stack<osg::Matrix> _viewMatrices;
+};
+
+}
+
+#endif
persparam.hxx \
placement.hxx \
placementtrans.hxx \
+ CheckSceneryVisitor.hxx \
SGClipGroup.hxx \
SGMaterialAnimation.hxx \
SGOffsetTransform.hxx \
+ SGPagedLOD.hxx \
+ SGReaderWriterXML.hxx \
+ SGReaderWriterXMLOptions.hxx \
SGRotateTransform.hxx \
SGScaleTransform.hxx \
SGTranslateTransform.hxx
placement.cxx \
placementtrans.cxx \
shadanim.cxx \
+ CheckSceneryVisitor.cxx \
SGClipGroup.cxx \
SGMaterialAnimation.cxx \
SGOffsetTransform.cxx \
+ SGPagedLOD.cxx \
+ SGReaderWriterXML.cxx \
SGRotateTransform.cxx \
SGScaleTransform.cxx \
SGTranslateTransform.cxx
--- /dev/null
+// 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.
+
+#include <osgDB/ReadFile>
+
+#include <simgear/debug/logstream.hxx>
+
+#include "modellib.hxx"
+#include "SGReaderWriterXMLOptions.hxx"
+#include "SGPagedLOD.hxx"
+
+using namespace osg;
+using namespace simgear;
+
+SGPagedLOD::SGPagedLOD()
+ : PagedLOD()
+{
+}
+
+SGPagedLOD::~SGPagedLOD()
+{
+ //SG_LOG(SG_GENERAL, SG_ALERT, "SGPagedLOD::~SGPagedLOD(" << getFileName(0) << ")");
+}
+
+SGPagedLOD::SGPagedLOD(const SGPagedLOD& plod,const CopyOp& copyop)
+ : osg::PagedLOD(plod, copyop),
+ _readerWriterOptions(plod._readerWriterOptions)
+{
+}
+
+bool SGPagedLOD::addChild(osg::Node *child)
+{
+ //SG_LOG(SG_GENERAL, SG_ALERT, "SGPagedLOD::addChild(" << getFileName(getNumChildren()) << ")");
+ if (!PagedLOD::addChild(child))
+ return false;
+
+ // if the model was an .xml-file it will have UserData set
+ osg::ref_ptr<SGModelData> d = dynamic_cast<SGModelData*>(child->getUserData());
+ if (d.valid())
+ d->modelLoaded(getFileName(getNumChildren()-1), d->getProperties(), this);
+ else // this calls modelLoaded for non-xml models
+ {
+ SGReaderWriterXMLOptions *o=dynamic_cast<SGReaderWriterXMLOptions*>(_readerWriterOptions.get());
+ if(o)
+ {
+ d = o->getModelData();
+ if(d.valid())
+ d->modelLoaded(getFileName(getNumChildren()-1), 0, this);
+ }
+ }
+ return true;
+}
+
+void SGPagedLOD::forceLoad(osgDB::DatabasePager *dbp)
+{
+ //SG_LOG(SG_GENERAL, SG_ALERT, "SGPagedLOD::forceLoad(" << getFileName(getNumChildren()) << ")");
+ setTimeStamp(getNumChildren(),0);
+ double priority=1.0;
+ dbp->requestNodeFile(getFileName(getNumChildren()),this,priority,0, _readerWriterOptions.get());
+}
+
--- /dev/null
+// 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 SGPAGEDLOD_HXX
+#define SGPAGEDLOD_HXX 1
+
+#include <osg/PagedLOD>
+#include <osgDB/ReaderWriter>
+#include <simgear/props/props.hxx>
+
+namespace osgDB {
+class DatabasePager;
+}
+
+
+namespace simgear
+{
+
+class SGPagedLOD : public osg::PagedLOD
+{
+public:
+ SGPagedLOD();
+
+ SGPagedLOD(const SGPagedLOD&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
+
+ META_Node(osg, PagedLOD);
+
+ // virtual void traverse(osg::NodeVisitor& nv);
+ virtual void forceLoad(osgDB::DatabasePager* dbp);
+
+ // reimplemented to notify the loading through ModelData
+ bool addChild(osg::Node *child);
+
+ void setReaderWriterOptions(osgDB::ReaderWriter::Options *o) {
+ _readerWriterOptions=o;
+ _readerWriterOptions->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_NONE);
+ }
+
+ osgDB::ReaderWriter::Options * getReaderWriterOptions() {
+ return _readerWriterOptions.get();
+ }
+
+protected:
+ virtual ~SGPagedLOD();
+ osg::ref_ptr<osgDB::ReaderWriter::Options> _readerWriterOptions;
+ SGPropertyNode_ptr _props;
+};
+}
+#endif
--- /dev/null
+// Copyright (C) 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.
+//
+
+#include <osgDB/WriteFile>
+#include <osgDB/Registry>
+#include <osg/Switch>
+#include <osgDB/FileNameUtils>
+
+#include <simgear/compiler.h>
+#include <simgear/structure/exception.hxx>
+#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx>
+#include <simgear/props/condition.hxx>
+#include <simgear/scene/util/SGNodeMasks.hxx>
+
+#include "modellib.hxx"
+#include "SGPagedLOD.hxx"
+#include "SGReaderWriterXML.hxx"
+#include "SGReaderWriterXMLOptions.hxx"
+
+#include "animation.hxx"
+#include "particles.hxx"
+#include "model.hxx"
+
+#include "SGReaderWriterXMLOptions.hxx"
+#include "SGReaderWriterXML.hxx"
+
+using namespace simgear;
+
+osg::Node *
+sgLoad3DModel_internal(const string &path,
+ SGPropertyNode *prop_root,
+ SGModelData *data=0,
+ osg::Node *(*load_panel)(SGPropertyNode *) = 0);
+
+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
+{
+ // SG_LOG(SG_GENERAL, SG_ALERT, "SGReaderWriterXML::readNode(" << fileName << ")");
+
+ 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) {
+ prop_root = xmlOptions->getPropRoot();
+ load_panel = xmlOptions->getLoadPanel();
+ model_data = xmlOptions->getModelData();
+ }
+
+ fg_root=osgDB::Registry::instance()->getDataFilePathList().front();
+
+ osg::Node *result=0;
+
+ try {
+ result=sgLoad3DModel_internal(fileName, prop_root, model_data, load_panel);
+ } catch (const sg_throwable &t) {
+ SG_LOG(SG_INPUT, SG_ALERT, "Failed to load model: " << t.getFormattedMessage());
+ result=new osg::Node;
+ }
+ if (result)
+ return result;
+ else
+ return ReadResult::FILE_NOT_HANDLED;
+}
+
+class SGSwitchUpdateCallback : public osg::NodeCallback
+{
+public:
+ SGSwitchUpdateCallback(SGCondition* condition) :
+ mCondition(condition) {}
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
+ assert(dynamic_cast<osg::Switch*>(node));
+ osg::Switch* s = static_cast<osg::Switch*>(node);
+
+ if (mCondition && mCondition->test()) {
+ s->setAllChildrenOn();
+ // note, callback is responsible for scenegraph traversal so
+ // should always include call traverse(node,nv) to ensure
+ // that the rest of cullbacks and the scene graph are traversed.
+ traverse(node, nv);
+ } else
+ s->setAllChildrenOff();
+ }
+
+private:
+ SGSharedPtr<SGCondition> mCondition;
+};
+
+osg::Node *
+sgLoad3DModel_internal(const string &path,
+ SGPropertyNode *prop_root,
+ SGModelData *data,
+ osg::Node *(*load_panel)(SGPropertyNode *))
+{
+ string fg_root=osgDB::Registry::instance()->getDataFilePathList().front();
+ osg::ref_ptr<osg::Node> model;
+ osg::ref_ptr<osg::Group> group;
+ SGPropertyNode_ptr props = new SGPropertyNode;
+
+ // Load the 3D object itself
+ SGPath modelpath = path, texturepath = path;
+ if ( !ulIsAbsolutePathName( path.c_str() ) ) {
+ SGPath tmp = fg_root;
+ tmp.append(modelpath.str());
+ modelpath = texturepath = tmp;
+ }
+
+ // Check for an XML wrapper
+ if (modelpath.str().substr(modelpath.str().size() - 4, 4) == ".xml") {
+ try {
+ readProperties(modelpath.str(), props);
+ } catch (const sg_throwable &t) {
+ SG_LOG(SG_INPUT, SG_ALERT, "Failed to load xml: " << t.getFormattedMessage());
+ throw;
+ }
+ if (props->hasValue("/path")) {
+ modelpath = modelpath.dir();
+ modelpath.append(props->getStringValue("/path"));
+ if (props->hasValue("/texture-path")) {
+ texturepath = texturepath.dir();
+ texturepath.append(props->getStringValue("/texture-path"));
+ }
+ } else {
+ model = new osg::Node;
+ }
+ }
+
+ osg::ref_ptr<osgDB::ReaderWriter::Options> options
+ = new osgDB::ReaderWriter::Options(*osgDB::Registry::instance()
+ ->getOptions());
+
+ // Assume that textures are in
+ // the same location as the XML file.
+ if (!model) {
+ if (texturepath.extension() != "")
+ texturepath = texturepath.dir();
+
+ options->setDatabasePath(texturepath.str());
+ model = osgDB::readNodeFile(modelpath.str(), options.get());
+ if (model == 0)
+ throw sg_io_exception("Failed to load 3D model",
+ sg_location(modelpath.str()));
+ }
+
+ bool needTransform=false;
+ // Set up the alignment node if needed
+ SGPropertyNode *offsets = props->getNode("offsets", false);
+ if (offsets) {
+ needTransform=true;
+ osg::MatrixTransform *alignmainmodel = new osg::MatrixTransform;
+ osg::Matrix res_matrix;
+ res_matrix.makeRotate(
+ offsets->getFloatValue("pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 1, 0),
+ offsets->getFloatValue("roll-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(1, 0, 0),
+ offsets->getFloatValue("heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 0, 1));
+
+ osg::Matrix tmat;
+ tmat.makeTranslate(offsets->getFloatValue("x-m", 0.0),
+ offsets->getFloatValue("y-m", 0.0),
+ offsets->getFloatValue("z-m", 0.0));
+ alignmainmodel->setMatrix(res_matrix*tmat);
+ group = alignmainmodel;
+ }
+ if (!group) {
+ group = new osg::Group;
+ }
+ group->addChild(model.get());
+
+ // Load sub-models
+ vector<SGPropertyNode_ptr> model_nodes = props->getChildren("model");
+ for (unsigned i = 0; i < model_nodes.size(); i++) {
+ SGPropertyNode_ptr sub_props = model_nodes[i];
+
+ osg::ref_ptr<osg::Node> submodel;
+ const char* submodelFileName = sub_props->getStringValue("path");
+ try {
+ submodel = sgLoad3DModel_internal(submodelFileName, prop_root, 0, load_panel);
+ } catch (const sg_throwable &t) {
+ SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage());
+ throw;
+ }
+
+ osg::ref_ptr<osg::Node> submodel_final=submodel.get();
+ SGPropertyNode *offs = sub_props->getNode("offsets", false);
+ if (offs) {
+ osg::Matrix res_matrix;
+ osg::ref_ptr<osg::MatrixTransform> align = new osg::MatrixTransform;
+ res_matrix.makeIdentity();
+ res_matrix.makeRotate(
+ offs->getDoubleValue("pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 1, 0),
+ offs->getDoubleValue("roll-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(1, 0, 0),
+ offs->getDoubleValue("heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
+ osg::Vec3(0, 0, 1));
+
+ osg::Matrix tmat;
+ tmat.makeIdentity();
+ tmat.makeTranslate(offs->getDoubleValue("x-m", 0),
+ offs->getDoubleValue("y-m", 0),
+ offs->getDoubleValue("z-m", 0));
+ align->setMatrix(res_matrix*tmat);
+ align->addChild(submodel.get());
+ submodel_final=align.get();
+ }
+ submodel_final->setName(sub_props->getStringValue("name", ""));
+
+ SGPropertyNode *cond = sub_props->getNode("condition", false);
+ if (cond) {
+ osg::ref_ptr<osg::Switch> sw = new osg::Switch;
+ sw->setUpdateCallback(new SGSwitchUpdateCallback(sgReadCondition(prop_root, cond)));
+ group->addChild(sw.get());
+ sw->addChild(submodel_final.get());
+ sw->setName("submodel condition switch");
+ } else {
+ group->addChild(submodel_final.get());
+ }
+ } // end of submodel loading
+
+ if ( load_panel ) {
+ // Load panels
+ vector<SGPropertyNode_ptr> panel_nodes = props->getChildren("panel");
+ for (unsigned i = 0; i < panel_nodes.size(); i++) {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel");
+ osg::ref_ptr<osg::Node> panel = load_panel(panel_nodes[i]);
+ if (panel_nodes[i]->hasValue("name"))
+ panel->setName((char *)panel_nodes[i]->getStringValue("name"));
+ group->addChild(panel.get());
+ }
+ }
+
+ std::vector<SGPropertyNode_ptr> particle_nodes;
+ particle_nodes = props->getChildren("particlesystem");
+ for (unsigned i = 0; i < particle_nodes.size(); ++i) {
+ if (i==0) {
+ if (texturepath.extension() != "")
+ texturepath = texturepath.dir();
+
+ options->setDatabasePath(texturepath.str());
+ }
+ group->addChild(Particles::appendParticles(particle_nodes[i],
+ prop_root,
+ options.get()));
+ }
+
+ if (data) {
+ SGPropertyNode *nasal = props->getNode("nasal", false);
+ data->setProps(nasal);
+ group->setUserData(data);
+ //data->modelLoaded(path, nasal, group.get());
+ }
+
+ std::vector<SGPropertyNode_ptr> animation_nodes;
+ animation_nodes = props->getChildren("animation");
+ for (unsigned i = 0; i < animation_nodes.size(); ++i)
+ /// OSGFIXME: duh, why not only model?????
+ SGAnimation::animate(group.get(), animation_nodes[i], prop_root,
+ options.get());
+
+ if (props->hasChild("debug-outfile")) {
+ std::string outputfile = props->getStringValue("debug-outfile",
+ "debug-model.osg");
+ osgDB::writeNodeFile(*group, outputfile);
+ }
+ if (!needTransform && group->getNumChildren() < 2) {
+ model = group->getChild(0);
+ group->removeChild(model.get());
+ model->setUserData(group->getUserData());
+ return model.release();
+ }
+
+ return group.release();
+}
+
--- /dev/null
+/*
+ * 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>
+namespace simgear
+{
+
+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
+
--- /dev/null
+// Copyright (C) 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 SGREADERWRITERXMLOPTIONS_HXX
+#define SGREADERWRITERXMLOPTIONS_HXX 1
+
+#include <osgDB/ReaderWriter>
+#include <simgear/props/props.hxx>
+
+class SGPropertyNode;
+
+namespace simgear
+{
+class SGModelData;
+
+class SGReaderWriterXMLOptions : public osgDB::ReaderWriter::Options
+{
+public:
+ typedef osg::Node *(*panel_func)(SGPropertyNode *);
+
+ 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) {}
+
+ SGReaderWriterXMLOptions(const SGReaderWriterXMLOptions& options,
+ const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
+ osgDB::ReaderWriter::Options(options, copyop),
+ _prop_root(options._prop_root),
+ _load_panel(options._load_panel),
+ _model_data(options._model_data) {}
+
+ SGReaderWriterXMLOptions(const osgDB::ReaderWriter::Options& options,
+ const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
+ osgDB::ReaderWriter::Options(options, copyop),
+ _prop_root(0),
+ _load_panel(0),
+ _model_data(0) {}
+
+ SGPropertyNode *getPropRoot() const {
+ return _prop_root;
+ }
+ panel_func getLoadPanel() const {
+ return _load_panel;
+ }
+ SGModelData *getModelData() const {
+ return _model_data.get();
+ }
+
+ void setPropRoot(SGPropertyNode *p) {
+ _prop_root=p;
+ }
+ void setLoadPanel(panel_func pf) {
+ _load_panel=pf;
+ }
+ void setModelData(SGModelData *d) {
+ _model_data=d;
+ }
+
+protected:
+ virtual ~SGReaderWriterXMLOptions() {}
+
+ SGPropertyNode_ptr _prop_root;
+ osg::Node *(*_load_panel)(SGPropertyNode *);
+ osg::ref_ptr<SGModelData> _model_data;
+};
+
+}
+#endif
#include <simgear_config.h>
#endif
-#include <osg/observer_ptr>
#include <osg/ref_ptr>
-#include <osg/Group>
-#include <osg/NodeCallback>
-#include <osg/Switch>
-#include <osg/MatrixTransform>
-#include <osgDB/Archive>
-#include <osgDB/FileNameUtils>
-#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
-#include <osgDB/WriteFile>
-#include <osgDB/Registry>
#include <osgDB/SharedStateManager>
-#include <osgUtil/Optimizer>
#include <simgear/scene/util/SGSceneFeatures.hxx>
-#include <simgear/scene/util/SGStateAttributeVisitor.hxx>
-#include <simgear/scene/util/SGTextureStateAttributeVisitor.hxx>
#include <simgear/structure/exception.hxx>
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/props/condition.hxx>
-#include "animation.hxx"
#include "model.hxx"
-#include "particles.hxx"
SG_USING_STD(vector);
-using namespace simgear;
-
osg::Texture2D*
SGLoadTexture2D(bool staticTexture, const std::string& path,
const osgDB::ReaderWriter::Options* options,
return texture.release();
}
-class SGSwitchUpdateCallback : public osg::NodeCallback {
-public:
- SGSwitchUpdateCallback(SGCondition* condition) :
- mCondition(condition) {}
- virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
- {
- assert(dynamic_cast<osg::Switch*>(node));
- osg::Switch* s = static_cast<osg::Switch*>(node);
-
- if (mCondition && mCondition->test()) {
- s->setAllChildrenOn();
- // note, callback is responsible for scenegraph traversal so
- // should always include call traverse(node,nv) to ensure
- // that the rest of cullbacks and the scene graph are traversed.
- traverse(node, nv);
- } else
- s->setAllChildrenOff();
- }
-
-private:
- SGSharedPtr<SGCondition> mCondition;
-};
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Global functions.
-////////////////////////////////////////////////////////////////////////
-
-osg::Node *
-sgLoad3DModel( const string &fg_root, const string &path,
- SGPropertyNode *prop_root,
- double sim_time_sec, osg::Node *(*load_panel)(SGPropertyNode *),
- SGModelData *data,
- const SGPath& externalTexturePath )
-{
- osg::ref_ptr<osg::Node> model;
- SGPropertyNode props;
-
- // Load the 3D aircraft object itself
- SGPath modelpath = path, texturepath = path;
- if ( !ulIsAbsolutePathName( path.c_str() ) ) {
- SGPath tmp = fg_root;
- tmp.append(modelpath.str());
- modelpath = texturepath = tmp;
- }
-
- // Check for an XML wrapper
- if (modelpath.str().substr(modelpath.str().size() - 4, 4) == ".xml") {
- readProperties(modelpath.str(), &props);
- if (props.hasValue("/path")) {
- modelpath = modelpath.dir();
- modelpath.append(props.getStringValue("/path"));
- if (props.hasValue("/texture-path")) {
- texturepath = texturepath.dir();
- texturepath.append(props.getStringValue("/texture-path"));
- }
- } else {
- if (!model)
- model = new osg::Switch;
- }
- }
-
- osg::ref_ptr<osgDB::ReaderWriter::Options> options
- = new osgDB::ReaderWriter::Options(*osgDB::Registry::instance()
- ->getOptions());
-
- // Assume that textures are in
- // the same location as the XML file.
- if (!model) {
- if (texturepath.extension() != "")
- texturepath = texturepath.dir();
-
- options->setDatabasePath(texturepath.str());
- if (!externalTexturePath.str().empty())
- options->getDatabasePathList().push_back(externalTexturePath.str());
-
- model = osgDB::readNodeFile(modelpath.str(), options.get());
- if (model == 0)
- throw sg_io_exception("Failed to load 3D model",
- sg_location(modelpath.str()));
- }
-
- // Set up the alignment node
- osg::ref_ptr<osg::MatrixTransform> alignmainmodel = new osg::MatrixTransform;
- alignmainmodel->addChild(model.get());
- osg::Matrix res_matrix;
- res_matrix.makeRotate(
- props.getFloatValue("/offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 1, 0),
- props.getFloatValue("/offsets/roll-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(1, 0, 0),
- props.getFloatValue("/offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 0, 1));
-
- osg::Matrix tmat;
- tmat.makeTranslate(props.getFloatValue("/offsets/x-m", 0.0),
- props.getFloatValue("/offsets/y-m", 0.0),
- props.getFloatValue("/offsets/z-m", 0.0));
- alignmainmodel->setMatrix(res_matrix*tmat);
-
- // Load sub-models
- vector<SGPropertyNode_ptr> model_nodes = props.getChildren("model");
- for (unsigned i = 0; i < model_nodes.size(); i++) {
- SGPropertyNode_ptr node = model_nodes[i];
- osg::ref_ptr<osg::MatrixTransform> align = new osg::MatrixTransform;
- res_matrix.makeIdentity();
- res_matrix.makeRotate(
- node->getDoubleValue("offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 1, 0),
- node->getDoubleValue("offsets/roll-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(1, 0, 0),
- node->getDoubleValue("offsets/heading-deg", 0.0)*SG_DEGREES_TO_RADIANS,
- osg::Vec3(0, 0, 1));
-
- tmat.makeIdentity();
- tmat.makeTranslate(node->getDoubleValue("offsets/x-m", 0),
- node->getDoubleValue("offsets/y-m", 0),
- node->getDoubleValue("offsets/z-m", 0));
- align->setMatrix(res_matrix*tmat);
-
- osg::ref_ptr<osg::Node> kid;
- const char* submodel = node->getStringValue("path");
- try {
- kid = sgLoad3DModel( fg_root, submodel, prop_root, sim_time_sec, load_panel );
-
- } catch (const sg_throwable &t) {
- SG_LOG(SG_INPUT, SG_ALERT, "Failed to load submodel: " << t.getFormattedMessage());
- throw;
- }
- align->addChild(kid.get());
-
- align->setName(node->getStringValue("name", ""));
-
- SGPropertyNode *cond = node->getNode("condition", false);
- if (cond) {
- osg::ref_ptr<osg::Switch> sw = new osg::Switch;
- sw->setUpdateCallback(new SGSwitchUpdateCallback(sgReadCondition(prop_root, cond)));
- alignmainmodel->addChild(sw.get());
- sw->addChild(align.get());
- sw->setName("submodel condition switch");
- } else {
- alignmainmodel->addChild(align.get());
- }
- }
-
- if ( load_panel ) {
- // Load panels
- vector<SGPropertyNode_ptr> panel_nodes = props.getChildren("panel");
- for (unsigned i = 0; i < panel_nodes.size(); i++) {
- SG_LOG(SG_INPUT, SG_DEBUG, "Loading a panel");
- osg::ref_ptr<osg::Node> panel = load_panel(panel_nodes[i]);
- if (panel_nodes[i]->hasValue("name"))
- panel->setName((char *)panel_nodes[i]->getStringValue("name"));
- alignmainmodel->addChild(panel.get());
- }
- }
-
- std::vector<SGPropertyNode_ptr> particle_nodes;
- particle_nodes = props.getChildren("particlesystem");
- for (unsigned i = 0; i < particle_nodes.size(); ++i)
- {
- if(i==0)
- {
- if (texturepath.extension() != "")
- texturepath = texturepath.dir();
-
- options->setDatabasePath(texturepath.str());
- if (!externalTexturePath.str().empty())
- options->getDatabasePathList().push_back(externalTexturePath.str());
- }
- alignmainmodel.get()->addChild(Particles::appendParticles(particle_nodes[i],
- prop_root,
- options.get()));
- }
-
- if (data) {
- alignmainmodel->setUserData(data);
- data->modelLoaded(path, &props, alignmainmodel.get());
- }
-
- std::vector<SGPropertyNode_ptr> animation_nodes;
- animation_nodes = props.getChildren("animation");
- for (unsigned i = 0; i < animation_nodes.size(); ++i)
- /// OSGFIXME: duh, why not only model?????
- SGAnimation::animate(alignmainmodel.get(), animation_nodes[i], prop_root,
- options.get());
-
- if (props.hasChild("debug-outfile")) {
- std::string outputfile = props.getStringValue("debug-outfile",
- "debug-model.osg");
- osgDB::writeNodeFile(*alignmainmodel, outputfile);
- }
-
- return alignmainmodel.release();
-}
-
// end of model.cxx
#include <osgDB/ReaderWriter>
#include <simgear/misc/sg_path.hxx>
-#include <simgear/props/props.hxx>
-
-
-// Has anyone done anything *really* stupid, like making min and max macros?
-#ifdef min
-#undef min
-#endif
-#ifdef max
-#undef max
-#endif
-
-
-/**
- * Abstract class for adding data to the scene graph. modelLoaded() is
- * called by sgLoad3DModel() after the model was loaded, and the destructor
- * when the branch is removed from the graph.
- */
-class SGModelData : public osg::Referenced {
-public:
- virtual ~SGModelData() {}
- virtual void modelLoaded( const string& path, SGPropertyNode *prop,
- osg::Node*branch) = 0;
-};
-
-
-/**
- * Load a 3D model with or without XML wrapper. Note, this version
- * Does not know about or load the panel/cockpit information. Use the
- * "model_panel.hxx" version if you want to load an aircraft
- * (i.e. ownship) with a panel.
- *
- * If the path ends in ".xml", then it will be used as a property-
- * list wrapper to add animations to the model.
- *
- * Subsystems should not normally invoke this function directly;
- * instead, they should use the FGModelLoader declared in loader.hxx.
- */
-osg::Node*
-sgLoad3DModel( const string& fg_root, const string &path,
- SGPropertyNode *prop_root, double sim_time_sec,
- osg::Node *(*load_panel)(SGPropertyNode *) = 0,
- SGModelData *data = 0,
- const SGPath& texturePath = SGPath() );
-
-
-/**
- * Make the animation
- */
-void
-sgMakeAnimation( osg::Node* model,
- const char * name,
- vector<SGPropertyNode_ptr> &name_nodes,
- SGPropertyNode *prop_root,
- SGPropertyNode_ptr node,
- double sim_time_sec,
- SGPath &texture_path,
- set<osg::Node*> &ignore_branches );
osg::Texture2D*
SGLoadTexture2D(bool staticTexture, const std::string& path,
-// modellib.cxx - implement an SSG model library.
+// 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.
+//
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
-#include <simgear/compiler.h>
+#include <osgDB/ReadFile>
+#include <osgDB/WriteFile>
+#include <osgDB/Registry>
+
+#include <simgear/constants.h>
#include <simgear/props/props.hxx>
-#include <simgear/scene/util/SGNodeMasks.hxx>
+#include <simgear/props/props_io.hxx>
+#include <simgear/scene/model/ModelRegistry.hxx>
-#include "model.hxx"
-#include "animation.hxx"
+#include "SGPagedLOD.hxx"
+#include "SGReaderWriterXML.hxx"
+#include "SGReaderWriterXMLOptions.hxx"
+//#include "model.hxx"
#include "modellib.hxx"
+using namespace simgear;
+
+osgDB::RegisterReaderWriterProxy<SGReaderWriterXML> g_readerWriter_XML_Proxy;
+ModelRegistryCallbackProxy<LoadOnlyCallback> g_xmlCallbackProxy("xml");
+
\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGModelLib.
////////////////////////////////////////////////////////////////////////
+void SGModelLib::init(const string &root_dir)
+{
+ osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir);
+}
-SGModelLib::SGModelLib ()
+SGModelLib::SGModelLib()
{
}
-SGModelLib::~SGModelLib ()
+SGModelLib::~SGModelLib()
{
}
-void
-SGModelLib::flush1()
+osg::Node*
+SGModelLib::loadModel(const string &path,
+ SGPropertyNode *prop_root,
+ SGModelData *data)
{
+ osg::ref_ptr<SGReaderWriterXMLOptions> opt = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance()->getOptions()));
+ opt->setPropRoot(prop_root);
+ opt->setModelData(data);
+ osg::Node *n = readNodeFile(path, opt.get());
+ if(data)
+ data->modelLoaded(path, data->getProperties(), n);
+ return n;
+
}
osg::Node*
-SGModelLib::load_model( const string &fg_root,
- const string &path,
- SGPropertyNode *prop_root,
- double sim_time_sec,
- bool cache_object,
- SGModelData *data )
+SGModelLib::loadModel(const string &path,
+ SGPropertyNode *prop_root,
+ panel_func pf)
{
- return sgLoad3DModel(fg_root, path, prop_root, sim_time_sec, 0, data );
+ osg::ref_ptr<SGReaderWriterXMLOptions> opt = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance()->getOptions()));
+ opt->setPropRoot(prop_root);
+ opt->setLoadPanel(pf);
+ return readNodeFile(path, opt.get());
}
+osg::Node*
+SGModelLib::loadPagedModel(const string &path,
+ SGPropertyNode *prop_root,
+ SGModelData *data)
+{
+ SGPagedLOD *plod = new SGPagedLOD;
+ plod->setFileName(0, path);
+ plod->setRange(0, 0.0, 50.0*SG_NM_TO_METER);
+
+ osg::ref_ptr<SGReaderWriterXMLOptions> opt = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance()->getOptions()));
+ opt->setPropRoot(prop_root);
+ opt->setModelData(data);
+ plod->setReaderWriterOptions(opt.get());
+ return plod;
+}
// end of modellib.cxx
-// modellib.cxx - implement an SSG model library.
+// 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 _SG_MODEL_LIB_HXX
#define _SG_MODEL_LIB_HXX 1
#include <simgear/compiler.h> // for SG_USING_STD
-#include <map>
#include STL_STRING
-#include <osg/ref_ptr>
#include <osg/Node>
#include <simgear/props/props.hxx>
-#include "model.hxx"
SG_USING_STD(map);
SG_USING_STD(string);
+namespace simgear {
+
+class SGModelData; // defined below
/**
* Class for loading and managing models with XML wrappers.
*/
class SGModelLib
{
+public:
+ typedef osg::Node *(*panel_func)(SGPropertyNode *);
+
+ static void init(const string &root_dir);
+
+ // Load a 3D model (any format)
+ // data->modelLoaded() will be called after the model is loaded
+ static osg::Node* loadModel(const string &path,
+ SGPropertyNode *prop_root,
+ SGModelData *data=0);
+
+ // Load a 3D model (any format)
+ // with a panel_func to load a panel
+ static osg::Node* loadModel(const string &path,
+ SGPropertyNode *prop_root,
+ panel_func pf);
+
+ // Load a 3D model (any format) through the DatabasePager.
+ // Most models should be loaded using this function!
+ // This function will initially return an SGPagedLOD node.
+ // data->modelLoaded() will be called after the model is loaded and
+ // connected to the scene graph. See AIModelData on how to use this.
+ // NOTE: AIModelData uses observer_ptr to avoid circular references.
+ static osg::Node* loadPagedModel(const string &path,
+ SGPropertyNode *prop_root,
+ SGModelData *data=0);
+protected:
+ SGModelLib();
+ ~SGModelLib ();
+};
+
+
+/**
+ * Abstract class for adding data to the scene graph. modelLoaded() is
+ * called after the model was loaded, and the destructor when the branch
+ * is removed from the scene graph.
+ */
+class SGModelData : public osg::Referenced {
public:
+ virtual ~SGModelData() {}
+ virtual void modelLoaded( const string& path, SGPropertyNode *prop,
+ osg::Node*branch) = 0;
- SGModelLib ();
- virtual ~SGModelLib ();
- virtual void flush1();
+ virtual void setProps(SGPropertyNode *p)
+ { _props = p; }
- virtual osg::Node *load_model( const string &fg_root,
- const string &path,
- SGPropertyNode *prop_root,
- double sim_time_sec,
- bool cache_object,
- SGModelData *data = 0 );
+ SGPropertyNode *getProperties()
+ { return _props; }
+protected:
+ SGPropertyNode_ptr _props;
};
+}
#endif // _SG_MODEL_LIB_HXX
// building / drawing any scenery.
static bool _inited = false;
-static SGModelLib *modellib = NULL;
-static string model_root = "";
static SGPropertyNode *root_props = NULL;
-static double sim_time_sec = 0.0;
// Because BTG files are now loaded through the osgDB::Registry, there
// are no symbols referenced by FlightGear in this library other than
// to be sucked in.
osgDB::RegisterReaderWriterProxy<SGReaderWriterBTG> g_readerWriter_BTG_Proxy;
-void sgUserDataInit( SGModelLib *m, const string &r,
- SGPropertyNode *p, double t ) {
+void sgUserDataInit( SGPropertyNode *p ) {
_inited = true;
- modellib = m;
- model_root = r;
root_props = p;
- sim_time_sec = t;
}
osg::Node* sgGetRandomModel(SGMatModel *obj) {
- return obj->get_random_model(modellib, model_root, root_props, sim_time_sec);
+ return obj->get_random_model( root_props );
}
osg::Node* sgGetModel(int i, SGMatModel *obj) {
- return obj->get_model(i, modellib, model_root, root_props, sim_time_sec);
+ return obj->get_model(i, root_props );
}
static void random_pt_inside_tri( float *res,
res[2] = n1[2]*a + n2[2]*b + n3[2]*c;
}
-
-/**
- * Fill in a triangle with randomly-placed objects.
- *
- * This method is invoked by a callback when the triangle is in range
- * but not yet populated.
- *
- */
-
-void SGTriUserData::fill_in_triangle ()
-{
- // generate a repeatable random seed
- sg_srandom(seed);
-
- int nObjects = object_group->get_object_count();
-
- for (int i = 0; i < nObjects; i++) {
- SGMatModel * object = object_group->get_object(i);
- double num = area / object->get_coverage_m2();
-
- // place an object each unit of area
- while ( num > 1.0 ) {
- add_object_to_triangle(object);
- num -= 1.0;
- }
- // for partial units of area, use a zombie door method to
- // create the proper random chance of an object being created
- // for this triangle
- if ( num > 0.0 ) {
- if ( sg_random() <= num ) {
- // a zombie made it through our door
- add_object_to_triangle(object);
- }
- }
- }
-}
-
-void SGTriUserData::add_object_to_triangle (SGMatModel * object)
-{
- // Set up the random heading if required.
- double hdg_deg = 0;
- if (object->get_heading_type() == SGMatModel::HEADING_RANDOM)
- hdg_deg = sg_random() * 360;
-
-#if 0
- // OSGFIXME
- sgMat4 mat;
- makeWorldMatrix(mat, hdg_deg);
-
- ssgTransform * pos = new ssgTransform;
- pos->setTransform(mat);
- // the parameters to get_random_model() are set in local static
- // data via the ssgUserDataInit() function. This function must be
- // called before any scenery is drawn.
- pos->addKid( object->get_random_model( modellib, model_root,
- root_props, sim_time_sec )
- );
- branch->addKid(pos);
-#endif
-}
-
-void SGTriUserData::makeWorldMatrix (sgMat4 mat, double hdg_deg )
-{
- // OSGFIXME
-// if (hdg_deg == 0) {
-// mat[0][0] = leafData->sin_lat * leafData->cos_lon;
-// mat[0][1] = leafData->sin_lat * leafData->sin_lon;
-// mat[0][2] = -leafData->cos_lat;
-// mat[0][3] = SG_ZERO;
-
-// mat[1][0] = -leafData->sin_lon;
-// mat[1][1] = leafData->cos_lon;
-// mat[1][2] = SG_ZERO;
-// mat[1][3] = SG_ZERO;
-// } else {
-// float sin_hdg = sin( hdg_deg * SGD_DEGREES_TO_RADIANS ) ;
-// float cos_hdg = cos( hdg_deg * SGD_DEGREES_TO_RADIANS ) ;
-// mat[0][0] = cos_hdg * leafData->sin_lat * leafData->cos_lon - sin_hdg * leafData->sin_lon;
-// mat[0][1] = cos_hdg * leafData->sin_lat * leafData->sin_lon + sin_hdg * leafData->cos_lon;
-// mat[0][2] = -cos_hdg * leafData->cos_lat;
-// mat[0][3] = SG_ZERO;
-
-// mat[1][0] = -sin_hdg * leafData->sin_lat * leafData->cos_lon - cos_hdg * leafData->sin_lon;
-// mat[1][1] = -sin_hdg * leafData->sin_lat * leafData->sin_lon + cos_hdg * leafData->cos_lon;
-// mat[1][2] = sin_hdg * leafData->cos_lat;
-// mat[1][3] = SG_ZERO;
-// }
-
-// mat[2][0] = leafData->cos_lat * leafData->cos_lon;
-// mat[2][1] = leafData->cos_lat * leafData->sin_lon;
-// mat[2][2] = leafData->sin_lat;
-// mat[2][3] = SG_ZERO;
-
-// // translate to random point in triangle
-// sgVec3 result;
-// random_pt_inside_tri(result, p1, p2, p3);
-// sgSubVec3(mat[3], result, center);
-
-// mat[3][3] = SG_ONE ;
-}
-
-/**
- * SSG callback for an in-range triangle of randomly-placed objects.
- *
- * This pretraversal callback is attached to a branch that is traversed
- * only when a triangle is in range. If the triangle is not currently
- * populated with randomly-placed objects, this callback will populate
- * it.
- *
- * @param entity The entity to which the callback is attached (not used).
- * @param mask The entity's traversal mask (not used).
- * @return Always 1, to allow traversal and culling to continue.
- */
-// static int
-// tri_in_range_callback (ssgEntity * entity, int mask)
-// {
-// SGTriUserData * data = (SGTriUserData *)entity->getUserData();
-// if (!data->is_filled_in) {
-// data->fill_in_triangle();
-// data->is_filled_in = true;
-// }
-// return 1;
-// }
-
-
-/**
- * SSG callback for an out-of-range triangle of randomly-placed objects.
- *
- * This pretraversal callback is attached to a branch that is traversed
- * only when a triangle is out of range. If the triangle is currently
- * populated with randomly-placed objects, the objects will be removed.
- *
- *
- * @param entity The entity to which the callback is attached (not used).
- * @param mask The entity's traversal mask (not used).
- * @return Always 0, to prevent any further traversal or culling.
- */
-// static int
-// tri_out_of_range_callback (ssgEntity * entity, int mask)
-// {
-// SGTriUserData * data = (SGTriUserData *)entity->getUserData();
-// if (data->is_filled_in) {
-// data->branch->removeAllKids();
-// data->is_filled_in = false;
-// }
-// return 0;
-// }
-
-
-/**
- * Calculate the bounding radius of a triangle from its center.
- *
- * @param center The triangle center.
- * @param p1 The first point in the triangle.
- * @param p2 The second point in the triangle.
- * @param p3 The third point in the triangle.
- * @return The greatest distance any point lies from the center.
- */
-// static inline float
-// get_bounding_radius( sgVec3 center, float *p1, float *p2, float *p3)
-// {
-// return sqrt( SG_MAX3( sgDistanceSquaredVec3(center, p1),
-// sgDistanceSquaredVec3(center, p2),
-// sgDistanceSquaredVec3(center, p3) ) );
-// }
-
-
-/**
- * Set up a triangle for randomly-placed objects.
- *
- * No objects will be added unless the triangle comes into range.
- *
- */
-
-void SGLeafUserData::setup_triangle (int i )
-{
-// short n1, n2, n3;
-// leaf->getTriangle(i, &n1, &n2, &n3);
-
-// float * p1 = leaf->getVertex(n1);
-// float * p2 = leaf->getVertex(n2);
-// float * p3 = leaf->getVertex(n3);
-
-// // Set up a single center point for LOD
-// sgVec3 center;
-// sgSetVec3(center,
-// (p1[0] + p2[0] + p3[0]) / 3.0,
-// (p1[1] + p2[1] + p3[1]) / 3.0,
-// (p1[2] + p2[2] + p3[2]) / 3.0);
-// double area = sgTriArea(p1, p2, p3);
-
-// // maximum radius of an object from center.
-// double bounding_radius = get_bounding_radius(center, p1, p2, p3);
-
-// // Set up a transformation to the center
-// // point, so that everything else can
-// // be specified relative to it.
-// ssgTransform * location = new ssgTransform;
-// sgMat4 TRANS;
-// sgMakeTransMat4(TRANS, center);
-// location->setTransform(TRANS);
-// branch->addKid(location);
-
-// // Iterate through all the object types.
-// int num_groups = mat->get_object_group_count();
-// for (int j = 0; j < num_groups; j++) {
-// // Look up the random object.
-// SGMatModelGroup * group = mat->get_object_group(j);
-
-// // Set up the range selector for the entire
-// // triangle; note that we use the object
-// // range plus the bounding radius here, to
-// // allow for objects far from the center.
-// float ranges[] = { 0,
-// group->get_range_m() + bounding_radius,
-// SG_MAX };
-// ssgRangeSelector * lod = new ssgRangeSelector;
-// lod->setRanges(ranges, 3);
-// location->addKid(lod);
-
-// // Create the in-range and out-of-range
-// // branches.
-// ssgBranch * in_range = new ssgBranch;
-// ssgBranch * out_of_range = new ssgBranch;
-
-// // Set up the user data for if/when
-// // the random objects in this triangle
-// // are filled in.
-// SGTriUserData * data = new SGTriUserData;
-// data->is_filled_in = false;
-// data->p1 = p1;
-// data->p2 = p2;
-// data->p3 = p3;
-// sgCopyVec3 (data->center, center);
-// data->area = area;
-// data->object_group = group;
-// data->branch = in_range;
-// data->leafData = this;
-// data->seed = (unsigned int)(p1[0] * j);
-
-// // Set up the in-range node.
-// in_range->setUserData(data);
-// in_range->setTravCallback(SSG_CALLBACK_PRETRAV,
-// tri_in_range_callback);
-// lod->addKid(in_range);
-
-// // Set up the out-of-range node.
-// out_of_range->setUserData(data);
-// out_of_range->setTravCallback(SSG_CALLBACK_PRETRAV,
-// tri_out_of_range_callback);
-// out_of_range->addKid(new SGDummyBSphereEntity(bounding_radius));
-// lod->addKid(out_of_range);
-// }
-}
* following values (needed by the model loader callback at draw time)
* before drawing any scenery.
*/
-void sgUserDataInit( SGModelLib *m, const string &r,
- SGPropertyNode *p, double t );
+void sgUserDataInit(SGPropertyNode *p);
/**
* Get a random model.
*/
osg::Node* sgGetRandomModel(SGMatModel *obj);
-/**
- * Get a specific model.
- */
-osg::Node* sgGetModel(int i, SGMatModel *obj);
-
-/**
- * User data for populating leaves when they come in range.
- */
-class SGLeafUserData : public osg::Referenced
-{
-public:
- bool is_filled_in;
- osg::Geometry *leaf;
- SGMaterial *mat;
- osg::Group *branch;
- float sin_lat;
- float cos_lat;
- float sin_lon;
- float cos_lon;
-
- void setup_triangle( int i );
-};
-
-
-/**
- * User data for populating triangles when they come in range.
- */
-class SGTriUserData : public osg::Referenced
-{
-public:
- bool is_filled_in;
- float * p1;
- float * p2;
- float * p3;
- osg::Vec3 center;
- double area;
- SGMatModelGroup * object_group;
- osg::Group * branch;
- SGLeafUserData * leafData;
- unsigned int seed;
-
- void fill_in_triangle();
- void add_object_to_triangle(SGMatModel * object);
- void makeWorldMatrix (sgMat4 ROT, double hdg_deg );
-};
-
#endif // _SG_USERDATA_HXX
* subsystems may also override the suspend() and resume() methods to
* take different actions.</p>
*/
-class SGSubsystem
+class SGSubsystem : public SGReferenced
{
public: