X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2Fmodelmgr.cxx;h=2e6ad72bcdaf19b498301a6f7503859cd14c1d7f;hb=9c98258ab08b48420c86cf09c0f6ba9d1ff82700;hp=90fd78cc229aa04f76a07b4046062226b449d1ef;hpb=dcac4d7e323e7ecdf8525c62cf8b6c71fbc4c6ee;p=flightgear.git diff --git a/src/Model/modelmgr.cxx b/src/Model/modelmgr.cxx index 90fd78cc2..2e6ad72bc 100644 --- a/src/Model/modelmgr.cxx +++ b/src/Model/modelmgr.cxx @@ -3,85 +3,137 @@ // // This file is in the Public Domain, and comes with no warranty. -#include "modelmgr.hxx" +#ifdef _MSC_VER +# pragma warning( disable: 4355 ) +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include #include
+#include + + +#include "modelmgr.hxx" +using std::vector; + +using namespace simgear; + +// OSGFIXME +// extern SGShadowVolume *shadows; FGModelMgr::FGModelMgr () - : _scene(new ssgRoot), - _nearplane(0.5f), - _farplane(120000.0f) + : _models(fgGetNode("/models", true)), + _listener(new Listener(this)) { + _models->addChangeListener(_listener); } FGModelMgr::~FGModelMgr () { - for (int i = 0; i < _instances.size(); i++) { + _models->removeChangeListener(_listener); + delete _listener; + + for (unsigned int i = 0; i < _instances.size(); i++) { + globals->get_scenery()->get_scene_graph() + ->removeChild(_instances[i]->model->getSceneGraph()); delete _instances[i]; } - delete _scene; } void FGModelMgr::init () { - vector model_nodes = - fgGetNode("/models", true)->getChildren("model"); - for (int i = 0; i < model_nodes.size(); i++) { - SGPropertyNode * node = model_nodes[i]; - SG_LOG(SG_GENERAL, SG_INFO, - "Adding model " << node->getStringValue("name", "[unnamed]")); - Instance * instance = new Instance; - FG3DModel * model = new FG3DModel; - instance->model = model; - model->init(node->getStringValue("path", "Models/Geometry/glider.ac")); + vector model_nodes = _models->getChildren("model"); + + for (unsigned int i = 0; i < model_nodes.size(); i++) + add_model(model_nodes[i]); +} + +void +FGModelMgr::add_model (SGPropertyNode * node) +{ + SG_LOG(SG_GENERAL, SG_INFO, + "Adding model " << node->getStringValue("name", "[unnamed]")); + + const char *path = node->getStringValue("path", "Models/Geometry/glider.ac"); + osg::Node *object; + + try { + object = SGModelLib::loadPagedModel(path, globals->get_props()); + } catch (const sg_throwable& t) { + SG_LOG(SG_GENERAL, SG_ALERT, "Error loading " << path << ":\n " + << t.getFormattedMessage() << t.getOrigin()); + return; + } + + Instance * instance = new Instance; + SGModelPlacement *model = new SGModelPlacement; + instance->model = model; + instance->node = node; + + model->init( object ); // Set position and orientation either // indirectly through property refs // or directly with static values. - SGPropertyNode * child = node->getChild("longitude-deg-prop"); - if (child != 0) - instance->lon_deg_node = fgGetNode(child->getStringValue(), true); - else - model->setLongitudeDeg(node->getDoubleValue("longitude-deg")); - - child = node->getChild("latitude-deg-prop"); - if (child != 0) - instance->lat_deg_node = fgGetNode(child->getStringValue(), true); - else - model->setLatitudeDeg(node->getDoubleValue("latitude-deg")); - - child = node->getChild("elevation-ft-prop"); - if (child != 0) - instance->elev_ft_node = fgGetNode(child->getStringValue(), true); - else - model->setElevationFt(node->getDoubleValue("elevation-ft")); - - child = node->getChild("roll-deg-prop"); - if (child != 0) - instance->roll_deg_node = fgGetNode(child->getStringValue(), true); - else - model->setRollDeg(node->getDoubleValue("roll-deg")); - - child = node->getChild("pitch-deg-prop"); - if (child != 0) - instance->pitch_deg_node = fgGetNode(child->getStringValue(), true); - else - model->setPitchDeg(node->getDoubleValue("pitch-deg")); - - child = node->getChild("heading-deg-prop"); - if (child != 0) - instance->heading_deg_node = fgGetNode(child->getStringValue(), true); - else - model->setHeadingDeg(node->getDoubleValue("heading-deg")); - - // Add this model to the scene graph - _scene->addKid(model->getSceneGraph()); - - // Save this instance for updating - _instances.push_back(instance); - } + SGPropertyNode * child = node->getChild("longitude-deg-prop"); + if (child != 0) + instance->lon_deg_node = fgGetNode(child->getStringValue(), true); + else + model->setLongitudeDeg(node->getDoubleValue("longitude-deg")); + + child = node->getChild("latitude-deg-prop"); + if (child != 0) + instance->lat_deg_node = fgGetNode(child->getStringValue(), true); + else + model->setLatitudeDeg(node->getDoubleValue("latitude-deg")); + + child = node->getChild("elevation-ft-prop"); + if (child != 0) + instance->elev_ft_node = fgGetNode(child->getStringValue(), true); + else + model->setElevationFt(node->getDoubleValue("elevation-ft")); + + child = node->getChild("roll-deg-prop"); + if (child != 0) + instance->roll_deg_node = fgGetNode(child->getStringValue(), true); + else + model->setRollDeg(node->getDoubleValue("roll-deg")); + + child = node->getChild("pitch-deg-prop"); + if (child != 0) + instance->pitch_deg_node = fgGetNode(child->getStringValue(), true); + else + model->setPitchDeg(node->getDoubleValue("pitch-deg")); + + child = node->getChild("heading-deg-prop"); + if (child != 0) + instance->heading_deg_node = fgGetNode(child->getStringValue(), true); + else + model->setHeadingDeg(node->getDoubleValue("heading-deg")); + + // Add this model to the global scene graph + globals->get_scenery()->get_scene_graph()->addChild(model->getSceneGraph()); + + + // Save this instance for updating + add_instance(instance); } void @@ -94,40 +146,90 @@ FGModelMgr::unbind () { } +namespace +{ +double testNan(double val) throw (sg_range_exception) +{ + if (osg::isNaN(val)) + throw sg_range_exception("value is nan"); + return val; +} + +struct UpdateFunctor : public std::unary_function +{ + void operator()(FGModelMgr::Instance* instance) const + { + SGModelPlacement* model = instance->model; + double lon, lat, elev, roll, pitch, heading; + + try { + // Optionally set position from properties + if (instance->lon_deg_node != 0) + lon = testNan(instance->lon_deg_node->getDoubleValue()); + if (instance->lat_deg_node != 0) + lat = testNan(instance->lat_deg_node->getDoubleValue()); + if (instance->elev_ft_node != 0) + elev = testNan(instance->elev_ft_node->getDoubleValue()); + + // Optionally set orientation from properties + if (instance->roll_deg_node != 0) + roll = testNan(instance->roll_deg_node->getDoubleValue()); + if (instance->pitch_deg_node != 0) + pitch = testNan(instance->pitch_deg_node->getDoubleValue()); + if (instance->heading_deg_node != 0) + heading = testNan(instance->heading_deg_node->getDoubleValue()); + } catch (const sg_range_exception&) { + const char *path = instance->node->getStringValue("path", + "unknown"); + SG_LOG(SG_GENERAL, SG_INFO, "Instance of model " << path + << " has invalid values"); + return; + } + // Optionally set position from properties + if (instance->lon_deg_node != 0) + model->setLongitudeDeg(lon); + if (instance->lat_deg_node != 0) + model->setLatitudeDeg(lat); + if (instance->elev_ft_node != 0) + model->setElevationFt(elev); + + // Optionally set orientation from properties + if (instance->roll_deg_node != 0) + model->setRollDeg(roll); + if (instance->pitch_deg_node != 0) + model->setPitchDeg(pitch); + if (instance->heading_deg_node != 0) + model->setHeadingDeg(heading); + + instance->model->update(); + } +}; +} + void -FGModelMgr::update (int dt) -{ - for (int i = 0; i < _instances.size(); i++) { - Instance * instance = _instances[i]; - FG3DModel * model = instance->model; - - // Optionally set position from properties - if (instance->lon_deg_node != 0) - model->setLongitudeDeg(instance->lon_deg_node->getDoubleValue()); - if (instance->lat_deg_node != 0) - model->setLatitudeDeg(instance->lat_deg_node->getDoubleValue()); - if (instance->elev_ft_node != 0) - model->setElevationFt(instance->elev_ft_node->getDoubleValue()); - - // Optionally set orientation from properties - if (instance->roll_deg_node != 0) - model->setRollDeg(instance->roll_deg_node->getDoubleValue()); - if (instance->pitch_deg_node != 0) - model->setPitchDeg(instance->pitch_deg_node->getDoubleValue()); - if (instance->heading_deg_node != 0) - model->setHeadingDeg(instance->heading_deg_node->getDoubleValue()); - - instance->model->update(dt); - } +FGModelMgr::update (double dt) +{ + std::for_each(_instances.begin(), _instances.end(), UpdateFunctor()); } void -FGModelMgr::draw () +FGModelMgr::add_instance (Instance * instance) { - ssgSetNearFar(_nearplane, _farplane); - ssgCullAndDraw(_scene); + _instances.push_back(instance); } +void +FGModelMgr::remove_instance (Instance * instance) +{ + vector::iterator it; + for (it = _instances.begin(); it != _instances.end(); it++) { + if (*it == instance) { + _instances.erase(it); + delete instance; + return; + } + } +} //////////////////////////////////////////////////////////////////////// @@ -136,12 +238,14 @@ FGModelMgr::draw () FGModelMgr::Instance::Instance () : model(0), + node(0), lon_deg_node(0), lat_deg_node(0), elev_ft_node(0), roll_deg_node(0), pitch_deg_node(0), - heading_deg_node(0) + heading_deg_node(0), + shadow(false) { } @@ -150,4 +254,46 @@ FGModelMgr::Instance::~Instance () delete model; } + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGModelMgr::Listener +//////////////////////////////////////////////////////////////////////// + +void +FGModelMgr::Listener::childAdded(SGPropertyNode * parent, SGPropertyNode * child) +{ + if (strcmp(parent->getName(), "model") || strcmp(child->getName(), "load")) + return; + + _mgr->add_model(parent); +} + +void +FGModelMgr::Listener::childRemoved(SGPropertyNode * parent, SGPropertyNode * child) +{ + if (strcmp(parent->getName(), "models") || strcmp(child->getName(), "model")) + return; + + // search instance by node and remove it from scenegraph + vector::iterator it = _mgr->_instances.begin(); + vector::iterator end = _mgr->_instances.end(); + + for (; it != end; ++it) { + Instance *instance = *it; + if (instance->node != child) + continue; + + _mgr->_instances.erase(it); + osg::Node *branch = instance->model->getSceneGraph(); + // OSGFIXME +// if (shadows && instance->shadow) +// shadows->deleteOccluder(branch); + globals->get_scenery()->get_scene_graph()->removeChild(branch); + + delete instance; + break; + } +} + // end of modelmgr.cxx