"Fossies" - the Fresh Open Source Software Archive

Member "flightgear-2020.3.8/src/Model/modelmgr.cxx" (24 Mar 2021, 8968 Bytes) of package /linux/privat/flightgear-2020.3.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "modelmgr.cxx" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2020.3.7_vs_2020.3.8.

    1 // modelmgr.cxx - manage a collection of 3D models.
    2 // Written by David Megginson, started 2002.
    3 //
    4 // This file is in the Public Domain, and comes with no warranty.
    5 
    6 #ifdef _MSC_VER
    7 #  pragma warning( disable: 4355 )
    8 #endif
    9 
   10 #ifdef HAVE_CONFIG_H
   11 #  include <config.h>
   12 #endif
   13 
   14 #include <simgear/compiler.h>
   15 
   16 #include <algorithm>
   17 #include <functional>
   18 #include <vector>
   19 #include <cstring>
   20 
   21 #include <simgear/scene/model/placement.hxx>
   22 #include <simgear/scene/model/modellib.hxx>
   23 #include <simgear/structure/exception.hxx>
   24 
   25 #include <Main/fg_props.hxx>
   26 #include <Scenery/scenery.hxx>
   27 
   28 
   29 #include "modelmgr.hxx"
   30 
   31 using namespace simgear;
   32 
   33 // OSGFIXME
   34 // extern SGShadowVolume *shadows;
   35 
   36 FGModelMgr::FGModelMgr ()
   37 {
   38 }
   39 
   40 FGModelMgr::~FGModelMgr ()
   41 {
   42 }
   43 
   44 void
   45 FGModelMgr::init ()
   46 {
   47     std::vector<SGPropertyNode_ptr> model_nodes = _models->getChildren("model");
   48 
   49   for (unsigned int i = 0; i < model_nodes.size(); i++)
   50       add_model(model_nodes[i]);
   51 }
   52 
   53 void FGModelMgr::shutdown()
   54 {
   55     osg::Group *scene_graph = NULL;
   56     if (globals->get_scenery()) {
   57         scene_graph = globals->get_scenery()->get_scene_graph();
   58     }
   59 
   60     // always delete instances, even if the scene-graph is gone
   61     for (unsigned int i = 0; i < _instances.size(); i++) {
   62         if (scene_graph) {
   63             scene_graph->removeChild(_instances[i]->model->getSceneGraph());
   64         }
   65 
   66         delete _instances[i];
   67     }
   68 }
   69 
   70 void
   71 FGModelMgr::add_model (SGPropertyNode * node)
   72 {
   73   SG_LOG(SG_AIRCRAFT, SG_INFO,
   74          "Adding model " << node->getStringValue("name", "[unnamed]"));
   75 
   76   const char *model_path = node->getStringValue("path", "Models/Geometry/glider.ac");
   77   osg::Node *object;
   78 
   79   try {
   80       std::string fullPath = simgear::SGModelLib::findDataFile(model_path);
   81       object = SGModelLib::loadDeferredModel(fullPath, globals->get_props());
   82   } catch (const sg_throwable& t) {
   83     SG_LOG(SG_AIRCRAFT, SG_ALERT, "Error loading " << model_path << ":\n  "
   84         << t.getFormattedMessage() << t.getOrigin());
   85     return;
   86   }
   87 
   88   Instance * instance = new Instance;
   89   SGModelPlacement *model = new SGModelPlacement;
   90   instance->model = model;
   91   instance->node = node;
   92 
   93   model->init( object );
   94     double lon = node->getDoubleValue("longitude-deg"),
   95         lat = node->getDoubleValue("latitude-deg"),
   96         elevFt = node->getDoubleValue("elevation-ft");
   97 
   98     model->setPosition(SGGeod::fromDegFt(lon, lat, elevFt));
   99 // Set position and orientation either
  100 // indirectly through property refs
  101 // or directly with static values.
  102   SGPropertyNode * child = node->getChild("longitude-deg-prop");
  103   if (child != 0)
  104     instance->lon_deg_node = fgGetNode(child->getStringValue(), true);
  105 
  106   child = node->getChild("latitude-deg-prop");
  107   if (child != 0)
  108     instance->lat_deg_node = fgGetNode(child->getStringValue(), true);
  109 
  110   child = node->getChild("elevation-ft-prop");
  111   if (child != 0)
  112     instance->elev_ft_node = fgGetNode(child->getStringValue(), true);
  113 
  114   child = node->getChild("roll-deg-prop");
  115   if (child != 0)
  116     instance->roll_deg_node = fgGetNode(child->getStringValue(), true);
  117   else
  118     model->setRollDeg(node->getDoubleValue("roll-deg"));
  119 
  120   child = node->getChild("pitch-deg-prop");
  121   if (child != 0)
  122     instance->pitch_deg_node = fgGetNode(child->getStringValue(), true);
  123   else
  124     model->setPitchDeg(node->getDoubleValue("pitch-deg"));
  125 
  126   child = node->getChild("heading-deg-prop");
  127   if (child != 0)
  128     instance->heading_deg_node = fgGetNode(child->getStringValue(), true);
  129   else
  130     model->setHeadingDeg(node->getDoubleValue("heading-deg"));
  131 
  132   if (node->hasChild("enable-hot")) {
  133     osg::Node::NodeMask mask = model->getSceneGraph()->getNodeMask();
  134     if (node->getBoolValue("enable-hot")) {
  135       mask |= SG_NODEMASK_TERRAIN_BIT;
  136     } else {
  137       mask &= ~SG_NODEMASK_TERRAIN_BIT;
  138     }
  139     model->getSceneGraph()->setNodeMask(mask);
  140   }
  141 
  142                 // Add this model to the global scene graph
  143   globals->get_scenery()->get_scene_graph()->addChild(model->getSceneGraph());
  144 
  145 
  146                 // Save this instance for updating
  147   add_instance(instance);
  148 }
  149 
  150 void
  151 FGModelMgr::bind ()
  152 {
  153     _models = fgGetNode("/models", true);
  154 
  155     _listener.reset(new Listener(this));
  156     _models->addChangeListener(_listener.get());
  157 }
  158 
  159 void
  160 FGModelMgr::unbind ()
  161 {
  162     // work-around for FLIGHTGEAR-37D : crash when quitting during
  163     // early startup
  164     if (!_listener) {
  165         _models->removeChangeListener(_listener.get());
  166     }
  167 
  168     _listener.reset();
  169     _models.clear();
  170 }
  171 
  172 namespace
  173 {
  174 double testNan(double val)
  175 {
  176     if (SGMisc<double>::isNaN(val))
  177         throw sg_range_exception("value is nan");
  178 
  179     return val;
  180 }
  181 
  182 struct UpdateFunctor : public std::unary_function<FGModelMgr::Instance*, void>
  183 {
  184     void operator()(FGModelMgr::Instance* instance) const
  185     {
  186         SGModelPlacement* model = instance->model;
  187         double roll, pitch, heading;
  188         roll = pitch = heading = 0.0;
  189         SGGeod pos = model->getPosition();
  190         
  191         try {
  192             // Optionally set position from properties
  193             if (instance->lon_deg_node != 0)
  194                 pos.setLongitudeDeg(testNan(instance->lon_deg_node->getDoubleValue()));
  195             if (instance->lat_deg_node != 0)
  196                 pos.setLatitudeDeg(testNan(instance->lat_deg_node->getDoubleValue()));
  197             if (instance->elev_ft_node != 0)
  198                 pos.setElevationFt(testNan(instance->elev_ft_node->getDoubleValue()));
  199             
  200             // Optionally set orientation from properties
  201             if (instance->roll_deg_node != 0)
  202                 roll = testNan(instance->roll_deg_node->getDoubleValue());
  203             if (instance->pitch_deg_node != 0)
  204                 pitch = testNan(instance->pitch_deg_node->getDoubleValue());
  205             if (instance->heading_deg_node != 0)
  206                 heading = testNan(instance->heading_deg_node->getDoubleValue());
  207         } catch (const sg_range_exception&) {
  208             const char *path = instance->node->getStringValue("path",
  209                                                               "unknown");
  210             SG_LOG(SG_AIRCRAFT, SG_INFO, "Instance of model " << path
  211                    << " has invalid values");
  212             return;
  213         }
  214 
  215         model->setPosition(pos);
  216         // Optionally set orientation from properties
  217         if (instance->roll_deg_node != 0)
  218             model->setRollDeg(roll);
  219         if (instance->pitch_deg_node != 0)
  220             model->setPitchDeg(pitch);
  221         if (instance->heading_deg_node != 0)
  222             model->setHeadingDeg(heading);
  223 
  224         instance->model->update();
  225     }
  226 };
  227 }
  228 
  229 void
  230 FGModelMgr::update (double dt)
  231 {
  232     std::for_each(_instances.begin(), _instances.end(), UpdateFunctor());
  233 }
  234 
  235 void
  236 FGModelMgr::add_instance (Instance * instance)
  237 {
  238     _instances.push_back(instance);
  239 }
  240 
  241 void
  242 FGModelMgr::remove_instance (Instance * instance)
  243 {
  244     std::vector<Instance *>::iterator it;
  245     for (it = _instances.begin(); it != _instances.end(); it++) {
  246         if (*it == instance) {
  247             _instances.erase(it);
  248             delete instance;
  249             return;
  250         }
  251     }
  252 }
  253 
  254 
  255 ////////////////////////////////////////////////////////////////////////
  256 // Implementation of FGModelMgr::Instance
  257 ////////////////////////////////////////////////////////////////////////
  258 
  259 FGModelMgr::Instance::Instance ()
  260   : model(0),
  261     node(0),
  262     lon_deg_node(0),
  263     lat_deg_node(0),
  264     elev_ft_node(0),
  265     roll_deg_node(0),
  266     pitch_deg_node(0),
  267     heading_deg_node(0),
  268     shadow(false)
  269 {
  270 }
  271 
  272 FGModelMgr::Instance::~Instance ()
  273 {
  274   delete model;
  275 }
  276 
  277 
  278 
  279 ////////////////////////////////////////////////////////////////////////
  280 // Implementation of FGModelMgr::Listener
  281 ////////////////////////////////////////////////////////////////////////
  282 
  283 void
  284 FGModelMgr::Listener::childAdded(SGPropertyNode * parent, SGPropertyNode * child)
  285 {
  286   if (strcmp(parent->getName(), "model") || strcmp(child->getName(), "load"))
  287     return;
  288 
  289   _mgr->add_model(parent);
  290 }
  291 
  292 void
  293 FGModelMgr::Listener::childRemoved(SGPropertyNode * parent, SGPropertyNode * child)
  294 {
  295   if (strcmp(parent->getName(), "models") || strcmp(child->getName(), "model"))
  296     return;
  297 
  298   // search instance by node and remove it from scenegraph
  299     std::vector<Instance *>::iterator it = _mgr->_instances.begin();
  300     std::vector<Instance *>::iterator end = _mgr->_instances.end();
  301 
  302   for (; it != end; ++it) {
  303     Instance *instance = *it;
  304     if (instance->node != child)
  305       continue;
  306 
  307     _mgr->_instances.erase(it);
  308     osg::Node *branch = instance->model->getSceneGraph();
  309     // OSGFIXME
  310 //     if (shadows && instance->shadow)
  311 //         shadows->deleteOccluder(branch);
  312 
  313       if (globals->get_scenery() && globals->get_scenery()->get_scene_graph()) {
  314           globals->get_scenery()->get_scene_graph()->removeChild(branch);
  315       }
  316 
  317     delete instance;
  318     break;
  319   }
  320 }
  321 
  322 
  323 // Register the subsystem.
  324 SGSubsystemMgr::Registrant<FGModelMgr> registrantFGModelMgr(
  325     SGSubsystemMgr::DISPLAY);
  326 
  327 // end of modelmgr.cxx