model paging patch from Till Busch
Comments from Till: I started the project at the end of february with a simple idea: move all 3d-model loading to the DatabasePager-thread. my first attempts looked promising, though they were a little too optimistic (or naive?). the patch has evolved a lot since. currently it does the following things: 1. revive SGModelLib, move functions for xml-model-loading there 2. replace all calls to sgLoad3dModel with calls to either SGModelLib::loadModel() or SGModelLib::loadPagedModel() almost all models will be loaded by the DatabasePager. the few exceptions are: your own plane, shared models in scenery, random objects, AIBallistic models. 3. simplify mode-loading functions (avoid passing around fg_root) 4. avoid supurious MatrixTransform nodes in loaded models 5. fix some memory leaks
This commit is contained in:
@@ -75,6 +75,8 @@
|
||||
* 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
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ SG_USING_STD(map);
|
||||
|
||||
#include "matmodel.hxx"
|
||||
|
||||
using namespace simgear;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Local static functions.
|
||||
@@ -115,27 +117,19 @@ SGMatModel::~SGMatModel ()
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -167,22 +161,16 @@ SGMatModel::load_models ( SGModelLib *modellib,
|
||||
|
||||
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)
|
||||
|
||||
@@ -46,7 +46,6 @@ SG_USING_STD(string);
|
||||
|
||||
|
||||
class SGMatModelGroup;
|
||||
class SGModelLib;
|
||||
|
||||
|
||||
/**
|
||||
@@ -76,10 +75,7 @@ public:
|
||||
*
|
||||
* @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 );
|
||||
|
||||
|
||||
/**
|
||||
@@ -88,11 +84,7 @@ public:
|
||||
* @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 );
|
||||
|
||||
|
||||
/**
|
||||
@@ -100,10 +92,7 @@ public:
|
||||
*
|
||||
* @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 );
|
||||
|
||||
|
||||
/**
|
||||
@@ -151,10 +140,7 @@ private:
|
||||
* 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;
|
||||
|
||||
70
simgear/scene/model/CheckSceneryVisitor.cxx
Normal file
70
simgear/scene/model/CheckSceneryVisitor.cxx
Normal file
@@ -0,0 +1,70 @@
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
68
simgear/scene/model/CheckSceneryVisitor.hxx
Normal file
68
simgear/scene/model/CheckSceneryVisitor.hxx
Normal file
@@ -0,0 +1,68 @@
|
||||
// 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
|
||||
@@ -14,9 +14,13 @@ include_HEADERS = \
|
||||
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
|
||||
@@ -32,9 +36,12 @@ libsgmodel_a_SOURCES = \
|
||||
placement.cxx \
|
||||
placementtrans.cxx \
|
||||
shadanim.cxx \
|
||||
CheckSceneryVisitor.cxx \
|
||||
SGClipGroup.cxx \
|
||||
SGMaterialAnimation.cxx \
|
||||
SGOffsetTransform.cxx \
|
||||
SGPagedLOD.cxx \
|
||||
SGReaderWriterXML.cxx \
|
||||
SGRotateTransform.cxx \
|
||||
SGScaleTransform.cxx \
|
||||
SGTranslateTransform.cxx
|
||||
|
||||
74
simgear/scene/model/SGPagedLOD.cxx
Normal file
74
simgear/scene/model/SGPagedLOD.cxx
Normal file
@@ -0,0 +1,74 @@
|
||||
// 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());
|
||||
}
|
||||
|
||||
62
simgear/scene/model/SGPagedLOD.hxx
Normal file
62
simgear/scene/model/SGPagedLOD.hxx
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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
|
||||
313
simgear/scene/model/SGReaderWriterXML.cxx
Normal file
313
simgear/scene/model/SGReaderWriterXML.cxx
Normal file
@@ -0,0 +1,313 @@
|
||||
// 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();
|
||||
}
|
||||
|
||||
41
simgear/scene/model/SGReaderWriterXML.hxx
Normal file
41
simgear/scene/model/SGReaderWriterXML.hxx
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
90
simgear/scene/model/SGReaderWriterXMLOptions.hxx
Normal file
90
simgear/scene/model/SGReaderWriterXMLOptions.hxx
Normal file
@@ -0,0 +1,90 @@
|
||||
// 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
|
||||
@@ -7,38 +7,21 @@
|
||||
#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,
|
||||
@@ -96,200 +79,4 @@ SGLoadTexture2D(bool staticTexture, const std::string& path,
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
@@ -23,63 +23,6 @@ SG_USING_STD(set);
|
||||
#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,
|
||||
|
||||
@@ -1,47 +1,103 @@
|
||||
// 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");
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of SGModelLib.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
void SGModelLib::init(const string &root_dir)
|
||||
{
|
||||
osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir);
|
||||
}
|
||||
|
||||
SGModelLib::SGModelLib ()
|
||||
SGModelLib::SGModelLib()
|
||||
{
|
||||
}
|
||||
|
||||
SGModelLib::~SGModelLib ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGModelLib::flush1()
|
||||
SGModelLib::~SGModelLib()
|
||||
{
|
||||
}
|
||||
|
||||
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,
|
||||
SGModelData *data)
|
||||
{
|
||||
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->setModelData(data);
|
||||
osg::Node *n = readNodeFile(path, opt.get());
|
||||
if(data)
|
||||
data->modelLoaded(path, data->getProperties(), n);
|
||||
return n;
|
||||
|
||||
}
|
||||
|
||||
osg::Node*
|
||||
SGModelLib::loadModel(const string &path,
|
||||
SGPropertyNode *prop_root,
|
||||
panel_func pf)
|
||||
{
|
||||
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
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
// 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
|
||||
@@ -9,38 +24,77 @@
|
||||
|
||||
#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 *);
|
||||
|
||||
SGModelLib ();
|
||||
virtual ~SGModelLib ();
|
||||
virtual void flush1();
|
||||
static void init(const string &root_dir);
|
||||
|
||||
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 );
|
||||
// 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;
|
||||
|
||||
virtual void setProps(SGPropertyNode *p)
|
||||
{ _props = p; }
|
||||
|
||||
SGPropertyNode *getProperties()
|
||||
{ return _props; }
|
||||
protected:
|
||||
SGPropertyNode_ptr _props;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _SG_MODEL_LIB_HXX
|
||||
|
||||
@@ -45,10 +45,7 @@
|
||||
// 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
|
||||
@@ -58,21 +55,17 @@ static double sim_time_sec = 0.0;
|
||||
// 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,
|
||||
@@ -91,257 +84,3 @@ 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);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -49,58 +49,11 @@ class SGPropertyNode;
|
||||
* 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
|
||||
|
||||
@@ -135,7 +135,7 @@ typedef vector<TimingInfo>::iterator eventTimeVecIterator;
|
||||
* subsystems may also override the suspend() and resume() methods to
|
||||
* take different actions.</p>
|
||||
*/
|
||||
class SGSubsystem
|
||||
class SGSubsystem : public SGReferenced
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user