From: david Date: Fri, 5 Apr 2002 03:19:34 +0000 (+0000) Subject: Moved FGAircraftModel subsystem out into its own directory, and X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=625572663e47fb4d801a3f18e7f83971da5bb519;p=flightgear.git 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). --- 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/Main/model.cxx b/src/Main/model.cxx deleted file mode 100644 index 461c5a8e4..000000000 --- a/src/Main/model.cxx +++ /dev/null @@ -1,586 +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 // for strcmp() - -#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 - -FGAircraftModel current_model; // FIXME: add to globals - - - -//////////////////////////////////////////////////////////////////////// -// Static utility functions. -//////////////////////////////////////////////////////////////////////// - -/** - * Locate a named SSG node in a branch. - */ -static ssgEntity * -find_named_node (ssgEntity * node, const char * name) -{ - char * node_name = node->getName(); - if (node_name != 0 && !strcmp(name, node_name)) - return node; - else if (node->isAKindOf(ssgTypeBranch())) { - int nKids = node->getNumKids(); - for (int i = 0; i < nKids; i++) { - ssgEntity * result = - find_named_node(((ssgBranch*)node)->getKid(i), name); - if (result != 0) - return result; - } - } - return 0; -} - -/** - * Splice a branch in between all child nodes and their parents. - */ -static void -splice_branch (ssgBranch * branch, ssgEntity * child) -{ - int nParents = child->getNumParents(); - branch->addKid(child); - for (int i = 0; i < nParents; i++) { - ssgBranch * parent = child->getParent(i); - parent->replaceKid(child, branch); - } -} - -/** - * Set up the transform matrix for a spin or rotation. - */ -static void -set_rotation (sgMat4 &matrix, double position_deg, - sgVec3 ¢er, sgVec3 &axis) -{ - float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ; - - float s = (float) sin ( temp_angle ) ; - float c = (float) cos ( temp_angle ) ; - float t = SG_ONE - c ; - - // axis was normalized at load time - // hint to the compiler to put these into FP registers - float x = axis[0]; - float y = axis[1]; - float z = axis[2]; - - matrix[0][0] = t * x * x + c ; - matrix[0][1] = t * y * x - s * z ; - matrix[0][2] = t * z * x + s * y ; - matrix[0][3] = SG_ZERO; - - matrix[1][0] = t * x * y + s * z ; - matrix[1][1] = t * y * y + c ; - matrix[1][2] = t * z * y - s * x ; - matrix[1][3] = SG_ZERO; - - matrix[2][0] = t * x * z - s * y ; - matrix[2][1] = t * y * z + s * x ; - matrix[2][2] = t * z * z + c ; - matrix[2][3] = SG_ZERO; - - // hint to the compiler to put these into FP registers - x = center[0]; - y = center[1]; - z = center[2]; - - matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0]; - matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1]; - matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2]; - matrix[3][3] = SG_ONE; -} - -/** - * Set up the transform matrix for a translation. - */ -static void -set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis) -{ - sgVec3 xyz; - sgScaleVec3(xyz, axis, position_m); - sgMakeTransMat4(matrix, xyz); -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel -//////////////////////////////////////////////////////////////////////// - -FGAircraftModel::FGAircraftModel () - : _model(0), - _selector(new ssgSelector), - _position(new ssgTransform) -{ -} - -FGAircraftModel::~FGAircraftModel () -{ - // since the nodes are attached to the scene graph, they'll be - // deleted automatically - - for (int i = 0; i < _animations.size(); i++) { - Animation * tmp = _animations[i]; - _animations[i] = 0; - delete tmp; - } - -} - -void -FGAircraftModel::init () -{ - // 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"); - xmlpath.append(modelpath.str()); - - 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"; - } - } - - 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"); - } - - // Load animations - vector animation_nodes = props.getChildren("animation"); - for (unsigned int i = 0; i < animation_nodes.size(); i++) { - vector name_nodes = - animation_nodes[i]->getChildren("object-name"); - if (name_nodes.size() < 1) { - SG_LOG(SG_INPUT, SG_ALERT, "No object-name given for transformation"); - } else { - for (unsigned int j = 0; j < name_nodes.size(); j++) { - Animation * animation = - make_animation(name_nodes[j]->getStringValue(), animation_nodes[i]); - if (animation != 0) - _animations.push_back(animation); - } - } - } - - // 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); - align->setTransform(res_matrix); - - // Set up the position node - _position->addKid(align); - - // Set up the selector node - _selector->addKid(_position); - _selector->clrTraversalMaskBits(SSGTRAV_HOT); - cockpit->addKid(_selector); -} - -void -FGAircraftModel::bind () -{ -} - -void -FGAircraftModel::unbind () -{ -} - -void -FGAircraftModel::update (int dt) -{ - sgMat4 MODEL_ROT, LOCAL; - sgMat4 sgTRANS; - - int view_number = globals->get_viewmgr()->get_current(); - - 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 ); - } -} - -FGAircraftModel::Animation * -FGAircraftModel::make_animation (const char * object_name, - SGPropertyNode * node) -{ - Animation * animation = 0; - const char * type = node->getStringValue("type"); - if (!strcmp("none", type)) { - animation = new NullAnimation(); - } else if (!strcmp("select", type)) { - animation = new SelectAnimation(); - } else if (!strcmp("spin", type)) { - animation = new SpinAnimation(); - } else if (!strcmp("rotate", type)) { - animation = new RotateAnimation(); - } else if (!strcmp("translate", type)) { - animation = new TranslateAnimation(); - } else { - animation = new NullAnimation(); - SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); - } - - ssgEntity * object = find_named_node(_model, object_name); - if (object == 0) { - SG_LOG(SG_INPUT, SG_WARN, "Object " << object_name << " not found"); - delete animation; - animation = 0; - } else { - animation->init(object, node); - } - - return animation; -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::Animation -//////////////////////////////////////////////////////////////////////// - -FGAircraftModel::Animation::Animation () -{ -} - -FGAircraftModel::Animation::~Animation () -{ -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::NullAnimation -//////////////////////////////////////////////////////////////////////// - -FGAircraftModel::NullAnimation::NullAnimation () - : _branch(new ssgBranch) -{ -} - -FGAircraftModel::NullAnimation::~NullAnimation () -{ - _branch = 0; -} - -void -FGAircraftModel::NullAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - splice_branch(_branch, object); - _branch->setName(props->getStringValue("name", 0)); -} - -void -FGAircraftModel::NullAnimation::update (int dt) -{ -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::SelectAnimation -//////////////////////////////////////////////////////////////////////// - -FGAircraftModel::SelectAnimation::SelectAnimation () - : _condition(0), - _selector(new ssgSelector) -{ -} - -FGAircraftModel::SelectAnimation::~SelectAnimation () -{ - delete _condition; - _selector = 0; -} - -void -FGAircraftModel::SelectAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - splice_branch(_selector, object); - _selector->setName(props->getStringValue("name", 0)); - SGPropertyNode * node = props->getChild("condition"); - if (node != 0) { - _condition = fgReadCondition(node); - } -} - -void -FGAircraftModel::SelectAnimation::update (int dt) -{ - if (_condition != 0 && _condition->test()) - _selector->select(0xffff); - else - _selector->select(0x0000); -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::SpinAnimation -//////////////////////////////////////////////////////////////////////// - -FGAircraftModel::SpinAnimation::SpinAnimation () - : _prop(0), - _factor(0), - _position_deg(0), - _transform(new ssgTransform) -{ -} - -FGAircraftModel::SpinAnimation::~SpinAnimation () -{ - _transform = 0; -} - -void -FGAircraftModel::SpinAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - // Splice in the new transform node - splice_branch(_transform, object); - _transform->setName(props->getStringValue("name", 0)); - _prop = fgGetNode(props->getStringValue("property", "/null"), true); - _factor = props->getDoubleValue("factor", 1.0); - _position_deg = props->getDoubleValue("starting-position-deg", 0); - _center[0] = props->getFloatValue("center/x-m", 0); - _center[1] = props->getFloatValue("center/y-m", 0); - _center[2] = props->getFloatValue("center/z-m", 0); - _axis[0] = props->getFloatValue("axis/x", 0); - _axis[1] = props->getFloatValue("axis/y", 0); - _axis[2] = props->getFloatValue("axis/z", 0); - sgNormalizeVec3(_axis); -} - -void -FGAircraftModel::SpinAnimation::update (int dt) -{ - float velocity_rpms = (_prop->getDoubleValue() * _factor / 60000.0); - _position_deg += (dt * velocity_rpms * 360); - while (_position_deg < 0) - _position_deg += 360.0; - while (_position_deg >= 360.0) - _position_deg -= 360.0; - set_rotation(_matrix, _position_deg, _center, _axis); - _transform->setTransform(_matrix); -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::RotateAnimation -//////////////////////////////////////////////////////////////////////// - -FGAircraftModel::RotateAnimation::RotateAnimation () - : _prop(0), - _offset_deg(0.0), - _factor(1.0), - _has_min(false), - _min_deg(0.0), - _has_max(false), - _max_deg(1.0), - _position_deg(0.0), - _transform(new ssgTransform) -{ -} - -FGAircraftModel::RotateAnimation::~RotateAnimation () -{ - _transform = 0; -} - -void -FGAircraftModel::RotateAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - // Splice in the new transform node - splice_branch(_transform, object); - _transform->setName(props->getStringValue("name", 0)); - _prop = fgGetNode(props->getStringValue("property", "/null"), true); - _offset_deg = props->getDoubleValue("offset-deg", 0.0); - _factor = props->getDoubleValue("factor", 1.0); - if (props->hasValue("min-deg")) { - _has_min = true; - _min_deg = props->getDoubleValue("min-deg"); - } - if (props->hasValue("max-deg")) { - _has_max = true; - _max_deg = props->getDoubleValue("max-deg"); - } - _position_deg = props->getDoubleValue("starting-position-deg", 0); - _center[0] = props->getFloatValue("center/x-m", 0); - _center[1] = props->getFloatValue("center/y-m", 0); - _center[2] = props->getFloatValue("center/z-m", 0); - _axis[0] = props->getFloatValue("axis/x", 0); - _axis[1] = props->getFloatValue("axis/y", 0); - _axis[2] = props->getFloatValue("axis/z", 0); - sgNormalizeVec3(_axis); -} - -void -FGAircraftModel::RotateAnimation::update (int dt) -{ - _position_deg = ((_prop->getDoubleValue() + _offset_deg) * _factor); - if (_has_min && _position_deg < _min_deg) - _position_deg = _min_deg; - if (_has_max && _position_deg > _max_deg) - _position_deg = _max_deg; - set_rotation(_matrix, _position_deg, _center, _axis); - _transform->setTransform(_matrix); -} - - - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGAircraftModel::TranslateAnimation -//////////////////////////////////////////////////////////////////////// - -FGAircraftModel::TranslateAnimation::TranslateAnimation () - : _prop(0), - _offset_m(0.0), - _factor(1.0), - _has_min(false), - _min_m(0.0), - _has_max(false), - _max_m(1.0), - _position_m(0.0), - _transform(new ssgTransform) -{ -} - -FGAircraftModel::TranslateAnimation::~TranslateAnimation () -{ - _transform = 0; -} - -void -FGAircraftModel::TranslateAnimation::init (ssgEntity * object, - SGPropertyNode * props) -{ - // Splice in the new transform node - splice_branch(_transform, object); - _transform->setName(props->getStringValue("name", 0)); - _prop = fgGetNode(props->getStringValue("property", "/null"), true); - _offset_m = props->getDoubleValue("offset-m", 0.0); - _factor = props->getDoubleValue("factor", 1.0); - if (props->hasValue("min-m")) { - _has_min = true; - _min_m = props->getDoubleValue("min-m"); - } - if (props->hasValue("max-m")) { - _has_max = true; - _max_m = props->getDoubleValue("max-m"); - } - _position_m = props->getDoubleValue("starting-position-m", 0); - _axis[0] = props->getFloatValue("axis/x", 0); - _axis[1] = props->getFloatValue("axis/y", 0); - _axis[2] = props->getFloatValue("axis/z", 0); - sgNormalizeVec3(_axis); -} - -void -FGAircraftModel::TranslateAnimation::update (int dt) -{ - _position_m = ((_prop->getDoubleValue() + _offset_m) * _factor); - if (_has_min && _position_m < _min_m) - _position_m = _min_m; - if (_has_max && _position_m > _max_m) - _position_m = _max_m; - set_translation(_matrix, _position_m, _axis); - _transform->setTransform(_matrix); -} - - -// end of model.cxx diff --git a/src/Main/model.hxx b/src/Main/model.hxx deleted file mode 100644 index 439f6eef1..000000000 --- a/src/Main/model.hxx +++ /dev/null @@ -1,202 +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 -#include - -SG_USING_STD(string); -SG_USING_STD(vector); - -#include "fgfs.hxx" -#include -#include - -// Has anyone done anything *really* stupid, like making min and max macros? -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif - -class FGAircraftModel : public FGSubsystem -{ -public: - - FGAircraftModel (); - virtual ~FGAircraftModel (); - - virtual void init (); - virtual void bind (); - virtual void unbind (); - virtual void update (int dt); - -private: - - class Animation; - - Animation * make_animation (const char * object_name, SGPropertyNode * node); - - ssgEntity * _model; - ssgSelector * _selector; - ssgTransform * _position; - - vector _animations; - - - - ////////////////////////////////////////////////////////////////////// - // Internal classes for individual animations. - ////////////////////////////////////////////////////////////////////// - - /** - * Abstract base class for all animations. - */ - class Animation - { - public: - - Animation (); - - virtual ~Animation (); - - /** - * Initialize the animation. - * - * @param object The object to animate. - * @param props The property node with configuration information. - */ - virtual void init (ssgEntity * object, SGPropertyNode * props) = 0; - - - /** - * Update the animation. - * - * @param dt The elapsed time in milliseconds since the last call. - */ - virtual void update (int dt) = 0; - - }; - - - /** - * A no-op animation. - */ - class NullAnimation : public Animation - { - public: - NullAnimation (); - virtual ~NullAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (int dt); - private: - ssgBranch * _branch; - }; - - - /** - * Animation to select alternative versions of the same object. - */ - class SelectAnimation : public Animation - { - public: - SelectAnimation (); - virtual ~SelectAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (int dt); - private: - FGCondition * _condition; - ssgSelector * _selector; - }; - - - /** - * Animation to spin an object around a center point. - * - * This animation rotates at a specific velocity. - */ - class SpinAnimation : public Animation - { - public: - SpinAnimation (); - virtual ~SpinAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (int dt); - private: - SGPropertyNode * _prop; - double _factor; - double _position_deg; - sgMat4 _matrix; - sgVec3 _center; - sgVec3 _axis; - ssgTransform * _transform; - }; - - - /** - * Animation to rotate an object around a center point. - * - * This animation rotates to a specific position. - */ - class RotateAnimation : public Animation - { - public: - RotateAnimation (); - virtual ~RotateAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (int dt); - private: - SGPropertyNode * _prop; - double _offset_deg; - double _factor; - bool _has_min; - double _min_deg; - bool _has_max; - double _max_deg; - double _position_deg; - sgMat4 _matrix; - sgVec3 _center; - sgVec3 _axis; - ssgTransform * _transform; - }; - - - /** - * Animation to slide along an axis. - */ - class TranslateAnimation : public Animation - { - public: - TranslateAnimation (); - virtual ~TranslateAnimation (); - virtual void init (ssgEntity * object, SGPropertyNode * props); - virtual void update (int dt); - private: - SGPropertyNode * _prop; - double _offset_m; - double _factor; - bool _has_min; - double _min_m; - bool _has_max; - double _max_m; - double _position_m; - sgMat4 _matrix; - sgVec3 _axis; - ssgTransform * _transform; - }; - -}; - -extern FGAircraftModel current_model; - -#endif // __MODEL_HXX - 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/Model/model.cxx b/src/Model/model.cxx new file mode 100644 index 000000000..33f16cedd --- /dev/null +++ b/src/Model/model.cxx @@ -0,0 +1,598 @@ +// 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 + +#include "model.hxx" + + + +//////////////////////////////////////////////////////////////////////// +// Static utility functions. +//////////////////////////////////////////////////////////////////////// + +/** + * Locate a named SSG node in a branch. + */ +static ssgEntity * +find_named_node (ssgEntity * node, const char * name) +{ + char * node_name = node->getName(); + if (node_name != 0 && !strcmp(name, node_name)) + return node; + else if (node->isAKindOf(ssgTypeBranch())) { + int nKids = node->getNumKids(); + for (int i = 0; i < nKids; i++) { + ssgEntity * result = + find_named_node(((ssgBranch*)node)->getKid(i), name); + if (result != 0) + return result; + } + } + return 0; +} + +/** + * Splice a branch in between all child nodes and their parents. + */ +static void +splice_branch (ssgBranch * branch, ssgEntity * child) +{ + int nParents = child->getNumParents(); + branch->addKid(child); + for (int i = 0; i < nParents; i++) { + ssgBranch * parent = child->getParent(i); + parent->replaceKid(child, branch); + } +} + +/** + * Set up the transform matrix for a spin or rotation. + */ +static void +set_rotation (sgMat4 &matrix, double position_deg, + sgVec3 ¢er, sgVec3 &axis) +{ + float temp_angle = -position_deg * SG_DEGREES_TO_RADIANS ; + + float s = (float) sin ( temp_angle ) ; + float c = (float) cos ( temp_angle ) ; + float t = SG_ONE - c ; + + // axis was normalized at load time + // hint to the compiler to put these into FP registers + float x = axis[0]; + float y = axis[1]; + float z = axis[2]; + + matrix[0][0] = t * x * x + c ; + matrix[0][1] = t * y * x - s * z ; + matrix[0][2] = t * z * x + s * y ; + matrix[0][3] = SG_ZERO; + + matrix[1][0] = t * x * y + s * z ; + matrix[1][1] = t * y * y + c ; + matrix[1][2] = t * z * y - s * x ; + matrix[1][3] = SG_ZERO; + + matrix[2][0] = t * x * z - s * y ; + matrix[2][1] = t * y * z + s * x ; + matrix[2][2] = t * z * z + c ; + matrix[2][3] = SG_ZERO; + + // hint to the compiler to put these into FP registers + x = center[0]; + y = center[1]; + z = center[2]; + + matrix[3][0] = x - x*matrix[0][0] - y*matrix[1][0] - z*matrix[2][0]; + matrix[3][1] = y - x*matrix[0][1] - y*matrix[1][1] - z*matrix[2][1]; + matrix[3][2] = z - x*matrix[0][2] - y*matrix[1][2] - z*matrix[2][2]; + matrix[3][3] = SG_ONE; +} + +/** + * Set up the transform matrix for a translation. + */ +static void +set_translation (sgMat4 &matrix, double position_m, sgVec3 &axis) +{ + sgVec3 xyz; + sgScaleVec3(xyz, axis, position_m); + sgMakeTransMat4(matrix, xyz); +} + + +// 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 FG3DModel +//////////////////////////////////////////////////////////////////////// + +FG3DModel::FG3DModel () + : _model(0), + _selector(new ssgSelector), + _position(new ssgTransform) +{ +} + +FG3DModel::~FG3DModel () +{ + // since the nodes are attached to the scene graph, they'll be + // deleted automatically + + for (int i = 0; i < _animations.size(); i++) { + Animation * tmp = _animations[i]; + _animations[i] = 0; + delete tmp; + } + +} + +void +FG3DModel::init (const string &path) +{ + SGPropertyNode props; + + // Load the 3D aircraft object itself + SGPath xmlpath = globals->get_fg_root(); + 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 { + 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) + throw sg_exception("Failed to load 3D model"); + + // Load animations + vector animation_nodes = props.getChildren("animation"); + for (unsigned int i = 0; i < animation_nodes.size(); i++) { + vector name_nodes = + animation_nodes[i]->getChildren("object-name"); + if (name_nodes.size() < 1) { + SG_LOG(SG_INPUT, SG_ALERT, "No object-name given for transformation"); + } else { + for (unsigned int j = 0; j < name_nodes.size(); j++) { + Animation * animation = + make_animation(name_nodes[j]->getStringValue(), animation_nodes[i]); + if (animation != 0) + _animations.push_back(animation); + } + } + } + + // 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); + align->setTransform(res_matrix); + + // Set up the position node + _position->addKid(align); + + // Set up the selector node + _selector->addKid(_position); + _selector->clrTraversalMaskBits(SSGTRAV_HOT); +} + +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); +} + +bool +FG3DModel::getVisible () const +{ + return _selector->getSelect(); +} + +void +FG3DModel::setVisible (bool visible) +{ + _selector->select(visible); +} + +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::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::make_animation (const char * object_name, + SGPropertyNode * node) +{ + Animation * animation = 0; + const char * type = node->getStringValue("type"); + if (!strcmp("none", type)) { + animation = new NullAnimation(); + } else if (!strcmp("select", type)) { + animation = new SelectAnimation(); + } else if (!strcmp("spin", type)) { + animation = new SpinAnimation(); + } else if (!strcmp("rotate", type)) { + animation = new RotateAnimation(); + } else if (!strcmp("translate", type)) { + animation = new TranslateAnimation(); + } else { + animation = new NullAnimation(); + SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); + } + + ssgEntity * object = find_named_node(_model, object_name); + if (object == 0) { + SG_LOG(SG_INPUT, SG_WARN, "Object " << object_name << " not found"); + delete animation; + animation = 0; + } else { + animation->init(object, node); + } + + return animation; +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FG3DModel::Animation +//////////////////////////////////////////////////////////////////////// + +FG3DModel::Animation::Animation () +{ +} + +FG3DModel::Animation::~Animation () +{ +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FG3DModel::NullAnimation +//////////////////////////////////////////////////////////////////////// + +FG3DModel::NullAnimation::NullAnimation () + : _branch(new ssgBranch) +{ +} + +FG3DModel::NullAnimation::~NullAnimation () +{ + _branch = 0; +} + +void +FG3DModel::NullAnimation::init (ssgEntity * object, + SGPropertyNode * props) +{ + splice_branch(_branch, object); + _branch->setName(props->getStringValue("name", 0)); +} + +void +FG3DModel::NullAnimation::update (int dt) +{ +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FG3DModel::SelectAnimation +//////////////////////////////////////////////////////////////////////// + +FG3DModel::SelectAnimation::SelectAnimation () + : _condition(0), + _selector(new ssgSelector) +{ +} + +FG3DModel::SelectAnimation::~SelectAnimation () +{ + delete _condition; + _selector = 0; +} + +void +FG3DModel::SelectAnimation::init (ssgEntity * object, + SGPropertyNode * props) +{ + splice_branch(_selector, object); + _selector->setName(props->getStringValue("name", 0)); + SGPropertyNode * node = props->getChild("condition"); + if (node != 0) { + _condition = fgReadCondition(node); + } +} + +void +FG3DModel::SelectAnimation::update (int dt) +{ + if (_condition != 0 && _condition->test()) + _selector->select(0xffff); + else + _selector->select(0x0000); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FG3DModel::SpinAnimation +//////////////////////////////////////////////////////////////////////// + +FG3DModel::SpinAnimation::SpinAnimation () + : _prop(0), + _factor(0), + _position_deg(0), + _transform(new ssgTransform) +{ +} + +FG3DModel::SpinAnimation::~SpinAnimation () +{ + _transform = 0; +} + +void +FG3DModel::SpinAnimation::init (ssgEntity * object, + SGPropertyNode * props) +{ + // Splice in the new transform node + splice_branch(_transform, object); + _transform->setName(props->getStringValue("name", 0)); + _prop = fgGetNode(props->getStringValue("property", "/null"), true); + _factor = props->getDoubleValue("factor", 1.0); + _position_deg = props->getDoubleValue("starting-position-deg", 0); + _center[0] = props->getFloatValue("center/x-m", 0); + _center[1] = props->getFloatValue("center/y-m", 0); + _center[2] = props->getFloatValue("center/z-m", 0); + _axis[0] = props->getFloatValue("axis/x", 0); + _axis[1] = props->getFloatValue("axis/y", 0); + _axis[2] = props->getFloatValue("axis/z", 0); + sgNormalizeVec3(_axis); +} + +void +FG3DModel::SpinAnimation::update (int dt) +{ + float velocity_rpms = (_prop->getDoubleValue() * _factor / 60000.0); + _position_deg += (dt * velocity_rpms * 360); + while (_position_deg < 0) + _position_deg += 360.0; + while (_position_deg >= 360.0) + _position_deg -= 360.0; + set_rotation(_matrix, _position_deg, _center, _axis); + _transform->setTransform(_matrix); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FG3DModel::RotateAnimation +//////////////////////////////////////////////////////////////////////// + +FG3DModel::RotateAnimation::RotateAnimation () + : _prop(0), + _offset_deg(0.0), + _factor(1.0), + _has_min(false), + _min_deg(0.0), + _has_max(false), + _max_deg(1.0), + _position_deg(0.0), + _transform(new ssgTransform) +{ +} + +FG3DModel::RotateAnimation::~RotateAnimation () +{ + _transform = 0; +} + +void +FG3DModel::RotateAnimation::init (ssgEntity * object, + SGPropertyNode * props) +{ + // Splice in the new transform node + splice_branch(_transform, object); + _transform->setName(props->getStringValue("name", 0)); + _prop = fgGetNode(props->getStringValue("property", "/null"), true); + _offset_deg = props->getDoubleValue("offset-deg", 0.0); + _factor = props->getDoubleValue("factor", 1.0); + if (props->hasValue("min-deg")) { + _has_min = true; + _min_deg = props->getDoubleValue("min-deg"); + } + if (props->hasValue("max-deg")) { + _has_max = true; + _max_deg = props->getDoubleValue("max-deg"); + } + _position_deg = props->getDoubleValue("starting-position-deg", 0); + _center[0] = props->getFloatValue("center/x-m", 0); + _center[1] = props->getFloatValue("center/y-m", 0); + _center[2] = props->getFloatValue("center/z-m", 0); + _axis[0] = props->getFloatValue("axis/x", 0); + _axis[1] = props->getFloatValue("axis/y", 0); + _axis[2] = props->getFloatValue("axis/z", 0); + sgNormalizeVec3(_axis); +} + +void +FG3DModel::RotateAnimation::update (int dt) +{ + _position_deg = ((_prop->getDoubleValue() + _offset_deg) * _factor); + if (_has_min && _position_deg < _min_deg) + _position_deg = _min_deg; + if (_has_max && _position_deg > _max_deg) + _position_deg = _max_deg; + set_rotation(_matrix, _position_deg, _center, _axis); + _transform->setTransform(_matrix); +} + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FG3DModel::TranslateAnimation +//////////////////////////////////////////////////////////////////////// + +FG3DModel::TranslateAnimation::TranslateAnimation () + : _prop(0), + _offset_m(0.0), + _factor(1.0), + _has_min(false), + _min_m(0.0), + _has_max(false), + _max_m(1.0), + _position_m(0.0), + _transform(new ssgTransform) +{ +} + +FG3DModel::TranslateAnimation::~TranslateAnimation () +{ + _transform = 0; +} + +void +FG3DModel::TranslateAnimation::init (ssgEntity * object, + SGPropertyNode * props) +{ + // Splice in the new transform node + splice_branch(_transform, object); + _transform->setName(props->getStringValue("name", 0)); + _prop = fgGetNode(props->getStringValue("property", "/null"), true); + _offset_m = props->getDoubleValue("offset-m", 0.0); + _factor = props->getDoubleValue("factor", 1.0); + if (props->hasValue("min-m")) { + _has_min = true; + _min_m = props->getDoubleValue("min-m"); + } + if (props->hasValue("max-m")) { + _has_max = true; + _max_m = props->getDoubleValue("max-m"); + } + _position_m = props->getDoubleValue("starting-position-m", 0); + _axis[0] = props->getFloatValue("axis/x", 0); + _axis[1] = props->getFloatValue("axis/y", 0); + _axis[2] = props->getFloatValue("axis/z", 0); + sgNormalizeVec3(_axis); +} + +void +FG3DModel::TranslateAnimation::update (int dt) +{ + _position_m = ((_prop->getDoubleValue() + _offset_m) * _factor); + if (_has_min && _position_m < _min_m) + _position_m = _min_m; + if (_has_max && _position_m > _max_m) + _position_m = _max_m; + set_translation(_matrix, _position_m, _axis); + _transform->setTransform(_matrix); +} + + +// end of model.cxx diff --git a/src/Model/model.hxx b/src/Model/model.hxx new file mode 100644 index 000000000..08aa4bafb --- /dev/null +++ b/src/Model/model.hxx @@ -0,0 +1,225 @@ +// 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 + +SG_USING_STD(vector); + +#include
+ +// Has anyone done anything *really* stupid, like making min and max macros? +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif + +class FG3DModel +{ +public: + + FG3DModel (); + virtual ~FG3DModel (); + + 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; + + + + ////////////////////////////////////////////////////////////////////// + // Internal classes for individual animations. + ////////////////////////////////////////////////////////////////////// + + /** + * Abstract base class for all animations. + */ + class Animation + { + public: + + Animation (); + + virtual ~Animation (); + + /** + * Initialize the animation. + * + * @param object The object to animate. + * @param props The property node with configuration information. + */ + virtual void init (ssgEntity * object, SGPropertyNode * props) = 0; + + + /** + * Update the animation. + * + * @param dt The elapsed time in milliseconds since the last call. + */ + virtual void update (int dt) = 0; + + }; + + + /** + * A no-op animation. + */ + class NullAnimation : public Animation + { + public: + NullAnimation (); + virtual ~NullAnimation (); + virtual void init (ssgEntity * object, SGPropertyNode * props); + virtual void update (int dt); + private: + ssgBranch * _branch; + }; + + + /** + * Animation to select alternative versions of the same object. + */ + class SelectAnimation : public Animation + { + public: + SelectAnimation (); + virtual ~SelectAnimation (); + virtual void init (ssgEntity * object, SGPropertyNode * props); + virtual void update (int dt); + private: + FGCondition * _condition; + ssgSelector * _selector; + }; + + + /** + * Animation to spin an object around a center point. + * + * This animation rotates at a specific velocity. + */ + class SpinAnimation : public Animation + { + public: + SpinAnimation (); + virtual ~SpinAnimation (); + virtual void init (ssgEntity * object, SGPropertyNode * props); + virtual void update (int dt); + private: + SGPropertyNode * _prop; + double _factor; + double _position_deg; + sgMat4 _matrix; + sgVec3 _center; + sgVec3 _axis; + ssgTransform * _transform; + }; + + + /** + * Animation to rotate an object around a center point. + * + * This animation rotates to a specific position. + */ + class RotateAnimation : public Animation + { + public: + RotateAnimation (); + virtual ~RotateAnimation (); + virtual void init (ssgEntity * object, SGPropertyNode * props); + virtual void update (int dt); + private: + SGPropertyNode * _prop; + double _offset_deg; + double _factor; + bool _has_min; + double _min_deg; + bool _has_max; + double _max_deg; + double _position_deg; + sgMat4 _matrix; + sgVec3 _center; + sgVec3 _axis; + ssgTransform * _transform; + }; + + + /** + * Animation to slide along an axis. + */ + class TranslateAnimation : public Animation + { + public: + TranslateAnimation (); + virtual ~TranslateAnimation (); + virtual void init (ssgEntity * object, SGPropertyNode * props); + virtual void update (int dt); + private: + SGPropertyNode * _prop; + double _offset_m; + double _factor; + bool _has_min; + double _min_m; + bool _has_max; + double _max_m; + double _position_m; + sgMat4 _matrix; + sgVec3 _axis; + ssgTransform * _transform; + }; + +}; + +#endif // __MODEL_HXX +