From 359a8c4a81323544180b7ccec3d6df45e4b4c8b8 Mon Sep 17 00:00:00 2001 From: mfranz Date: Thu, 9 Mar 2006 09:03:57 +0000 Subject: [PATCH] model.[ch]xx: add abstract class SGModelData. If a pointer to such a class is handed over to sgLoad3DModel, then its modelLoaded() method is called with path, property node and branch. And then it's added to the scene graph so that it's destroyed when the model branch is removed from the graph. modellib.[ch]xx: only cache objects when asked to. This is the case for OBJECT_SHARED and random objects (like before), but no longer for OBJECT_STATIC. These are now removed from the graph when they are "out of sight". This prevents accumulation of static models, and makes destroying model data possible (e.g. removing Nasal modules) matmodel.cxx: set cache flag for random objects (same behavior as before) --- simgear/scene/material/matmodel.cxx | 3 ++- simgear/scene/model/model.cxx | 11 ++++++++++- simgear/scene/model/model.hxx | 16 +++++++++++++++- simgear/scene/model/modellib.cxx | 12 ++++++++---- simgear/scene/model/modellib.hxx | 5 ++++- 5 files changed, 39 insertions(+), 8 deletions(-) diff --git a/simgear/scene/material/matmodel.cxx b/simgear/scene/material/matmodel.cxx index f1d8ac08..314f1403 100644 --- a/simgear/scene/material/matmodel.cxx +++ b/simgear/scene/material/matmodel.cxx @@ -146,7 +146,8 @@ SGMatModel::load_models ( SGModelLib *modellib, if (!_models_loaded) { for (unsigned int i = 0; i < _paths.size(); i++) { ssgEntity *entity = modellib->load_model( fg_root, _paths[i], - prop_root, sim_time_sec ); + prop_root, sim_time_sec, + /*cache_object*/ true ); if (entity != 0) { // FIXME: this stuff can be handled // in the XML wrapper as well (at least, diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 48adc59f..fe3c5c5b 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -245,7 +245,8 @@ static void makeDList( ssgBranch *b, const set &ignore ) ssgBranch * sgLoad3DModel( const string &fg_root, const string &path, SGPropertyNode *prop_root, - double sim_time_sec, ssgEntity *(*load_panel)(SGPropertyNode *) ) + double sim_time_sec, ssgEntity *(*load_panel)(SGPropertyNode *), + SGModelData *data ) { ssgBranch * model = 0; SGPropertyNode props; @@ -336,6 +337,11 @@ sgLoad3DModel( const string &fg_root, const string &path, model->addKid(panel); } } + + if (data) { + data->modelLoaded(path, &props, model); + model->setUserData(data); + } // Load animations set ignore_branches; vector animation_nodes = props.getChildren("animation"); @@ -353,6 +359,9 @@ sgLoad3DModel( const string &fg_root, const string &path, } #endif + int m = props.getIntValue("dump", 0); + if (m > 0) + model->print(stderr, "", m - 1); return alignmainmodel; } diff --git a/simgear/scene/model/model.hxx b/simgear/scene/model/model.hxx index a2ecc522..2f8648e2 100644 --- a/simgear/scene/model/model.hxx +++ b/simgear/scene/model/model.hxx @@ -32,6 +32,19 @@ SG_USING_STD(set); #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 ssgBase { +public: + virtual ~SGModelData() {} + virtual void modelLoaded( const string& path, SGPropertyNode *prop, + ssgBranch *branch) {} +}; + + /** * Load a 3D model with or without XML wrapper. Note, this version * Does not know about or load the panel/cockpit information. Use the @@ -47,7 +60,8 @@ SG_USING_STD(set); ssgBranch * sgLoad3DModel( const string& fg_root, const string &path, SGPropertyNode *prop_root, double sim_time_sec, - ssgEntity *(*load_panel)(SGPropertyNode *) = 0 ); + ssgEntity *(*load_panel)(SGPropertyNode *) = 0, + SGModelData *data = 0 ); /** diff --git a/simgear/scene/model/modellib.cxx b/simgear/scene/model/modellib.cxx index 735625a4..bd28d43d 100644 --- a/simgear/scene/model/modellib.cxx +++ b/simgear/scene/model/modellib.cxx @@ -81,7 +81,9 @@ ssgEntity * SGModelLib::load_model( const string &fg_root, const string &path, SGPropertyNode *prop_root, - double sim_time_sec ) + double sim_time_sec, + bool cache_object, + SGModelData *data ) { ssgBranch *personality_branch = new SGPersonalityBranch; personality_branch->setTravCallback(SSG_CALLBACK_PRETRAV, personality_pretrav_callback); @@ -90,10 +92,12 @@ SGModelLib::load_model( const string &fg_root, // FIXME: normalize path to // avoid duplicates. map >::iterator it = _table.find(path); - if (it == _table.end()) { + if (!cache_object || it == _table.end()) { ssgSharedPtr model = sgLoad3DModel(fg_root, path, prop_root, - sim_time_sec ); - _table[path] = model; // add one reference to keep it around + sim_time_sec, 0, data ); + if (cache_object) + _table[path] = model; // add one reference to keep it around + personality_branch->addKid( model ); } else { personality_branch->addKid( it->second ); diff --git a/simgear/scene/model/modellib.hxx b/simgear/scene/model/modellib.hxx index 18e304ea..73866f20 100644 --- a/simgear/scene/model/modellib.hxx +++ b/simgear/scene/model/modellib.hxx @@ -16,6 +16,7 @@ #include #include +#include "model.hxx" SG_USING_STD(map); SG_USING_STD(string); @@ -36,7 +37,9 @@ public: virtual ssgEntity *load_model( const string &fg_root, const string &path, SGPropertyNode *prop_root, - double sim_time_sec ); + double sim_time_sec, + bool cache_object, + SGModelData *data = 0 ); protected: map > _table;