From: david Date: Wed, 7 Aug 2002 01:34:49 +0000 (+0000) Subject: Removed the FG3DModel class and replaced it with fgLoad3DModel. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=0ebe8ec8f0e88451fc41b0a2fd44df2380e19661;p=flightgear.git Removed the FG3DModel class and replaced it with fgLoad3DModel. Animations are now contained within the scene graph itself and are updated whenever the graph is traversed -- that saves time by not updating animations not currently in sight, and it allows animations to be used for static objects and random objects as well. Added new FGModelLoader and FGTextureLoader classes. These are intern tables for models, to guarantee (mostly) that no model is loaded more than once. FGTextureLoader is not yet used anywhere, but FGModelLoader is now in place everywhere that ssgLoad* used to be used (thus adding the ability to use animations). In the future, FGModelLoader will add some interesting functionality, including the ability to reload 3D models on the fly. --- diff --git a/src/ATC/AILocalTraffic.cxx b/src/ATC/AILocalTraffic.cxx index d95d929d6..a705d753d 100644 --- a/src/ATC/AILocalTraffic.cxx +++ b/src/ATC/AILocalTraffic.cxx @@ -28,6 +28,7 @@ ******************************************************************/ #include
+#include //#include #include #include @@ -48,12 +49,11 @@ FGAILocalTraffic::~FGAILocalTraffic() { void FGAILocalTraffic::Init() { // Hack alert - Hardwired path!! string planepath = "Aircraft/c172/Models/c172-dpm.ac"; - SGPath path = globals->get_fg_root(); - path.append(planepath); - ssgTexturePath((char*)path.dir().c_str()); - model = ssgLoad((char*)planepath.c_str()); + model = globals->get_model_loader()->load_model(planepath); if (model == 0) { - model = ssgLoad((char*)"Models/Geometry/glider.ac"); + model = + globals->get_model_loader() + ->load_model("Models/Geometry/glider.ac"); if (model == 0) cout << "Failed to load an aircraft model in AILocalTraffic\n"; } else { diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 438c6ec65..50123defc 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -65,6 +65,8 @@ class FGViewer; class FGATCMgr; class FGATCDisplay; class FGAIMgr; +class FGModelLoader; +class FGTextureLoader; class FGAircraftModel; class FGModelMgr; class FGScenery; @@ -156,6 +158,10 @@ private: SGCommandMgr *commands; + FGModelLoader * model_loader; + + FGTextureLoader * texture_loader; + FGAircraftModel *acmodel; FGModelMgr * model_mgr; @@ -256,6 +262,18 @@ public: inline SGCommandMgr *get_commands () { return commands; } + inline FGModelLoader * get_model_loader () { return model_loader; } + + inline void set_model_loader (FGModelLoader * loader) { + model_loader = loader; + } + + inline FGTextureLoader * get_texture_loader () { return texture_loader; } + + inline void set_texture_loader (FGTextureLoader * loader) { + texture_loader = loader; + } + inline FGAircraftModel *get_aircraft_model () { return acmodel; } inline void set_aircraft_model (FGAircraftModel * model) diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 765997437..a28675965 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -100,8 +100,9 @@ SG_USING_STD(endl); #include #include #include -#include +#include #include +#include #include
#ifdef FG_NETWORK_OLK #include @@ -1543,6 +1544,8 @@ int mainLoop( int argc, char **argv ) { // Initialize the general model subsystem. //////////////////////////////////////////////////////////////////// + globals->set_model_loader(new FGModelLoader); + globals->set_texture_loader(new FGTextureLoader); globals->set_model_mgr(new FGModelMgr); globals->get_model_mgr()->init(); globals->get_model_mgr()->bind(); @@ -1744,7 +1747,8 @@ void fgLoadDCS(void) { // instance of the last object. if ( strcmp(obj_filename,"repeat") != 0) { - ship_obj = ssgLoad( obj_filename ); + ship_obj = + globals->get_model_loader()->load_model( obj_filename ); } if ( ship_obj != NULL ) { diff --git a/src/Model/Makefile.am b/src/Model/Makefile.am index e932518fe..7ed105849 100644 --- a/src/Model/Makefile.am +++ b/src/Model/Makefile.am @@ -1,6 +1,7 @@ noinst_LIBRARIES = libModel.a -libModel_a_SOURCES = model.cxx model.hxx \ +libModel_a_SOURCES = loader.cxx loader.hxx \ + model.cxx model.hxx \ modelmgr.cxx modelmgr.hxx \ acmodel.cxx acmodel.hxx \ panelnode.cxx panelnode.hxx diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index 9e9dd6dc0..786a6ba07 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -94,7 +94,7 @@ FGAircraftModel::update (double dt) _aircraft->setOrientation(fgGetDouble("/orientation/roll-deg"), fgGetDouble("/orientation/pitch-deg"), fgGetDouble("/orientation/heading-deg")); - _aircraft->update(dt); + _aircraft->update(); } diff --git a/src/Model/loader.cxx b/src/Model/loader.cxx new file mode 100644 index 000000000..0e0ccf4d7 --- /dev/null +++ b/src/Model/loader.cxx @@ -0,0 +1,104 @@ +// loader.cxx - implement SSG model and texture loaders. + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "loader.hxx" +#include "model.hxx" + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGSSGLoader. +//////////////////////////////////////////////////////////////////////// + +FGSSGLoader::FGSSGLoader () +{ + // no op +} + +FGSSGLoader::~FGSSGLoader () +{ + map::iterator it = _table.begin(); + while (it != _table.end()) { + it->second->deRef(); + _table.erase(it); + } +} + +void +FGSSGLoader::flush () +{ + map::iterator it = _table.begin(); + while (it != _table.end()) { + ssgBase * item = it->second; + // If there is only one reference, it's + // ours; no one else is using the item. + if (item->getRef() == 1) { + item->deRef(); + _table.erase(it); + } + it++; + } +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGModelLoader. +//////////////////////////////////////////////////////////////////////// + +FGModelLoader::FGModelLoader () +{ +} + +FGModelLoader::~FGModelLoader () +{ +} + +ssgEntity * +FGModelLoader::load_model (const string &path) +{ + // FIXME: normalize path to + // avoid duplicates. + map::iterator it = _table.find(path); + if (it == _table.end()) { + _table[path] = fgLoad3DModel((char *)path.c_str()); + it = _table.find(path); + it->second->ref(); // add one reference to keep it around + } + return (ssgEntity *)it->second; +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGTextureLoader. +//////////////////////////////////////////////////////////////////////// + +FGTextureLoader::FGTextureLoader () +{ +} + +FGTextureLoader::~FGTextureLoader () +{ +} + +ssgTexture * +FGTextureLoader::load_texture (const string &path) +{ + map::iterator it = _table.find(path); + if (it == _table.end()) { + _table[path] = new ssgTexture((char *)path.c_str()); // FIXME wrapu/v + it = _table.find(path); + it->second->ref(); // add one reference to keep it around + } + return (ssgTexture *)it->second; +} + + +// end of loader.cxx diff --git a/src/Model/loader.hxx b/src/Model/loader.hxx new file mode 100644 index 000000000..bbacbecf7 --- /dev/null +++ b/src/Model/loader.hxx @@ -0,0 +1,58 @@ +#ifndef __MODEL_LOADER_HXX +#define __MODEL_LOADER_HXX 1 + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include // for SG_USING_STD + +#include +SG_USING_STD(map); + +#include +SG_USING_STD(string); + +#include + + +/** + * Base class for loading and managing SSG things. + */ +class FGSSGLoader +{ +public: + FGSSGLoader (); + virtual ~FGSSGLoader (); + virtual void flush (); +protected: + map _table; +}; + + +/** + * Class for loading and managing models with XML wrappers. + */ +class FGModelLoader : public FGSSGLoader +{ +public: + FGModelLoader (); + virtual ~FGModelLoader (); + + virtual ssgEntity * load_model (const string &path); +}; + + +/** + * Class for loading and managing textures. + */ +class FGTextureLoader : public FGSSGLoader +{ +public: + FGTextureLoader (); + virtual ~FGTextureLoader (); + + virtual ssgTexture * load_texture (const string &path); +}; + +#endif diff --git a/src/Model/model.cxx b/src/Model/model.cxx index 8e20a812a..84fdc229c 100644 --- a/src/Model/model.cxx +++ b/src/Model/model.cxx @@ -34,6 +34,17 @@ // Static utility functions. //////////////////////////////////////////////////////////////////////// +/** + * Callback to update an animation. + */ +static int +animation_callback (ssgEntity * entity, int mask) +{ + ((Animation *)entity->getUserData())->update(); + return true; +} + + /** * Locate a named SSG node in a branch. */ @@ -161,29 +172,60 @@ read_interpolation_table (const SGPropertyNode * props) } - -//////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel -//////////////////////////////////////////////////////////////////////// - -FG3DModel::FG3DModel () - : _model(0) +static void +make_animation (ssgBranch * model, + const char * object_name, + SGPropertyNode * node) { + Animation * animation = 0; + const char * type = node->getStringValue("type"); + if (!strcmp("none", type)) { + animation = new NullAnimation(node); + } else if (!strcmp("range", type)) { + animation = new RangeAnimation(node); + } else if (!strcmp("billboard", type)) { + animation = new BillboardAnimation(node); + } else if (!strcmp("select", type)) { + animation = new SelectAnimation(node); + } else if (!strcmp("spin", type)) { + animation = new SpinAnimation(node); + } else if (!strcmp("rotate", type)) { + animation = new RotateAnimation(node); + } else if (!strcmp("translate", type)) { + animation = new TranslateAnimation(node); + } else { + animation = new NullAnimation(node); + SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); + } + + ssgEntity * object; + if (object_name != 0) { + object = find_named_node(model, object_name); + if (object == 0) { + SG_LOG(SG_INPUT, SG_WARN, "Object " << object_name << " not found"); + delete animation; + animation = 0; + } + } else { + object = model; + } + + ssgBranch * branch = animation->getBranch(); + splice_branch(branch, object); + branch->setUserData(animation); + branch->setTravCallback(SSG_CALLBACK_PRETRAV, animation_callback); } -FG3DModel::~FG3DModel () -{ - // since the nodes are attached to the scene graph, they'll be - // deleted automatically - unsigned int i; - for (i = 0; i < _animations.size(); i++) - delete _animations[i]; -} + +//////////////////////////////////////////////////////////////////////// +// Global functions. +//////////////////////////////////////////////////////////////////////// -void -FG3DModel::init (const string &path) +ssgBranch * +fgLoad3DModel (const string &path) { + ssgBranch * model = 0; SGPropertyNode props; // Load the 3D aircraft object itself @@ -198,23 +240,23 @@ FG3DModel::init (const string &path) modelpath = modelpath.dir(); modelpath.append(props.getStringValue("/path")); } else { - if (_model == 0) - _model = new ssgBranch; + if (model == 0) + model = new ssgBranch; } } // Assume that textures are in // the same location as the XML file. - if (_model == 0) { + if (model == 0) { ssgTexturePath((char *)xmlpath.dir().c_str()); - _model = (ssgBranch *)ssgLoad((char *)modelpath.c_str()); - if (_model == 0) + model = (ssgBranch *)ssgLoad((char *)modelpath.c_str()); + if (model == 0) throw sg_exception("Failed to load 3D model"); } // Set up the alignment node ssgTransform * align = new ssgTransform; - align->addKid(_model); + align->addKid(model); sgMat4 res_matrix; make_offsets_matrix(&res_matrix, props.getFloatValue("/offsets/heading-deg", 0.0), @@ -232,15 +274,10 @@ FG3DModel::init (const string &path) vector name_nodes = animation_nodes[i]->getChildren("object-name"); if (name_nodes.size() < 1) { - Animation * animation = make_animation(0, animation_nodes[i]); - if (animation != 0) - _animations.push_back(animation); + make_animation(model, 0, animation_nodes[i]); } else { for (unsigned int j = 0; j < name_nodes.size(); j++) { - Animation * animation = - make_animation(name_nodes[j]->getStringValue(), animation_nodes[i]); - if (animation != 0) - _animations.push_back(animation); + make_animation(model, name_nodes[j]->getStringValue(), animation_nodes[i]); } } } @@ -250,7 +287,7 @@ FG3DModel::init (const string &path) for (i = 0; i < panel_nodes.size(); i++) { printf("Reading a panel in model.cxx\n"); FGPanelNode * panel = new FGPanelNode(panel_nodes[i]); - _model->addKid(panel); + model->addKid(panel); } // Load sub-models @@ -267,255 +304,157 @@ FG3DModel::init (const string &path) node->getFloatValue("offsets/y-m", 0.0), node->getFloatValue("offsets/z-m", 0.0)); align->setTransform(res_matrix); - FG3DModel * kid = new FG3DModel; - kid->init(node->getStringValue("path")); - align->addKid(kid->getSceneGraph()); - _model->addKid(align); - _children.push_back(kid); - } -} - -void -FG3DModel::update (double dt) -{ - unsigned int i; - - for (i = 0; i < _children.size(); i++) - _children[i]->update(dt); - for (i = 0; i < _animations.size(); i++) - _animations[i]->update(dt); -} -FG3DModel::Animation * -FG3DModel::make_animation (const char * object_name, - SGPropertyNode * node) -{ - Animation * animation = 0; - const char * type = node->getStringValue("type"); - if (!strcmp("none", type)) { - animation = new NullAnimation(); - } else if (!strcmp("range", type)) { - animation = new RangeAnimation(); - } else if (!strcmp("billboard", type)) { - animation = new BillboardAnimation(); - } else if (!strcmp("select", type)) { - animation = new SelectAnimation(); - } else if (!strcmp("spin", type)) { - animation = new SpinAnimation(); - } else if (!strcmp("rotate", type)) { - animation = new RotateAnimation(); - } else if (!strcmp("translate", type)) { - animation = new TranslateAnimation(); - } else { - animation = new NullAnimation(); - SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); + ssgBranch * kid = fgLoad3DModel(node->getStringValue("path")); + align->addKid(kid); + model->addKid(align); } - ssgEntity * object; - if (object_name != 0) { - object = find_named_node(_model, object_name); - if (object == 0) { - SG_LOG(SG_INPUT, SG_WARN, "Object " << object_name << " not found"); - delete animation; - animation = 0; - } - } else { - object = _model; - } - - if (animation != 0) - animation->init(object, node); - return animation; + return model; } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::Animation +// Implementation of Animation //////////////////////////////////////////////////////////////////////// -FG3DModel::Animation::Animation () +Animation::Animation (SGPropertyNode_ptr props, ssgBranch * branch) + : _branch(branch) { + _branch->setName(props->getStringValue("name", 0)); } -FG3DModel::Animation::~Animation () +Animation::~Animation () { } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::NullAnimation +// Implementation of NullAnimation //////////////////////////////////////////////////////////////////////// -FG3DModel::NullAnimation::NullAnimation () - : _branch(new ssgBranch) -{ -} - -FG3DModel::NullAnimation::~NullAnimation () +NullAnimation::NullAnimation (SGPropertyNode_ptr props) + : Animation(props, new ssgBranch) { - _branch = 0; } -void -FG3DModel::NullAnimation::init (ssgEntity * object, - SGPropertyNode * props) +NullAnimation::~NullAnimation () { - splice_branch(_branch, object); - _branch->setName(props->getStringValue("name", 0)); } void -FG3DModel::NullAnimation::update (double dt) +NullAnimation::update () { } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::RangeAnimation +// Implementation of RangeAnimation //////////////////////////////////////////////////////////////////////// -FG3DModel::RangeAnimation::RangeAnimation () - : _branch(new ssgRangeSelector) -{ -} - -FG3DModel::RangeAnimation::~RangeAnimation () +RangeAnimation::RangeAnimation (SGPropertyNode_ptr props) + : Animation(props, new ssgRangeSelector) { - _branch = 0; + float ranges[] = { props->getFloatValue("min-m", 0), + props->getFloatValue("max-m", 5000) }; + ((ssgRangeSelector *)_branch)->setRanges(ranges, 2); + } -void -FG3DModel::RangeAnimation::init (ssgEntity * object, - SGPropertyNode * props) +RangeAnimation::~RangeAnimation () { - float ranges[2]; - splice_branch(_branch, object); - _branch->setName(props->getStringValue("name", 0)); - ranges[0] = props->getFloatValue("min-m", 0); - ranges[1] = props->getFloatValue("max-m", 5000); - _branch->setRanges(ranges, 2); } void -FG3DModel::RangeAnimation::update (double dt) +RangeAnimation::update () { } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::BillboardAnimation +// Implementation of BillboardAnimation //////////////////////////////////////////////////////////////////////// -FG3DModel::BillboardAnimation::BillboardAnimation () - : _branch(0) -{ - // Note: we cannot allocate the branch until we know whether - // it can rotate around the x axis as well as the z axis. -} - -FG3DModel::BillboardAnimation::~BillboardAnimation () +BillboardAnimation::BillboardAnimation (SGPropertyNode_ptr props) + : Animation(props, new ssgCutout(props->getBoolValue("spherical", true))) { - _branch = 0; } -void -FG3DModel::BillboardAnimation::init (ssgEntity * object, - SGPropertyNode * props) +BillboardAnimation::~BillboardAnimation () { - _branch = new ssgCutout(props->getBoolValue("spherical", true)); - splice_branch(_branch, object); - _branch->setName(props->getStringValue("name", 0)); } void -FG3DModel::BillboardAnimation::update (double dt) +BillboardAnimation::update () { } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::SelectAnimation +// Implementation of SelectAnimation //////////////////////////////////////////////////////////////////////// -FG3DModel::SelectAnimation::SelectAnimation () - : _condition(0), - _selector(new ssgSelector) +SelectAnimation::SelectAnimation (SGPropertyNode_ptr props) + : Animation(props, new ssgSelector), + _condition(0) { + SGPropertyNode * node = props->getChild("condition"); + if (node != 0) + _condition = fgReadCondition(node); } -FG3DModel::SelectAnimation::~SelectAnimation () +SelectAnimation::~SelectAnimation () { delete _condition; - _selector = 0; -} - -void -FG3DModel::SelectAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - splice_branch(_selector, object); - _selector->setName(props->getStringValue("name", 0)); - SGPropertyNode * node = props->getChild("condition"); - if (node != 0) { - _condition = fgReadCondition(node); - } } void -FG3DModel::SelectAnimation::update (double dt) +SelectAnimation::update () { if (_condition != 0 && _condition->test()) - _selector->select(0xffff); + ((ssgSelector *)_branch)->select(0xffff); else - _selector->select(0x0000); + ((ssgSelector *)_branch)->select(0x0000); } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::SpinAnimation +// Implementation of SpinAnimation //////////////////////////////////////////////////////////////////////// -FG3DModel::SpinAnimation::SpinAnimation () - : _prop(0), - _factor(0), - _position_deg(0), - _transform(new ssgTransform) +SpinAnimation::SpinAnimation (SGPropertyNode_ptr props) + : Animation(props, new ssgTransform), + _prop(fgGetNode(props->getStringValue("property", "/null"), true)), + _factor(props->getDoubleValue("factor", 1.0)), + _position_deg(props->getDoubleValue("starting-position-deg", 0)), + _last_time_sec(globals->get_sim_time_sec()) { + _center[0] = props->getFloatValue("center/x-m", 0); + _center[1] = props->getFloatValue("center/y-m", 0); + _center[2] = props->getFloatValue("center/z-m", 0); + _axis[0] = props->getFloatValue("axis/x", 0); + _axis[1] = props->getFloatValue("axis/y", 0); + _axis[2] = props->getFloatValue("axis/z", 0); + sgNormalizeVec3(_axis); } -FG3DModel::SpinAnimation::~SpinAnimation () +SpinAnimation::~SpinAnimation () { - _transform = 0; -} - -void -FG3DModel::SpinAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - // Splice in the new transform node - splice_branch(_transform, object); - _transform->setName(props->getStringValue("name", 0)); - _prop = fgGetNode(props->getStringValue("property", "/null"), true); - _factor = props->getDoubleValue("factor", 1.0); - _position_deg = props->getDoubleValue("starting-position-deg", 0); - _center[0] = props->getFloatValue("center/x-m", 0); - _center[1] = props->getFloatValue("center/y-m", 0); - _center[2] = props->getFloatValue("center/z-m", 0); - _axis[0] = props->getFloatValue("axis/x", 0); - _axis[1] = props->getFloatValue("axis/y", 0); - _axis[2] = props->getFloatValue("axis/z", 0); - sgNormalizeVec3(_axis); } void -FG3DModel::SpinAnimation::update (double dt) +SpinAnimation::update () { + double sim_time = globals->get_sim_time_sec(); + double dt = sim_time - _last_time_sec; + _last_time_sec = sim_time; + float velocity_rpms = (_prop->getDoubleValue() * _factor / 60.0); _position_deg += (dt * velocity_rpms * 360); while (_position_deg < 0) @@ -523,55 +462,27 @@ FG3DModel::SpinAnimation::update (double dt) while (_position_deg >= 360.0) _position_deg -= 360.0; set_rotation(_matrix, _position_deg, _center, _axis); - _transform->setTransform(_matrix); + ((ssgTransform *)_branch)->setTransform(_matrix); } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::RotateAnimation +// Implementation of RotateAnimation //////////////////////////////////////////////////////////////////////// -FG3DModel::RotateAnimation::RotateAnimation () - : _prop(0), - _offset_deg(0.0), - _factor(1.0), - _table(0), - _has_min(false), - _min_deg(0.0), - _has_max(false), - _max_deg(1.0), - _position_deg(0.0), - _transform(new ssgTransform) -{ -} - -FG3DModel::RotateAnimation::~RotateAnimation () +RotateAnimation::RotateAnimation (SGPropertyNode_ptr props) + : Animation(props, new ssgTransform), + _prop(fgGetNode(props->getStringValue("property", "/null"), true)), + _offset_deg(props->getDoubleValue("offset-deg", 0.0)), + _factor(props->getDoubleValue("factor", 1.0)), + _table(read_interpolation_table(props)), + _has_min(props->hasValue("min-deg")), + _min_deg(props->getDoubleValue("min-deg")), + _has_max(props->hasValue("max-deg")), + _max_deg(props->getDoubleValue("max-deg")), + _position_deg(props->getDoubleValue("starting-position-deg", 0)) { - delete _table; - _transform = 0; -} - -void -FG3DModel::RotateAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - // Splice in the new transform node - splice_branch(_transform, object); - _transform->setName(props->getStringValue("name", 0)); - _prop = fgGetNode(props->getStringValue("property", "/null"), true); - _offset_deg = props->getDoubleValue("offset-deg", 0.0); - _factor = props->getDoubleValue("factor", 1.0); - _table = read_interpolation_table(props); - if (props->hasValue("min-deg")) { - _has_min = true; - _min_deg = props->getDoubleValue("min-deg"); - } - if (props->hasValue("max-deg")) { - _has_max = true; - _max_deg = props->getDoubleValue("max-deg"); - } - _position_deg = props->getDoubleValue("starting-position-deg", 0); _center[0] = props->getFloatValue("center/x-m", 0); _center[1] = props->getFloatValue("center/y-m", 0); _center[2] = props->getFloatValue("center/z-m", 0); @@ -581,8 +492,13 @@ FG3DModel::RotateAnimation::init (ssgEntity * object, sgNormalizeVec3(_axis); } +RotateAnimation::~RotateAnimation () +{ + delete _table; +} + void -FG3DModel::RotateAnimation::update (double dt) +RotateAnimation::update () { if (_table == 0) { _position_deg = (_prop->getDoubleValue() + _offset_deg) * _factor; @@ -594,63 +510,40 @@ FG3DModel::RotateAnimation::update (double dt) _position_deg = _table->interpolate(_prop->getDoubleValue()); } set_rotation(_matrix, _position_deg, _center, _axis); - _transform->setTransform(_matrix); + ((ssgTransform *)_branch)->setTransform(_matrix); } //////////////////////////////////////////////////////////////////////// -// Implementation of FG3DModel::TranslateAnimation +// Implementation of TranslateAnimation //////////////////////////////////////////////////////////////////////// -FG3DModel::TranslateAnimation::TranslateAnimation () - : _prop(0), - _offset_m(0.0), - _factor(1.0), - _table(0), - _has_min(false), - _min_m(0.0), - _has_max(false), - _max_m(1.0), - _position_m(0.0), - _transform(new ssgTransform) -{ -} - -FG3DModel::TranslateAnimation::~TranslateAnimation () +TranslateAnimation::TranslateAnimation (SGPropertyNode_ptr props) + : Animation(props, new ssgTransform), + _prop(fgGetNode(props->getStringValue("property", "/null"), true)), + _offset_m(props->getDoubleValue("offset-m", 0.0)), + _factor(props->getDoubleValue("factor", 1.0)), + _table(read_interpolation_table(props)), + _has_min(props->hasValue("min-m")), + _min_m(props->getDoubleValue("min-m")), + _has_max(props->hasValue("max-m")), + _max_m(props->getDoubleValue("max-m")), + _position_m(props->getDoubleValue("starting-position-m", 0)) { - delete _table; - _transform = 0; -} - -void -FG3DModel::TranslateAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - // Splice in the new transform node - splice_branch(_transform, object); - _transform->setName(props->getStringValue("name", 0)); - _prop = fgGetNode(props->getStringValue("property", "/null"), true); - _offset_m = props->getDoubleValue("offset-m", 0.0); - _factor = props->getDoubleValue("factor", 1.0); - _table = read_interpolation_table(props); - if (props->hasValue("min-m")) { - _has_min = true; - _min_m = props->getDoubleValue("min-m"); - } - if (props->hasValue("max-m")) { - _has_max = true; - _max_m = props->getDoubleValue("max-m"); - } - _position_m = props->getDoubleValue("starting-position-m", 0); _axis[0] = props->getFloatValue("axis/x", 0); _axis[1] = props->getFloatValue("axis/y", 0); _axis[2] = props->getFloatValue("axis/z", 0); sgNormalizeVec3(_axis); } +TranslateAnimation::~TranslateAnimation () +{ + delete _table; +} + void -FG3DModel::TranslateAnimation::update (double dt) +TranslateAnimation::update () { if (_table == 0) { _position_m = (_prop->getDoubleValue() + _offset_m) * _factor; @@ -662,7 +555,7 @@ FG3DModel::TranslateAnimation::update (double dt) _position_m = _table->interpolate(_prop->getDoubleValue()); } set_translation(_matrix, _position_m, _axis); - _transform->setTransform(_matrix); + ((ssgTransform *)_branch)->setTransform(_matrix); } @@ -672,8 +565,7 @@ FG3DModel::TranslateAnimation::update (double dt) //////////////////////////////////////////////////////////////////////// FGModelPlacement::FGModelPlacement () - : _model(new FG3DModel), - _lon_deg(0), + : _lon_deg(0), _lat_deg(0), _elev_ft(0), _roll_deg(0), @@ -687,24 +579,21 @@ FGModelPlacement::FGModelPlacement () FGModelPlacement::~FGModelPlacement () { - delete _model; - delete _selector; } void FGModelPlacement::init (const string &path) { - _model->init(path); - _position->addKid(_model->getSceneGraph()); + ssgBranch * model = fgLoad3DModel(path); + if (model != 0) + _position->addKid(model); _selector->addKid(_position); _selector->clrTraversalMaskBits(SSGTRAV_HOT); } void -FGModelPlacement::update (double dt) +FGModelPlacement::update () { - _model->update(dt); - _location->setPosition( _lon_deg, _lat_deg, _elev_ft ); _location->setOrientation( _roll_deg, _pitch_deg, _heading_deg ); diff --git a/src/Model/model.hxx b/src/Model/model.hxx index cc5142519..edfbfdae0 100644 --- a/src/Model/model.hxx +++ b/src/Model/model.hxx @@ -15,6 +15,7 @@ SG_USING_STD(vector); #include +#include // Don't pull in the headers, since we don't need them here. @@ -40,210 +41,182 @@ class FGLocation; #endif -class FG3DModel -{ -public: - - FG3DModel (); - virtual ~FG3DModel (); - - virtual void init (const string &path); - virtual void update (double dt); - - virtual ssgEntity * getSceneGraph () const { return (ssgEntity *)_model; } - -private: +/** + * Load a 3D model with or without XML wrapper. + * + * 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. + */ +ssgBranch * fgLoad3DModel (const string &path); - class Animation; - Animation * make_animation (const char * object_name, SGPropertyNode * node); - // Child models. - vector _children; + +////////////////////////////////////////////////////////////////////// +// Animation classes +////////////////////////////////////////////////////////////////////// - // Animations - vector _animations; - - // Scene graph - ssgBranch * _model; +/** + * Abstract base class for all animations. + */ +class Animation : public ssgBase +{ +public: + Animation (SGPropertyNode_ptr props, ssgBranch * branch); - - ////////////////////////////////////////////////////////////////////// - // Internal classes for individual animations. - ////////////////////////////////////////////////////////////////////// + virtual ~Animation (); /** - * Abstract base class for all animations. + * Get the SSG branch holding the animation. */ - class Animation - { - public: - - Animation (); - - virtual ~Animation (); - - /** - * Initialize the animation. - * - * @param object The object to animate. - * @param props The property node with configuration information. - */ - virtual void init (ssgEntity * object, SGPropertyNode * props) = 0; + virtual ssgBranch * getBranch () { return _branch; } + /** + * Update the animation. + */ + virtual void update () = 0; - /** - * Update the animation. - * - * @param dt The elapsed time in seconds since the last call. - */ - virtual void update (double dt) = 0; +protected: - }; + ssgBranch * _branch; +}; - /** - * A no-op animation. - */ - class NullAnimation : public Animation - { - public: - NullAnimation (); - virtual ~NullAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (double dt); - private: - ssgBranch * _branch; - }; - - /** - * A range, or level-of-detail (LOD) animation. - */ - class RangeAnimation : public Animation - { - public: - RangeAnimation (); - virtual ~RangeAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (double dt); - private: - ssgRangeSelector * _branch; - }; +/** + * A no-op animation. + */ +class NullAnimation : public Animation +{ +public: + NullAnimation (SGPropertyNode_ptr props); + virtual ~NullAnimation (); + virtual void update (); +}; - /** - * Animation to turn and face the screen. - */ - class BillboardAnimation : public Animation - { - public: - BillboardAnimation (); - virtual ~BillboardAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (double dt); - private: - ssgCutout * _branch; - }; +/** + * A range, or level-of-detail (LOD) animation. + */ +class RangeAnimation : public Animation +{ +public: + RangeAnimation (SGPropertyNode_ptr props); + virtual ~RangeAnimation (); + virtual void update (); +}; - /** - * Animation to select alternative versions of the same object. - */ - class SelectAnimation : public Animation - { - public: - SelectAnimation (); - virtual ~SelectAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (double dt); - private: - FGCondition * _condition; - ssgSelector * _selector; - }; +/** + * Animation to turn and face the screen. + */ +class BillboardAnimation : public Animation +{ +public: + BillboardAnimation (SGPropertyNode_ptr props); + virtual ~BillboardAnimation (); + virtual void update (); +}; - /** - * Animation to spin an object around a center point. - * - * This animation rotates at a specific velocity. - */ - class SpinAnimation : public Animation - { - public: - SpinAnimation (); - virtual ~SpinAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (double dt); - private: - SGPropertyNode * _prop; - double _factor; - double _position_deg; - sgMat4 _matrix; - sgVec3 _center; - sgVec3 _axis; - ssgTransform * _transform; - }; +/** + * Animation to select alternative versions of the same object. + */ +class SelectAnimation : public Animation +{ +public: + SelectAnimation (SGPropertyNode_ptr props); + virtual ~SelectAnimation (); + virtual void update (); +private: + FGCondition * _condition; +}; - /** - * Animation to rotate an object around a center point. - * - * This animation rotates to a specific position. - */ - class RotateAnimation : public Animation - { - public: - RotateAnimation (); - virtual ~RotateAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (double dt); - private: - SGPropertyNode * _prop; - double _offset_deg; - double _factor; - SGInterpTable * _table; - bool _has_min; - double _min_deg; - bool _has_max; - double _max_deg; - double _position_deg; - sgMat4 _matrix; - sgVec3 _center; - sgVec3 _axis; - ssgTransform * _transform; - }; +/** + * Animation to spin an object around a center point. + * + * This animation rotates at a specific velocity. + */ +class SpinAnimation : public Animation +{ +public: + SpinAnimation (SGPropertyNode_ptr props); + virtual ~SpinAnimation (); + virtual void update (); +private: + SGPropertyNode * _prop; + double _factor; + double _position_deg; + double _last_time_sec; + sgMat4 _matrix; + sgVec3 _center; + sgVec3 _axis; +}; - /** - * Animation to slide along an axis. - */ - class TranslateAnimation : public Animation - { - public: - TranslateAnimation (); - virtual ~TranslateAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (double dt); - private: - SGPropertyNode * _prop; - double _offset_m; - double _factor; - SGInterpTable * _table; - bool _has_min; - double _min_m; - bool _has_max; - double _max_m; - double _position_m; - sgMat4 _matrix; - sgVec3 _axis; - ssgTransform * _transform; - }; +/** + * Animation to rotate an object around a center point. + * + * This animation rotates to a specific position. + */ +class RotateAnimation : public Animation +{ +public: + RotateAnimation (SGPropertyNode_ptr props); + virtual ~RotateAnimation (); + virtual void update (); +private: + SGPropertyNode * _prop; + double _offset_deg; + double _factor; + SGInterpTable * _table; + bool _has_min; + double _min_deg; + bool _has_max; + double _max_deg; + double _position_deg; + sgMat4 _matrix; + sgVec3 _center; + sgVec3 _axis; +}; +/** + * Animation to slide along an axis. + */ +class TranslateAnimation : public Animation +{ +public: + TranslateAnimation (SGPropertyNode_ptr props); + virtual ~TranslateAnimation (); + virtual void update (); +private: + SGPropertyNode * _prop; + double _offset_m; + double _factor; + SGInterpTable * _table; + bool _has_min; + double _min_m; + bool _has_max; + double _max_m; + double _position_m; + sgMat4 _matrix; + sgVec3 _axis; }; + +//////////////////////////////////////////////////////////////////////// +// Model placement. +//////////////////////////////////////////////////////////////////////// + +/** + * A wrapper for a model with a definite placement. + */ class FGModelPlacement { public: @@ -252,7 +225,7 @@ public: virtual ~FGModelPlacement (); virtual void init (const string &path); - virtual void update (double dt); + virtual void update (); virtual ssgEntity * getSceneGraph () { return (ssgEntity *)_selector; } @@ -278,18 +251,16 @@ public: virtual void setPitchDeg (double pitch_deg); virtual void setHeadingDeg (double heading_deg); virtual void setOrientation (double roll_deg, double pitch_deg, - double heading_deg); + double heading_deg); private: - FG3DModel * _model; - - // Geodetic position + // Geodetic position double _lon_deg; double _lat_deg; double _elev_ft; - // Orientation + // Orientation double _roll_deg; double _pitch_deg; double _heading_deg; @@ -297,7 +268,7 @@ private: ssgSelector * _selector; ssgTransform * _position; - // Location + // Location FGLocation * _location; }; diff --git a/src/Model/modelmgr.cxx b/src/Model/modelmgr.cxx index ce15e6078..f3f7cc8e4 100644 --- a/src/Model/modelmgr.cxx +++ b/src/Model/modelmgr.cxx @@ -120,7 +120,7 @@ FGModelMgr::update (double dt) if (instance->heading_deg_node != 0) model->setHeadingDeg(instance->heading_deg_node->getDoubleValue()); - instance->model->update(dt); + instance->model->update(); } } diff --git a/src/NetworkOLK/net_send.cxx b/src/NetworkOLK/net_send.cxx index 2465d843c..788968828 100644 --- a/src/NetworkOLK/net_send.cxx +++ b/src/NetworkOLK/net_send.cxx @@ -42,6 +42,7 @@ #include #include
#include
+#include //#define printf // @@ -162,7 +163,7 @@ struct list_ele *new_ele; new_ele->fgd_sel = new ssgSelector; new_ele->fgd_pos = new ssgTransform; - ssgEntity *fgd_obj = ssgLoadAC( "tuxcopter.ac" ); + ssgEntity *fgd_obj = globals->get_model_loader()->load_model( "tuxcopter.ac" ); fgd_obj->clrTraversalMaskBits( SSGTRAV_HOT ); new_ele->fgd_pos->addKid( fgd_obj ); new_ele->fgd_sel->addKid( new_ele->fgd_pos ); diff --git a/src/Objects/newmat.cxx b/src/Objects/newmat.cxx index 270099830..96288fe87 100644 --- a/src/Objects/newmat.cxx +++ b/src/Objects/newmat.cxx @@ -43,37 +43,15 @@ SG_USING_STD(map); #include
#include
+#include #include "newmat.hxx" - -//////////////////////////////////////////////////////////////////////// -// Local static variables. -// FIXME: write a proper manager. -//////////////////////////////////////////////////////////////////////// - -// Objects already loaded (that can be reused). -map object_map; - - //////////////////////////////////////////////////////////////////////// // Local static functions. //////////////////////////////////////////////////////////////////////// -// FIXME: this is totally evil and non-robust: it assumes that -// entities will never be refcounted to 0 (which is safe for now). -static ssgEntity * -load_object (char * path) -{ - ssgEntity * object = object_map[path]; - if (object == 0) { - object = ssgLoad(path); - object_map[path] = object; - } - return object; -} - /** * Internal method to test whether a file exists. * @@ -154,28 +132,18 @@ FGNewMat::Object::load_models () const // Load model only on demand if (!_models_loaded) { for (int i = 0; i < _paths.size(); i++) { - -// Original -// SGPath path = globals->get_fg_root(); -// path.append(_paths[i]); -// ssgTexturePath((char *)path.dir().c_str()); -// ssgEntity * entity = load_object((char *)path.c_str()); - -// DCL - SGPath path = globals->get_fg_root(); - SGPath modelPath = _paths[i]; - path.append(_paths[i]); - ssgTexturePath((char *)path.dir().c_str()); - ssgEntity * entity = load_object((char *)modelPath.c_str()); + ssgEntity * entity = globals->get_model_loader()->load_model(_paths[i]); if (entity != 0) { - // entity->ref(); + // FIXME: this stuff can be handled + // in the XML wrapper as well (at least, + // the billboarding should be handled + // there). float ranges[] = {0, _range_m}; ssgRangeSelector * lod = new ssgRangeSelector; lod->ref(); lod->setRanges(ranges, 2); if (_heading_type == HEADING_BILLBOARD) { ssgCutout * cutout = new ssgCutout(false); - // cutout->ref(); cutout->addKid(entity); lod->addKid(cutout); } else { @@ -183,7 +151,7 @@ FGNewMat::Object::load_models () const } _models.push_back(lod); } else { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << path.str()); + SG_LOG(SG_INPUT, SG_ALERT, "Failed to load object " << _paths[i]); } } } diff --git a/src/Scenery/tilemgr.cxx b/src/Scenery/tilemgr.cxx index 767fcd8e5..8c3e6f548 100644 --- a/src/Scenery/tilemgr.cxx +++ b/src/Scenery/tilemgr.cxx @@ -43,6 +43,7 @@ #include
#include
#include
+#include #include #include "newcache.hxx" @@ -329,8 +330,7 @@ int FGTileMgr::update( double lon, double lat, double visibility_meters, #endif ssgTexturePath( (char *)(dm->get_texture_path().c_str()) ); - ssgEntity *obj_model - = ssgLoad( (char *)(dm->get_model_path().c_str()) ); + ssgEntity *obj_model = globals->get_model_loader()->load_model(dm->get_model_path()); if ( obj_model != NULL ) { dm->get_obj_trans()->addKid( obj_model ); }