From: James Turner Date: Sun, 20 Oct 2013 19:46:33 +0000 (+0100) Subject: Support explicit aircraft interior models. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=38193d78431bf35e06667be77259bc84cc4e9e93;p=flightgear.git Support explicit aircraft interior models. - allow multiple model files in the -set.xml specification - allow each model to be tagged with a usage string - put models tagged 'interior' into a LOD group. This is experimental, the LOD ranges will be made configurable soon. --- diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index 1933dac0d..21e295a99 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -2,14 +2,12 @@ include(FlightGearComponent) set(SOURCES acmodel.cxx - model_panel.cxx modelmgr.cxx panelnode.cxx ) set(HEADERS acmodel.hxx - model_panel.hxx modelmgr.hxx panelnode.hxx ) diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index 73701f622..02924e455 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -7,7 +7,8 @@ # include #endif -#include // for strcmp() +#include // for strcmp() +#include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include #include
#include
@@ -24,26 +26,26 @@ #include #include -#include "model_panel.hxx" - #include "acmodel.hxx" +static osg::Node * +fgLoad3DModelPanel(const std::string &path, SGPropertyNode *prop_root) +{ + bool loadPanels = true; + osg::Node* node = simgear::SGModelLib::loadModel(path, prop_root, NULL, loadPanels); + if (node) + node->setNodeMask(~SG_NODEMASK_TERRAIN_BIT); + return node; +} //////////////////////////////////////////////////////////////////////// // Implementation of FGAircraftModel //////////////////////////////////////////////////////////////////////// FGAircraftModel::FGAircraftModel () - : _aircraft(0), - _velocity(SGVec3d::zeros()), + : _velocity(SGVec3d::zeros()), _fx(0), - _lon(0), - _lat(0), - _alt(0), - _pitch(0), - _roll(0), - _heading(0), _speed_n(0), _speed_e(0), _speed_d(0) @@ -62,38 +64,66 @@ FGAircraftModel::~FGAircraftModel () void FGAircraftModel::init () { - osg::Node *model = NULL; - - _aircraft = new SGModelPlacement; - std::string path = fgGetString("/sim/model/path", "Models/Geometry/glider.ac"); - - SGPath resolvedPath = globals->resolve_aircraft_path(path); - if (resolvedPath.isNull()) - { - SG_LOG(SG_AIRCRAFT, SG_ALERT, "Failed to load aircraft from " << path << ':'); - } - else - { - try { - model = fgLoad3DModelPanel( resolvedPath.str(), globals->get_props()); - } catch (const sg_exception &ex) { - SG_LOG(SG_AIRCRAFT, SG_ALERT, "Failed to load aircraft from " << path << ':'); - SG_LOG(SG_AIRCRAFT, SG_ALERT, " " << ex.getFormattedMessage()); - } - } - - if (!model) - { - SG_LOG(SG_AIRCRAFT, SG_ALERT, "(Falling back to glider.ac.)"); - model = fgLoad3DModelPanel( "Models/Geometry/glider.ac", - globals->get_props()); - } - _aircraft->init( model ); + if (_aircraft.get()) { + SG_LOG(SG_AIRCRAFT, SG_ALERT, "FGAircraftModel::init: already inited"); + return; + } + + SGPropertyNode_ptr sim = fgGetNode("/sim", true); + BOOST_FOREACH(SGPropertyNode_ptr model, sim->getChildren("model")) { + std::string path = model->getStringValue("path", "Models/Geometry/glider.ac"); + std::string usage = model->getStringValue("usage", "external"); + + SGPath resolvedPath = globals->resolve_aircraft_path(path); + if (resolvedPath.isNull()) { + SG_LOG(SG_AIRCRAFT, SG_ALERT, "Failed to find aircraft model: " << path); + continue; + } + + osg::Node* node = NULL; + try { + node = fgLoad3DModelPanel( resolvedPath.str(), globals->get_props()); + } catch (const sg_exception &ex) { + SG_LOG(SG_AIRCRAFT, SG_ALERT, "Failed to load aircraft from " << path << ':'); + SG_LOG(SG_AIRCRAFT, SG_ALERT, " " << ex.getFormattedMessage()); + } + + if (usage == "interior") { + // interior model + if (!_interior.get()) { + _interior.reset(new SGModelPlacement); + _interior->init(node); + } else { + _interior->add(node); + } + } else { + // normal / exterior model + if (!_aircraft.get()) { + _aircraft.reset(new SGModelPlacement); + _aircraft->init(node); + } else { + _aircraft->add(node); + } + } // of model usage switch + } // of models iteration + + // no models loaded, load the glider instead + if (!_aircraft.get()) { + SG_LOG(SG_AIRCRAFT, SG_ALERT, "(Falling back to glider.ac.)"); + osg::Node* model = fgLoad3DModelPanel( "Models/Geometry/glider.ac", + globals->get_props()); + _aircraft.reset(new SGModelPlacement); + _aircraft->init(model); + + } osg::Node* node = _aircraft->getSceneGraph(); - // Do not do altitude computations with that model - node->setNodeMask(~SG_NODEMASK_TERRAIN_BIT); globals->get_scenery()->get_aircraft_branch()->addChild(node); + + if (_interior.get()) { + node = _interior->getSceneGraph(); + globals->get_scenery()->get_interior_branch()->addChild(node); + } } void @@ -109,26 +139,24 @@ FGAircraftModel::reinit() void FGAircraftModel::deinit() { - if (!_aircraft) { + if (!_aircraft.get()) { return; } osg::Node* node = _aircraft->getSceneGraph(); globals->get_scenery()->get_aircraft_branch()->removeChild(node); - delete _aircraft; - _aircraft = NULL; + if (_interior.get()) { + globals->get_scenery()->get_interior_branch()->removeChild(_interior->getSceneGraph()); + } + + _aircraft.reset(); + _interior.reset(); } void FGAircraftModel::bind () { - _lon = fgGetNode("position/longitude-deg", true); - _lat = fgGetNode("position/latitude-deg", true); - _alt = fgGetNode("position/altitude-ft", true); - _pitch = fgGetNode("orientation/pitch-deg", true); - _roll = fgGetNode("orientation/roll-deg", true); - _heading = fgGetNode("orientation/heading-deg", true); _speed_n = fgGetNode("velocities/speed-north-fps", true); _speed_e = fgGetNode("velocities/speed-east-fps", true); _speed_d = fgGetNode("velocities/speed-down-fps", true); @@ -151,22 +179,25 @@ FGAircraftModel::update (double dt) } else { _aircraft->setVisible(true); } - - _aircraft->setPosition(_lon->getDoubleValue(), - _lat->getDoubleValue(), - _alt->getDoubleValue()); - _aircraft->setOrientation(_roll->getDoubleValue(), - _pitch->getDoubleValue(), - _heading->getDoubleValue()); - _aircraft->update(); - + + double heading, pitch, roll; + globals->get_aircraft_orientation(heading, pitch, roll); + SGQuatd orient = SGQuatd::fromYawPitchRollDeg(heading, pitch, roll); + + SGGeod pos = globals->get_aircraft_position(); + + _aircraft->setPosition(pos); + _aircraft->setOrientation(orient); + _aircraft->update(); + + if (_interior.get()) { + _interior->setPosition(pos); + _interior->setOrientation(orient); + _interior->update(); + } + // update model's audio sample values - SGGeod position = _aircraft->getPosition(); - _fx->set_position_geod( position ); - - SGQuatd orient = SGQuatd::fromYawPitchRollDeg(_heading->getDoubleValue(), - _pitch->getDoubleValue(), - _roll->getDoubleValue()); + _fx->set_position_geod( pos ); _fx->set_orientation( orient ); _velocity = SGVec3d( _speed_n->getDoubleValue(), diff --git a/src/Model/acmodel.hxx b/src/Model/acmodel.hxx index b774874d2..552144181 100644 --- a/src/Model/acmodel.hxx +++ b/src/Model/acmodel.hxx @@ -10,6 +10,7 @@ #include #include +#include #include // for SGSubsystem @@ -29,22 +30,18 @@ public: virtual void bind (); virtual void unbind (); virtual void update (double dt); - virtual SGModelPlacement * get3DModel() { return _aircraft; } + virtual SGModelPlacement * get3DModel() { return _aircraft.get(); } virtual SGVec3d& getVelocity() { return _velocity; } private: void deinit (); - SGModelPlacement * _aircraft; + std::auto_ptr _aircraft; + std::auto_ptr _interior; + SGVec3d _velocity; SGSharedPtr _fx; - SGPropertyNode_ptr _lon; - SGPropertyNode_ptr _lat; - SGPropertyNode_ptr _alt; - SGPropertyNode_ptr _pitch; - SGPropertyNode_ptr _roll; - SGPropertyNode_ptr _heading; SGPropertyNode_ptr _speed_n; SGPropertyNode_ptr _speed_e; SGPropertyNode_ptr _speed_d; diff --git a/src/Model/model_panel.cxx b/src/Model/model_panel.cxx deleted file mode 100644 index ac2ab88b1..000000000 --- a/src/Model/model_panel.cxx +++ /dev/null @@ -1,40 +0,0 @@ -// model.cxx - manage a 3D aircraft model. -// Written by David Megginson, started 2002. -// -// This file is in the Public Domain, and comes with no warranty. - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include - -#include -#include -#include - -#include "panelnode.hxx" -#include "model_panel.hxx" - -using std::vector; - -using namespace simgear; - -//////////////////////////////////////////////////////////////////////// -// Global functions. -//////////////////////////////////////////////////////////////////////// - -osg::Node * -fgLoad3DModelPanel(const std::string &path, SGPropertyNode *prop_root) -{ - bool loadPanels = true; - osg::Node* node = SGModelLib::loadModel(path, prop_root, NULL, loadPanels); - if (node) - node->setNodeMask(~SG_NODEMASK_TERRAIN_BIT); - return node; -} - - -// end of model_panel.cxx diff --git a/src/Model/model_panel.hxx b/src/Model/model_panel.hxx deleted file mode 100644 index 301f770c8..000000000 --- a/src/Model/model_panel.hxx +++ /dev/null @@ -1,51 +0,0 @@ -// model.hxx - manage a 3D aircraft model. -// Written by David Megginson, started 2002. -// -// This file is in the Public Domain, and comes with no warranty. - -#ifndef __MODEL_HXX -#define __MODEL_HXX 1 - -#ifndef __cplusplus -# error This library requires C++ -#endif - -#include - -using std::vector; - -#include - - -// Don't pull in the headers, since we don't need them here. - -class SGInterpTable; -class FGCondition; -class FGLocation; - - -// Has anyone done anything *really* stupid, like making min and max macros? -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif - - -/** - * Load a 3D model with or without XML wrapper. This version supports - * also loading the instrument panel and is wired in with dependencies - * on panelnode.hxx, and thus files in src/Cockpit and also GUI/mouse - * input code to support the 3d clickable hotspots. - * - * 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 SGModelLoader declared in loader.hxx. - */ -osg::Node *fgLoad3DModelPanel( const std::string &path, SGPropertyNode *prop_root); - - -#endif // __MODEL_HXX diff --git a/src/Model/modelmgr.cxx b/src/Model/modelmgr.cxx index 449c3bedc..4af505c38 100644 --- a/src/Model/modelmgr.cxx +++ b/src/Model/modelmgr.cxx @@ -86,27 +86,25 @@ FGModelMgr::add_model (SGPropertyNode * node) instance->node = node; model->init( object ); - - // Set position and orientation either - // indirectly through property refs - // or directly with static values. + double lon = node->getDoubleValue("longitude-deg"), + lat = node->getDoubleValue("latitude-deg"), + elevFt = node->getDoubleValue("elevation-ft"); + + model->setPosition(SGGeod::fromDegFt(lon, lat, elevFt)); +// 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) @@ -158,18 +156,19 @@ struct UpdateFunctor : public std::unary_function void operator()(FGModelMgr::Instance* instance) const { SGModelPlacement* model = instance->model; - double lon, lat, elev, roll, pitch, heading; - lon = lat = elev = roll = pitch = heading = 0.0; - + double roll, pitch, heading; + roll = pitch = heading = 0.0; + SGGeod pos = model->getPosition(); + try { // Optionally set position from properties if (instance->lon_deg_node != 0) - lon = testNan(instance->lon_deg_node->getDoubleValue()); + pos.setLongitudeDeg(testNan(instance->lon_deg_node->getDoubleValue())); if (instance->lat_deg_node != 0) - lat = testNan(instance->lat_deg_node->getDoubleValue()); + pos.setLatitudeDeg(testNan(instance->lat_deg_node->getDoubleValue())); if (instance->elev_ft_node != 0) - elev = testNan(instance->elev_ft_node->getDoubleValue()); - + pos.setElevationFt(testNan(instance->elev_ft_node->getDoubleValue())); + // Optionally set orientation from properties if (instance->roll_deg_node != 0) roll = testNan(instance->roll_deg_node->getDoubleValue()); @@ -184,14 +183,8 @@ struct UpdateFunctor : public std::unary_function << " 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); + model->setPosition(pos); // Optionally set orientation from properties if (instance->roll_deg_node != 0) model->setRollDeg(roll); diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx index 379538ba8..d243a8ae4 100644 --- a/src/Scenery/scenery.cxx +++ b/src/Scenery/scenery.cxx @@ -33,6 +33,8 @@ #include #include #include +#include + #include #include @@ -252,6 +254,17 @@ void FGScenery::init() { aircraft_branch->setName( "Aircraft" ); scene_graph->addChild( aircraft_branch.get() ); +// choosing to make the interior branch a child of the main +// aircraft group, for the moment. This simplifes places which +// assume all aircraft elements are within this group - principally +// FGODGuage::set_aircraft_texture. + interior_branch = new osg::Group; + interior_branch->setName( "Interior" ); + + osg::LOD* interiorLOD = new osg::LOD; + interiorLOD->addChild(interior_branch.get(), 0.0, 50.0); + aircraft_branch->addChild( interiorLOD ); + // Initials values needed by the draw-time object loader sgUserDataInit( globals->get_props() ); } diff --git a/src/Scenery/scenery.hxx b/src/Scenery/scenery.hxx index d53344354..cfa0f935a 100644 --- a/src/Scenery/scenery.hxx +++ b/src/Scenery/scenery.hxx @@ -50,6 +50,8 @@ class FGScenery : public SGSubsystem { osg::ref_ptr terrain_branch; osg::ref_ptr models_branch; osg::ref_ptr aircraft_branch; + osg::ref_ptr interior_branch; + osg::ref_ptr _pager; public: @@ -106,7 +108,8 @@ public: osg::Group *get_terrain_branch () const { return terrain_branch.get(); } osg::Group *get_models_branch () const { return models_branch.get(); } osg::Group *get_aircraft_branch () const { return aircraft_branch.get(); } - + osg::Group *get_interior_branch () const { return interior_branch.get(); } + /// Returns true if scenery is available for the given lat, lon position /// within a range of range_m. /// lat and lon are expected to be in degrees.