From 625572663e47fb4d801a3f18e7f83971da5bb519 Mon Sep 17 00:00:00 2001 From: david Date: Fri, 5 Apr 2002 03:19:34 +0000 Subject: [PATCH] Moved FGAircraftModel subsystem out into its own directory, and separated out a new class, FG3DModel, that allows any arbitrary 3D model to be positioned, oriented, and animated (not just the aircraft). --- src/Main/Makefile.am | 2 +- src/Main/README | 5 - src/Main/main.cxx | 2 +- src/Makefile.am | 1 + src/Model/.cvsignore | 3 + src/Model/Makefile.am | 10 ++ src/Model/README | 14 +++ src/Model/acmodel.cxx | 87 +++++++++++++ src/Model/acmodel.hxx | 46 +++++++ src/{Main => Model}/model.cxx | 228 ++++++++++++++++++---------------- src/{Main => Model}/model.hxx | 55 +++++--- 11 files changed, 322 insertions(+), 131 deletions(-) create mode 100644 src/Model/.cvsignore create mode 100644 src/Model/Makefile.am create mode 100644 src/Model/README create mode 100644 src/Model/acmodel.cxx create mode 100644 src/Model/acmodel.hxx rename src/{Main => Model}/model.cxx (74%) rename src/{Main => Model}/model.hxx (78%) diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 84feff63b..a3056b5a7 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -48,7 +48,6 @@ fgfs_SOURCES = \ fgfs.cxx fgfs.hxx \ globals.cxx globals.hxx \ logger.cxx logger.hxx \ - model.cxx model.hxx \ options.cxx options.hxx \ splash.cxx splash.hxx \ viewer.cxx viewer.hxx \ @@ -68,6 +67,7 @@ fgfs_LDADD = \ $(top_builddir)/src/FDM/LaRCsim/libLaRCsim.a \ $(top_builddir)/src/FDM/UIUCModel/libUIUCModel.a \ $(top_builddir)/src/GUI/libGUI.a \ + $(top_builddir)/src/Model/libModel.a \ $(top_builddir)/src/Navaids/libNavaids.a \ $(top_builddir)/src/Scenery/libScenery.a \ $(top_builddir)/src/Sound/libSound.a \ diff --git a/src/Main/README b/src/Main/README index 7c4b3cd8f..b78bb9cc5 100644 --- a/src/Main/README +++ b/src/Main/README @@ -61,11 +61,6 @@ main.cxx methods; eventually, this will be a short, simple file defining the top-level flow logic of the program. -model.cxx -model.hxx - This module defines the FGAircraftModel subsystem, which controls - the display and animation of 3D models in FlightGear. - options.cxx options.hxx This module defines global functions for parsing command-line diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 2a1cdcf64..68c80e025 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -96,6 +96,7 @@ SG_USING_STD(endl); #include #include +#include #ifdef FG_NETWORK_OLK #include #endif @@ -163,7 +164,6 @@ float scene_farplane = 120000.0f; #include "viewmgr.hxx" #include "options.hxx" #include "logger.hxx" -#include "model.hxx" #ifdef macintosh # include // -dw- for command line dialog diff --git a/src/Makefile.am b/src/Makefile.am index d1a55d76f..86c9491f0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,6 +21,7 @@ SUBDIRS = \ FDM \ GUI \ Input \ + Model \ Navaids \ $(NETWORK_DIRS) \ Objects \ diff --git a/src/Model/.cvsignore b/src/Model/.cvsignore new file mode 100644 index 000000000..e99558847 --- /dev/null +++ b/src/Model/.cvsignore @@ -0,0 +1,3 @@ +.deps +Makefile +Makefile.in diff --git a/src/Model/Makefile.am b/src/Model/Makefile.am new file mode 100644 index 000000000..ddb86d876 --- /dev/null +++ b/src/Model/Makefile.am @@ -0,0 +1,10 @@ +noinst_LIBRARIES = libModel.a + +libModel_a_SOURCES = model.cxx model.hxx \ + acmodel.cxx acmodel.hxx + +if OLD_AUTOMAKE +INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/src +else +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src +endif diff --git a/src/Model/README b/src/Model/README new file mode 100644 index 000000000..3d21a5108 --- /dev/null +++ b/src/Model/README @@ -0,0 +1,14 @@ +Last updated $Date$ + +This directory contains code for loading, positioning, orienting, and +animating 3D models. + +acmodel.cxx +acmodel.hxx + This module defines the FGAircraftModel subsystem, which manages the 3D + model representing the aircraft the user is flying. + +model.cxx +model.hxx + This module defines the FG3DModel class, which represents any 3D + model in the FlightGear world. diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx new file mode 100644 index 000000000..ece3d5076 --- /dev/null +++ b/src/Model/acmodel.cxx @@ -0,0 +1,87 @@ +// 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 // for strcmp() + +#include +#include + +#include +#include +#include +#include + +#include
+#include
+#include
+#include "acmodel.hxx" + +extern ssgRoot * cockpit; // FIXME: from main.cxx + +FGAircraftModel current_model; // FIXME: add to globals + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGAircraftModel +//////////////////////////////////////////////////////////////////////// + +FGAircraftModel::FGAircraftModel () + : _aircraft(0) +{ +} + +FGAircraftModel::~FGAircraftModel () +{ + delete _aircraft; +} + +void +FGAircraftModel::init () +{ + _aircraft = new FG3DModel; + _aircraft->init(fgGetString("/sim/model/path", "Models/Geometry/glider.ac")); + cockpit->addKid(_aircraft->getSceneGraph()); +} + +void +FGAircraftModel::bind () +{ + // No-op +} + +void +FGAircraftModel::unbind () +{ + // No-op +} + +void +FGAircraftModel::update (int dt) +{ + int view_number = globals->get_viewmgr()->get_current(); + + if (view_number == 0 && !fgGetBool("/sim/view/internal")) { + _aircraft->setVisible(false); + return; + } + + _aircraft->setVisible(true); + + _aircraft->setPosition(fgGetDouble("/position/longitude-deg"), + fgGetDouble("/position/latitude-deg"), + fgGetDouble("/position/altitude-ft")); + _aircraft->setOrientation(fgGetDouble("/orientation/roll-deg"), + fgGetDouble("/orientation/pitch-deg"), + fgGetDouble("/orientation/heading-deg")); + _aircraft->update(dt); +} + + +// end of model.cxx diff --git a/src/Model/acmodel.hxx b/src/Model/acmodel.hxx new file mode 100644 index 000000000..920fbbdc4 --- /dev/null +++ b/src/Model/acmodel.hxx @@ -0,0 +1,46 @@ +// 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 __ACMODEL_HXX +#define __ACMODEL_HXX 1 + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include + +SG_USING_STD(string); +SG_USING_STD(vector); + +#include + +#include
+ +#include "model.hxx" + + +class FGAircraftModel : public FGSubsystem +{ +public: + + FGAircraftModel (); + virtual ~FGAircraftModel (); + + virtual void init (); + virtual void bind (); + virtual void unbind (); + virtual void update (int dt); + +private: + + FG3DModel * _aircraft; + +}; + +extern FGAircraftModel current_model; + +#endif // __ACMODEL_HXX + diff --git a/src/Main/model.cxx b/src/Model/model.cxx similarity index 74% rename from src/Main/model.cxx rename to src/Model/model.cxx index 461c5a8e4..33f16cedd 100644 --- a/src/Main/model.cxx +++ b/src/Model/model.cxx @@ -14,17 +14,15 @@ #include #include +#include +#include #include #include -#include "globals.hxx" -#include "fg_props.hxx" -#include "viewmgr.hxx" -#include "model.hxx" - -extern ssgRoot * cockpit; // FIXME: from main.cxx +#include
+#include -FGAircraftModel current_model; // FIXME: add to globals +#include "model.hxx" @@ -124,19 +122,62 @@ set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis) } +// TODO: once this is working, look at Norm's optimized version +static void +world_coordinate( sgCoord *obj_pos, + double lat_deg, double lon_deg, double elev_ft, + double roll_deg, double pitch_deg, double hdg_deg) +{ + Point3D center = scenery.get_center(); + + // setup transforms + Point3D geod( lon_deg * SGD_DEGREES_TO_RADIANS, + lat_deg * SGD_DEGREES_TO_RADIANS, + elev_ft * SG_FEET_TO_METER); + + Point3D world_pos = sgGeodToCart( geod ); + Point3D offset = world_pos - center; + + sgMat4 POS; + sgMakeTransMat4( POS, offset.x(), offset.y(), offset.z() ); + + sgVec3 obj_bk, obj_rt, obj_up; + sgSetVec3( obj_bk, 1.0, 0.0, 0.0); // X axis + sgSetVec3( obj_rt, 0.0, 1.0, 0.0); // Y axis + sgSetVec3( obj_up, 0.0, 0.0, 1.0); // Z axis + + sgMat4 ROT_lon, ROT_lat, ROT_hdg, ROT_pitch, ROT_roll; + sgMakeRotMat4( ROT_lon, lon_deg, obj_up ); + sgMakeRotMat4( ROT_lat, 90 - lat_deg, obj_rt ); + sgMakeRotMat4( ROT_hdg, -hdg_deg, obj_up ); + sgMakeRotMat4( ROT_pitch, pitch_deg, obj_rt ); + sgMakeRotMat4( ROT_roll, -roll_deg, obj_bk ); + + sgMat4 TRANS; + sgCopyMat4( TRANS, ROT_roll ); + sgPostMultMat4( TRANS, ROT_pitch ); + sgPostMultMat4( TRANS, ROT_hdg ); + sgPostMultMat4( TRANS, ROT_lat ); + sgPostMultMat4( TRANS, ROT_lon ); + sgPostMultMat4( TRANS, POS ); + + sgSetCoord( obj_pos, TRANS ); +} + + //////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel +// Implementation of FG3DModel //////////////////////////////////////////////////////////////////////// -FGAircraftModel::FGAircraftModel () +FG3DModel::FG3DModel () : _model(0), _selector(new ssgSelector), _position(new ssgTransform) { } -FGAircraftModel::~FGAircraftModel () +FG3DModel::~FG3DModel () { // since the nodes are attached to the scene graph, they'll be // deleted automatically @@ -150,39 +191,32 @@ FGAircraftModel::~FGAircraftModel () } void -FGAircraftModel::init () +FG3DModel::init (const string &path) { - // TODO: optionally load an XML file with a pointer to the 3D object - // and placement and animation info - SGPropertyNode props; - SG_LOG(SG_INPUT, SG_INFO, "Initializing aircraft 3D model"); - // Load the 3D aircraft object itself - // DCL - the xml parser requires the full path but the ssgLoader doesn't - // so lets have two paths. SGPath xmlpath = globals->get_fg_root(); - SGPath modelpath = (string)fgGetString("/sim/model/path", "Models/Geometry/glider.ac"); + SGPath modelpath = path; xmlpath.append(modelpath.str()); + // Check for an XML wrapper if (xmlpath.str().substr(xmlpath.str().size() - 4, 4) == ".xml") { readProperties(xmlpath.str(), &props); if (props.hasValue("/path")) { modelpath = modelpath.dir(); modelpath.append(props.getStringValue("/path")); } else { - modelpath = "Models/Geometry/glider.ac"; + throw sg_exception("No path for model"); } } + // Assume that textures are in + // the same location as the XML file. ssgTexturePath((char *)xmlpath.dir().c_str()); _model = ssgLoad((char *)modelpath.c_str()); - if (_model == 0) { - _model = ssgLoad((char *)"Models/Geometry/glider.ac"); - if (_model == 0) - throw sg_exception("Failed to load an aircraft model"); - } + if (_model == 0) + throw sg_exception("Failed to load 3D model"); // Load animations vector animation_nodes = props.getChildren("animation"); @@ -224,75 +258,53 @@ FGAircraftModel::init () // Set up the selector node _selector->addKid(_position); _selector->clrTraversalMaskBits(SSGTRAV_HOT); - cockpit->addKid(_selector); } -void -FGAircraftModel::bind () +void +FG3DModel::update (int dt) { + for (unsigned int i = 0; i < _animations.size(); i++) + _animations[i]->update(dt); + + _selector->select(true); + + sgCoord obj_pos; + world_coordinate(&obj_pos, _lat_deg, _lon_deg, _elev_ft, + _roll_deg, _pitch_deg, _heading_deg); + _position->setTransform(&obj_pos); } -void -FGAircraftModel::unbind () +bool +FG3DModel::getVisible () const { + return _selector->getSelect(); } void -FGAircraftModel::update (int dt) +FG3DModel::setVisible (bool visible) { - sgMat4 MODEL_ROT, LOCAL; - sgMat4 sgTRANS; + _selector->select(visible); +} - int view_number = globals->get_viewmgr()->get_current(); +void +FG3DModel::setPosition (double lon_deg, double lat_deg, double elev_ft) +{ + _lon_deg = lon_deg; + _lat_deg = lat_deg; + _elev_ft = elev_ft; +} - if (view_number == 0 && !fgGetBool("/sim/view/internal")) { - _selector->select(false); - } else { - for (unsigned int i = 0; i < _animations.size(); i++) - _animations[i]->update(dt); - - _selector->select(true); - FGViewer *current_view = - (FGViewer *)globals->get_viewmgr()->get_view( view_number ); - - // FIXME: this class needs to be unlinked from the viewer - // get transform for current position in the world... - sgMakeTransMat4( sgTRANS, current_view->getRelativeViewPos() ); - - // get a copy of the LOCAL rotation from the current view... - sgCopyMat4( LOCAL, current_view->get_LOCAL_ROT() ); - - // Make the MODEL Rotation (just reordering the LOCAL matrix - // and flipping the model over on its feet)... - MODEL_ROT[0][0] = -LOCAL[2][0]; - MODEL_ROT[0][1] = -LOCAL[2][1]; - MODEL_ROT[0][2] = -LOCAL[2][2]; - MODEL_ROT[0][3] = SG_ZERO; - MODEL_ROT[1][0] = LOCAL[1][0]; - MODEL_ROT[1][1] = LOCAL[1][1]; - MODEL_ROT[1][2] = LOCAL[1][2]; - MODEL_ROT[1][3] = SG_ZERO; - MODEL_ROT[2][0] = LOCAL[0][0]; - MODEL_ROT[2][1] = LOCAL[0][1]; - MODEL_ROT[2][2] = LOCAL[0][2]; - MODEL_ROT[2][3] = SG_ZERO; - - // add the position data to the matrix - MODEL_ROT[3][0] = SG_ZERO; - MODEL_ROT[3][1] = SG_ZERO; - MODEL_ROT[3][2] = SG_ZERO; - MODEL_ROT[3][3] = SG_ONE; - - sgPostMultMat4( MODEL_ROT, sgTRANS ); - - sgCoord tuxpos; - sgSetCoord( &tuxpos, MODEL_ROT ); - _position->setTransform( &tuxpos ); - } +void +FG3DModel::setOrientation (double roll_deg, double pitch_deg, + double heading_deg) +{ + _roll_deg = roll_deg; + _pitch_deg = pitch_deg; + _heading_deg = heading_deg; } -FGAircraftModel::Animation * -FGAircraftModel::make_animation (const char * object_name, +FG3DModel::Animation * +FG3DModel::make_animation (const char * object_name, SGPropertyNode * node) { Animation * animation = 0; @@ -327,35 +339,35 @@ FGAircraftModel::make_animation (const char * object_name, //////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::Animation +// Implementation of FG3DModel::Animation //////////////////////////////////////////////////////////////////////// -FGAircraftModel::Animation::Animation () +FG3DModel::Animation::Animation () { } -FGAircraftModel::Animation::~Animation () +FG3DModel::Animation::~Animation () { } //////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::NullAnimation +// Implementation of FG3DModel::NullAnimation //////////////////////////////////////////////////////////////////////// -FGAircraftModel::NullAnimation::NullAnimation () +FG3DModel::NullAnimation::NullAnimation () : _branch(new ssgBranch) { } -FGAircraftModel::NullAnimation::~NullAnimation () +FG3DModel::NullAnimation::~NullAnimation () { _branch = 0; } void -FGAircraftModel::NullAnimation::init (ssgEntity * object, +FG3DModel::NullAnimation::init (ssgEntity * object, SGPropertyNode * props) { splice_branch(_branch, object); @@ -363,30 +375,30 @@ FGAircraftModel::NullAnimation::init (ssgEntity * object, } void -FGAircraftModel::NullAnimation::update (int dt) +FG3DModel::NullAnimation::update (int dt) { } //////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::SelectAnimation +// Implementation of FG3DModel::SelectAnimation //////////////////////////////////////////////////////////////////////// -FGAircraftModel::SelectAnimation::SelectAnimation () +FG3DModel::SelectAnimation::SelectAnimation () : _condition(0), _selector(new ssgSelector) { } -FGAircraftModel::SelectAnimation::~SelectAnimation () +FG3DModel::SelectAnimation::~SelectAnimation () { delete _condition; _selector = 0; } void -FGAircraftModel::SelectAnimation::init (ssgEntity * object, +FG3DModel::SelectAnimation::init (ssgEntity * object, SGPropertyNode * props) { splice_branch(_selector, object); @@ -398,7 +410,7 @@ FGAircraftModel::SelectAnimation::init (ssgEntity * object, } void -FGAircraftModel::SelectAnimation::update (int dt) +FG3DModel::SelectAnimation::update (int dt) { if (_condition != 0 && _condition->test()) _selector->select(0xffff); @@ -409,10 +421,10 @@ FGAircraftModel::SelectAnimation::update (int dt) //////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::SpinAnimation +// Implementation of FG3DModel::SpinAnimation //////////////////////////////////////////////////////////////////////// -FGAircraftModel::SpinAnimation::SpinAnimation () +FG3DModel::SpinAnimation::SpinAnimation () : _prop(0), _factor(0), _position_deg(0), @@ -420,13 +432,13 @@ FGAircraftModel::SpinAnimation::SpinAnimation () { } -FGAircraftModel::SpinAnimation::~SpinAnimation () +FG3DModel::SpinAnimation::~SpinAnimation () { _transform = 0; } void -FGAircraftModel::SpinAnimation::init (ssgEntity * object, +FG3DModel::SpinAnimation::init (ssgEntity * object, SGPropertyNode * props) { // Splice in the new transform node @@ -445,7 +457,7 @@ FGAircraftModel::SpinAnimation::init (ssgEntity * object, } void -FGAircraftModel::SpinAnimation::update (int dt) +FG3DModel::SpinAnimation::update (int dt) { float velocity_rpms = (_prop->getDoubleValue() * _factor / 60000.0); _position_deg += (dt * velocity_rpms * 360); @@ -460,10 +472,10 @@ FGAircraftModel::SpinAnimation::update (int dt) //////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::RotateAnimation +// Implementation of FG3DModel::RotateAnimation //////////////////////////////////////////////////////////////////////// -FGAircraftModel::RotateAnimation::RotateAnimation () +FG3DModel::RotateAnimation::RotateAnimation () : _prop(0), _offset_deg(0.0), _factor(1.0), @@ -476,13 +488,13 @@ FGAircraftModel::RotateAnimation::RotateAnimation () { } -FGAircraftModel::RotateAnimation::~RotateAnimation () +FG3DModel::RotateAnimation::~RotateAnimation () { _transform = 0; } void -FGAircraftModel::RotateAnimation::init (ssgEntity * object, +FG3DModel::RotateAnimation::init (ssgEntity * object, SGPropertyNode * props) { // Splice in the new transform node @@ -510,7 +522,7 @@ FGAircraftModel::RotateAnimation::init (ssgEntity * object, } void -FGAircraftModel::RotateAnimation::update (int dt) +FG3DModel::RotateAnimation::update (int dt) { _position_deg = ((_prop->getDoubleValue() + _offset_deg) * _factor); if (_has_min && _position_deg < _min_deg) @@ -524,10 +536,10 @@ FGAircraftModel::RotateAnimation::update (int dt) //////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::TranslateAnimation +// Implementation of FG3DModel::TranslateAnimation //////////////////////////////////////////////////////////////////////// -FGAircraftModel::TranslateAnimation::TranslateAnimation () +FG3DModel::TranslateAnimation::TranslateAnimation () : _prop(0), _offset_m(0.0), _factor(1.0), @@ -540,13 +552,13 @@ FGAircraftModel::TranslateAnimation::TranslateAnimation () { } -FGAircraftModel::TranslateAnimation::~TranslateAnimation () +FG3DModel::TranslateAnimation::~TranslateAnimation () { _transform = 0; } void -FGAircraftModel::TranslateAnimation::init (ssgEntity * object, +FG3DModel::TranslateAnimation::init (ssgEntity * object, SGPropertyNode * props) { // Splice in the new transform node @@ -571,7 +583,7 @@ FGAircraftModel::TranslateAnimation::init (ssgEntity * object, } void -FGAircraftModel::TranslateAnimation::update (int dt) +FG3DModel::TranslateAnimation::update (int dt) { _position_m = ((_prop->getDoubleValue() + _offset_m) * _factor); if (_has_min && _position_m < _min_m) diff --git a/src/Main/model.hxx b/src/Model/model.hxx similarity index 78% rename from src/Main/model.hxx rename to src/Model/model.hxx index 439f6eef1..08aa4bafb 100644 --- a/src/Main/model.hxx +++ b/src/Model/model.hxx @@ -10,15 +10,11 @@ # error This library requires C++ #endif -#include #include -SG_USING_STD(string); SG_USING_STD(vector); -#include "fgfs.hxx" -#include -#include +#include
// Has anyone done anything *really* stupid, like making min and max macros? #ifdef min @@ -28,30 +24,59 @@ SG_USING_STD(vector); #undef max #endif -class FGAircraftModel : public FGSubsystem +class FG3DModel { public: - FGAircraftModel (); - virtual ~FGAircraftModel (); + FG3DModel (); + virtual ~FG3DModel (); - virtual void init (); - virtual void bind (); - virtual void unbind (); + virtual void init (const string &path); virtual void update (int dt); + virtual bool getVisible () const; + virtual void setVisible (bool visible); + + virtual double getLongitudeDeg () const { return _lon_deg; } + virtual double getLatitudeDeg () const { return _lat_deg; } + virtual double getElevationFt () const { return _elev_ft; } + + virtual void setPosition (double lon_deg, double lat_deg, double elev_ft); + + virtual double getRoll () const { return _roll_deg; } + virtual double getPitch () const { return _pitch_deg; } + virtual double getHeading () const { return _heading_deg; } + + virtual void setOrientation (double roll_deg, double pitch_deg, + double heading_deg); + + virtual ssgEntity * getSceneGraph () const { return _selector; } + private: class Animation; - Animation * make_animation (const char * object_name, SGPropertyNode * node); + // Geodetic position + double _lon_deg; + double _lat_deg; + double _elev_ft; + + // Orientation + double _roll_deg; + double _pitch_deg; + double _heading_deg; + + // Animations + + vector _animations; + + + // Scene graph ssgEntity * _model; ssgSelector * _selector; ssgTransform * _position; - vector _animations; - ////////////////////////////////////////////////////////////////////// @@ -196,7 +221,5 @@ private: }; -extern FGAircraftModel current_model; - #endif // __MODEL_HXX -- 2.39.5