diff --git a/src/Model/acmodel.cxx b/src/Model/acmodel.cxx index 30bebb0c1..9e9dd6dc0 100644 --- a/src/Model/acmodel.cxx +++ b/src/Model/acmodel.cxx @@ -51,7 +51,7 @@ FGAircraftModel::~FGAircraftModel () void FGAircraftModel::init () { - _aircraft = new FG3DModel; + _aircraft = new FGModelPlacement; string path = fgGetString("/sim/model/path", "Models/Geometry/glider.ac"); try { _aircraft->init(path); diff --git a/src/Model/acmodel.hxx b/src/Model/acmodel.hxx index 4e691ca0a..b2674e70f 100644 --- a/src/Model/acmodel.hxx +++ b/src/Model/acmodel.hxx @@ -21,7 +21,7 @@ SG_USING_STD(vector); // Don't pull in the headers, since we don't need them here. class ssgRoot; class ssgSelector; -class FG3DModel; +class FGModelPlacement; class FGAircraftModel : public FGSubsystem @@ -36,11 +36,11 @@ public: virtual void unbind (); virtual void update (double dt); virtual void draw (); - virtual FG3DModel * get3DModel() { return _aircraft; } + virtual FGModelPlacement * get3DModel() { return _aircraft; } private: - FG3DModel * _aircraft; + FGModelPlacement * _aircraft; ssgSelector * _selector; ssgRoot * _scene; float _nearplane; diff --git a/src/Model/model.cxx b/src/Model/model.cxx index f13c8e13a..430c48cc0 100644 --- a/src/Model/model.cxx +++ b/src/Model/model.cxx @@ -125,6 +125,21 @@ set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis) } +/** + * Make an offset matrix from rotations and position offset. + */ +static void +make_offsets_matrix (sgMat4 * result, double h_rot, double p_rot, double r_rot, + double x_off, double y_off, double z_off) +{ + sgMat4 rot_matrix; + sgMat4 pos_matrix; + sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot); + sgMakeTransMat4(pos_matrix, x_off, y_off, z_off); + sgMultMat4(*result, pos_matrix, rot_matrix); +} + + /** * Read an interpolation table from properties. */ @@ -151,9 +166,7 @@ read_interpolation_table (const SGPropertyNode * props) //////////////////////////////////////////////////////////////////////// FG3DModel::FG3DModel () - : _model(0), - _selector(new ssgSelector), - _position(new ssgTransform) + : _model(0) { } @@ -198,30 +211,16 @@ FG3DModel::init (const string &path) // Set up the alignment node ssgTransform * align = new ssgTransform; align->addKid(_model); - sgMat4 rot_matrix; - sgMat4 off_matrix; sgMat4 res_matrix; - float h_rot = props.getFloatValue("/offsets/heading-deg", 0.0); - float p_rot = props.getFloatValue("/offsets/roll-deg", 0.0); - float r_rot = props.getFloatValue("/offsets/pitch-deg", 0.0); - float x_off = props.getFloatValue("/offsets/x-m", 0.0); - float y_off = props.getFloatValue("/offsets/y-m", 0.0); - float z_off = props.getFloatValue("/offsets/z-m", 0.0); - sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot); - sgMakeTransMat4(off_matrix, x_off, y_off, z_off); - sgMultMat4(res_matrix, off_matrix, rot_matrix); + make_offsets_matrix(&res_matrix, + props.getFloatValue("/offsets/heading-deg", 0.0), + props.getFloatValue("/offsets/roll-deg", 0.0), + props.getFloatValue("/offsets/pitch-deg", 0.0), + props.getFloatValue("/offsets/x-m", 0.0), + props.getFloatValue("/offsets/y-m", 0.0), + props.getFloatValue("/offsets/z-m", 0.0)); align->setTransform(res_matrix); - // Set up the position node - _position->addKid(align); - - // Set up the selector node - _selector->addKid(_position); - _selector->clrTraversalMaskBits(SSGTRAV_HOT); - - // Set up a location class - _location = (FGLocation *) new FGLocation; - // Load animations vector animation_nodes = props.getChildren("animation"); unsigned int i; @@ -238,6 +237,27 @@ FG3DModel::init (const string &path) _animations.push_back(animation); } } + } + + // Load sub-models + vector model_nodes = props.getChildren("model"); + for (i = 0; i < model_nodes.size(); i++) { + SGPropertyNode_ptr node = model_nodes[i]; + ssgTransform * align = new ssgTransform; + sgMat4 res_matrix; + make_offsets_matrix(&res_matrix, + node->getFloatValue("offsets/heading-deg", 0.0), + node->getFloatValue("offsets/roll-deg", 0.0), + node->getFloatValue("offsets/pitch-deg", 0.0), + node->getFloatValue("offsets/x-m", 0.0), + 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); } } @@ -246,90 +266,10 @@ 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); - - _location->setPosition( _lon_deg, _lat_deg, _elev_ft ); - _location->setOrientation( _roll_deg, _pitch_deg, _heading_deg ); - - sgMat4 POS; - sgCopyMat4(POS, _location->getTransformMatrix()); - - sgVec3 trans; - sgCopyVec3(trans, _location->get_view_pos()); - - for(i = 0; i < 4; i++) { - float tmp = POS[i][3]; - for( int j=0; j<3; j++ ) { - POS[i][j] += (tmp * trans[j]); - } - } - _position->setTransform(POS); -} - -bool -FG3DModel::getVisible () const -{ - return (_selector->getSelect() != 0); -} - -void -FG3DModel::setVisible (bool visible) -{ - _selector->select(visible); -} - -void -FG3DModel::setLongitudeDeg (double lon_deg) -{ - _lon_deg = lon_deg; -} - -void -FG3DModel::setLatitudeDeg (double lat_deg) -{ - _lat_deg = lat_deg; -} - -void -FG3DModel::setElevationFt (double elev_ft) -{ - _elev_ft = elev_ft; -} - -void -FG3DModel::setPosition (double lon_deg, double lat_deg, double elev_ft) -{ - _lon_deg = lon_deg; - _lat_deg = lat_deg; - _elev_ft = elev_ft; -} - -void -FG3DModel::setRollDeg (double roll_deg) -{ - _roll_deg = roll_deg; -} - -void -FG3DModel::setPitchDeg (double pitch_deg) -{ - _pitch_deg = pitch_deg; -} - -void -FG3DModel::setHeadingDeg (double heading_deg) -{ - _heading_deg = heading_deg; -} - -void -FG3DModel::setOrientation (double roll_deg, double pitch_deg, - double heading_deg) -{ - _roll_deg = roll_deg; - _pitch_deg = pitch_deg; - _heading_deg = heading_deg; } FG3DModel::Animation * @@ -711,4 +651,126 @@ FG3DModel::TranslateAnimation::update (double dt) } + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGModelPlacement. +//////////////////////////////////////////////////////////////////////// + +FGModelPlacement::FGModelPlacement () + : _model(new FG3DModel), + _lon_deg(0), + _lat_deg(0), + _elev_ft(0), + _roll_deg(0), + _pitch_deg(0), + _heading_deg(0), + _selector(new ssgSelector), + _position(new ssgTransform), + _location(new FGLocation) +{ +} + +FGModelPlacement::~FGModelPlacement () +{ + delete _model; + delete _selector; +} + +void +FGModelPlacement::init (const string &path) +{ + _model->init(path); + _position->addKid(_model->getSceneGraph()); + _selector->addKid(_position); + _selector->clrTraversalMaskBits(SSGTRAV_HOT); +} + +void +FGModelPlacement::update (double dt) +{ + _model->update(dt); + + _location->setPosition( _lon_deg, _lat_deg, _elev_ft ); + _location->setOrientation( _roll_deg, _pitch_deg, _heading_deg ); + + sgMat4 POS; + sgCopyMat4(POS, _location->getTransformMatrix()); + + sgVec3 trans; + sgCopyVec3(trans, _location->get_view_pos()); + + for(int i = 0; i < 4; i++) { + float tmp = POS[i][3]; + for( int j=0; j<3; j++ ) { + POS[i][j] += (tmp * trans[j]); + } + } + _position->setTransform(POS); +} + +bool +FGModelPlacement::getVisible () const +{ + return (_selector->getSelect() != 0); +} + +void +FGModelPlacement::setVisible (bool visible) +{ + _selector->select(visible); +} + +void +FGModelPlacement::setLongitudeDeg (double lon_deg) +{ + _lon_deg = lon_deg; +} + +void +FGModelPlacement::setLatitudeDeg (double lat_deg) +{ + _lat_deg = lat_deg; +} + +void +FGModelPlacement::setElevationFt (double elev_ft) +{ + _elev_ft = elev_ft; +} + +void +FGModelPlacement::setPosition (double lon_deg, double lat_deg, double elev_ft) +{ + _lon_deg = lon_deg; + _lat_deg = lat_deg; + _elev_ft = elev_ft; +} + +void +FGModelPlacement::setRollDeg (double roll_deg) +{ + _roll_deg = roll_deg; +} + +void +FGModelPlacement::setPitchDeg (double pitch_deg) +{ + _pitch_deg = pitch_deg; +} + +void +FGModelPlacement::setHeadingDeg (double heading_deg) +{ + _heading_deg = heading_deg; +} + +void +FGModelPlacement::setOrientation (double roll_deg, double pitch_deg, + double heading_deg) +{ + _roll_deg = roll_deg; + _pitch_deg = pitch_deg; + _heading_deg = heading_deg; +} + // end of model.cxx diff --git a/src/Model/model.hxx b/src/Model/model.hxx index bc48663ac..cc5142519 100644 --- a/src/Model/model.hxx +++ b/src/Model/model.hxx @@ -39,6 +39,7 @@ class FGLocation; #undef max #endif + class FG3DModel { public: @@ -49,57 +50,21 @@ public: virtual void init (const string &path); virtual void update (double 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 setLongitudeDeg (double lon_deg); - virtual void setLatitudeDeg (double lat_deg); - virtual void setElevationFt (double elev_ft); - virtual void setPosition (double lon_deg, double lat_deg, double elev_ft); - - virtual double getRollDeg () const { return _roll_deg; } - virtual double getPitchDeg () const { return _pitch_deg; } - virtual double getHeadingDeg () const { return _heading_deg; } - - virtual void setRollDeg (double roll_deg); - virtual void setPitchDeg (double pitch_deg); - virtual void setHeadingDeg (double heading_deg); - virtual void setOrientation (double roll_deg, double pitch_deg, - double heading_deg); - - virtual ssgEntity * getSceneGraph () const { return (ssgEntity *)_selector; } - - virtual FGLocation * getFGLocation () const { return _location; } + virtual ssgEntity * getSceneGraph () const { return (ssgEntity *)_model; } 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; + // Child models. + vector _children; // Animations vector _animations; // Scene graph ssgBranch * _model; - ssgSelector * _selector; - ssgTransform * _position; - - // Location - FGLocation * _location; @@ -278,6 +243,65 @@ private: }; + +class FGModelPlacement +{ +public: + + FGModelPlacement (); + virtual ~FGModelPlacement (); + + virtual void init (const string &path); + virtual void update (double dt); + + virtual ssgEntity * getSceneGraph () { return (ssgEntity *)_selector; } + + virtual FGLocation * getFGLocation () { return _location; } + + 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 setLongitudeDeg (double lon_deg); + virtual void setLatitudeDeg (double lat_deg); + virtual void setElevationFt (double elev_ft); + virtual void setPosition (double lon_deg, double lat_deg, double elev_ft); + + virtual double getRollDeg () const { return _roll_deg; } + virtual double getPitchDeg () const { return _pitch_deg; } + virtual double getHeadingDeg () const { return _heading_deg; } + + virtual void setRollDeg (double roll_deg); + virtual void setPitchDeg (double pitch_deg); + virtual void setHeadingDeg (double heading_deg); + virtual void setOrientation (double roll_deg, double pitch_deg, + double heading_deg); + +private: + + FG3DModel * _model; + + // Geodetic position + double _lon_deg; + double _lat_deg; + double _elev_ft; + + // Orientation + double _roll_deg; + double _pitch_deg; + double _heading_deg; + + ssgSelector * _selector; + ssgTransform * _position; + + // Location + FGLocation * _location; + +}; + #endif // __MODEL_HXX diff --git a/src/Model/modelmgr.cxx b/src/Model/modelmgr.cxx index 5d7f2afd4..ce15e6078 100644 --- a/src/Model/modelmgr.cxx +++ b/src/Model/modelmgr.cxx @@ -36,7 +36,7 @@ FGModelMgr::init () SG_LOG(SG_GENERAL, SG_INFO, "Adding model " << node->getStringValue("name", "[unnamed]")); Instance * instance = new Instance; - FG3DModel * model = new FG3DModel; + FGModelPlacement * model = new FGModelPlacement; instance->model = model; model->init(node->getStringValue("path", "Models/Geometry/glider.ac")); @@ -102,7 +102,7 @@ FGModelMgr::update (double dt) { for (unsigned int i = 0; i < _instances.size(); i++) { Instance * instance = _instances[i]; - FG3DModel * model = instance->model; + FGModelPlacement * model = instance->model; // Optionally set position from properties if (instance->lon_deg_node != 0) diff --git a/src/Model/modelmgr.hxx b/src/Model/modelmgr.hxx index 8f953875a..d0b7841cd 100644 --- a/src/Model/modelmgr.hxx +++ b/src/Model/modelmgr.hxx @@ -21,7 +21,7 @@ SG_USING_STD(vector); // Don't pull in headers, since we don't need them here. class ssgSelector; class SGPropertyNode; -class FG3DModel; +class FGModelPlacement; /** @@ -46,7 +46,7 @@ private: { Instance (); virtual ~Instance (); - FG3DModel * model; + FGModelPlacement * model; SGPropertyNode * lon_deg_node; SGPropertyNode * lat_deg_node; SGPropertyNode * elev_ft_node;