1
0
Fork 0

Separate the model geodetic position and orientation into a separate

class, FGModelPlacement, while FG3DModel retains control of animation.
This way, we can have a single, top-level placement, but multiple
layers of nested models underneath.  To include a nested model, use
something like this in the XML wrapper:

  <model>
   <path>Models/Stuff/my-component.xml</path>
   <offsets>
    <roll-offset-deg>45</roll-offset-deg>
   </offsets>
  </model>
This commit is contained in:
david 2002-06-10 13:20:26 +00:00
parent 0cabedaa4f
commit a74c184cfb
6 changed files with 239 additions and 153 deletions

View file

@ -51,7 +51,7 @@ FGAircraftModel::~FGAircraftModel ()
void void
FGAircraftModel::init () FGAircraftModel::init ()
{ {
_aircraft = new FG3DModel; _aircraft = new FGModelPlacement;
string path = fgGetString("/sim/model/path", "Models/Geometry/glider.ac"); string path = fgGetString("/sim/model/path", "Models/Geometry/glider.ac");
try { try {
_aircraft->init(path); _aircraft->init(path);

View file

@ -21,7 +21,7 @@ SG_USING_STD(vector);
// Don't pull in the headers, since we don't need them here. // Don't pull in the headers, since we don't need them here.
class ssgRoot; class ssgRoot;
class ssgSelector; class ssgSelector;
class FG3DModel; class FGModelPlacement;
class FGAircraftModel : public FGSubsystem class FGAircraftModel : public FGSubsystem
@ -36,11 +36,11 @@ public:
virtual void unbind (); virtual void unbind ();
virtual void update (double dt); virtual void update (double dt);
virtual void draw (); virtual void draw ();
virtual FG3DModel * get3DModel() { return _aircraft; } virtual FGModelPlacement * get3DModel() { return _aircraft; }
private: private:
FG3DModel * _aircraft; FGModelPlacement * _aircraft;
ssgSelector * _selector; ssgSelector * _selector;
ssgRoot * _scene; ssgRoot * _scene;
float _nearplane; float _nearplane;

View file

@ -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. * Read an interpolation table from properties.
*/ */
@ -151,9 +166,7 @@ read_interpolation_table (const SGPropertyNode * props)
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
FG3DModel::FG3DModel () FG3DModel::FG3DModel ()
: _model(0), : _model(0)
_selector(new ssgSelector),
_position(new ssgTransform)
{ {
} }
@ -198,30 +211,16 @@ FG3DModel::init (const string &path)
// Set up the alignment node // Set up the alignment node
ssgTransform * align = new ssgTransform; ssgTransform * align = new ssgTransform;
align->addKid(_model); align->addKid(_model);
sgMat4 rot_matrix;
sgMat4 off_matrix;
sgMat4 res_matrix; sgMat4 res_matrix;
float h_rot = props.getFloatValue("/offsets/heading-deg", 0.0); make_offsets_matrix(&res_matrix,
float p_rot = props.getFloatValue("/offsets/roll-deg", 0.0); props.getFloatValue("/offsets/heading-deg", 0.0),
float r_rot = props.getFloatValue("/offsets/pitch-deg", 0.0); props.getFloatValue("/offsets/roll-deg", 0.0),
float x_off = props.getFloatValue("/offsets/x-m", 0.0); props.getFloatValue("/offsets/pitch-deg", 0.0),
float y_off = props.getFloatValue("/offsets/y-m", 0.0); props.getFloatValue("/offsets/x-m", 0.0),
float z_off = props.getFloatValue("/offsets/z-m", 0.0); props.getFloatValue("/offsets/y-m", 0.0),
sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot); props.getFloatValue("/offsets/z-m", 0.0));
sgMakeTransMat4(off_matrix, x_off, y_off, z_off);
sgMultMat4(res_matrix, off_matrix, rot_matrix);
align->setTransform(res_matrix); 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 // Load animations
vector<SGPropertyNode_ptr> animation_nodes = props.getChildren("animation"); vector<SGPropertyNode_ptr> animation_nodes = props.getChildren("animation");
unsigned int i; unsigned int i;
@ -238,6 +237,27 @@ FG3DModel::init (const string &path)
_animations.push_back(animation); _animations.push_back(animation);
} }
} }
}
// Load sub-models
vector<SGPropertyNode_ptr> 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; unsigned int i;
for (i = 0; i < _children.size(); i++)
_children[i]->update(dt);
for (i = 0; i < _animations.size(); i++) for (i = 0; i < _animations.size(); i++)
_animations[i]->update(dt); _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 * 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 // end of model.cxx

View file

@ -39,6 +39,7 @@ class FGLocation;
#undef max #undef max
#endif #endif
class FG3DModel class FG3DModel
{ {
public: public:
@ -49,57 +50,21 @@ public:
virtual void init (const string &path); virtual void init (const string &path);
virtual void update (double dt); virtual void update (double dt);
virtual bool getVisible () const; virtual ssgEntity * getSceneGraph () const { return (ssgEntity *)_model; }
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; }
private: private:
class Animation; class Animation;
Animation * make_animation (const char * object_name, SGPropertyNode * node); Animation * make_animation (const char * object_name, SGPropertyNode * node);
// Geodetic position // Child models.
double _lon_deg; vector<FG3DModel *> _children;
double _lat_deg;
double _elev_ft;
// Orientation
double _roll_deg;
double _pitch_deg;
double _heading_deg;
// Animations // Animations
vector <Animation *> _animations; vector <Animation *> _animations;
// Scene graph // Scene graph
ssgBranch * _model; 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 #endif // __MODEL_HXX

View file

@ -36,7 +36,7 @@ FGModelMgr::init ()
SG_LOG(SG_GENERAL, SG_INFO, SG_LOG(SG_GENERAL, SG_INFO,
"Adding model " << node->getStringValue("name", "[unnamed]")); "Adding model " << node->getStringValue("name", "[unnamed]"));
Instance * instance = new Instance; Instance * instance = new Instance;
FG3DModel * model = new FG3DModel; FGModelPlacement * model = new FGModelPlacement;
instance->model = model; instance->model = model;
model->init(node->getStringValue("path", "Models/Geometry/glider.ac")); 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++) { for (unsigned int i = 0; i < _instances.size(); i++) {
Instance * instance = _instances[i]; Instance * instance = _instances[i];
FG3DModel * model = instance->model; FGModelPlacement * model = instance->model;
// Optionally set position from properties // Optionally set position from properties
if (instance->lon_deg_node != 0) if (instance->lon_deg_node != 0)

View file

@ -21,7 +21,7 @@ SG_USING_STD(vector);
// Don't pull in headers, since we don't need them here. // Don't pull in headers, since we don't need them here.
class ssgSelector; class ssgSelector;
class SGPropertyNode; class SGPropertyNode;
class FG3DModel; class FGModelPlacement;
/** /**
@ -46,7 +46,7 @@ private:
{ {
Instance (); Instance ();
virtual ~Instance (); virtual ~Instance ();
FG3DModel * model; FGModelPlacement * model;
SGPropertyNode * lon_deg_node; SGPropertyNode * lon_deg_node;
SGPropertyNode * lat_deg_node; SGPropertyNode * lat_deg_node;
SGPropertyNode * elev_ft_node; SGPropertyNode * elev_ft_node;