subsystem, FGAircraftModel.
fg_props.cxx fg_props.hxx \
fgfs.cxx fgfs.hxx \
globals.cxx globals.hxx \
+ model.cxx model.hxx \
options.cxx options.hxx \
splash.cxx splash.hxx \
viewer.cxx viewer.hxx \
#include "splash.hxx"
#include "viewmgr.hxx"
#include "options.hxx"
+#include "model.hxx"
#ifdef macintosh
# include <console.h> // -dw- for command line dialog
ssgRoot *scene = NULL;
ssgBranch *terrain = NULL;
-// aircraft model stuff
-ssgSelector *acmodel_selector = NULL;
-ssgTransform *acmodel_pos = NULL;
-ssgSelector *prop_selector = NULL;
-ssgSelector *flaps_selector = NULL;
-int acmodel_npropsettings;
-int acmodel_proprpms[4][2]; // different propeller settings
-
ssgRoot *lighting = NULL;
ssgBranch *ground = NULL;
ssgBranch *airport = NULL;
ssgSetNearFar( 0.5f, 120000.0f );
}
- if ( globals->get_viewmgr()->get_current() == 0 ) {
- // disable aircraft model
- acmodel_selector->select(0);
- } else {
- // enable aircraft model and set up its position and orientation
- acmodel_selector->select(1);
-
- FGViewerRPH *pilot_view =
- (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
-
- sgMat4 sgTRANS;
- sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
-
- sgVec3 ownship_up;
- sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
-
- sgMat4 sgROT;
- sgMakeRotMat4( sgROT, -90.0, ownship_up );
-
- // sgMat4 sgTMP;
- // sgMat4 sgTUX;
- // sgMultMat4( sgTMP, sgROT, pilot_view.VIEW_ROT );
- // sgMultMat4( sgTUX, sgTMP, sgTRANS );
-
- // sgTUX = ( sgROT * pilot_view.VIEW_ROT ) * sgTRANS
- sgMat4 sgTUX;
- sgCopyMat4( sgTUX, sgROT );
- sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
- sgPostMultMat4( sgTUX, sgTRANS );
-
- sgCoord tuxpos;
- sgSetCoord( &tuxpos, sgTUX );
- acmodel_pos->setTransform( &tuxpos );
-
- // set up moving parts
- if (flaps_selector != NULL) {
- flaps_selector->select( (globals->get_controls()->get_flaps() > 0.5f) ? 1 : 2 );
- }
-
- if (prop_selector != NULL) {
- int propsel_mask = 0;
- double rpm = fgGetDouble("/engines/engine[0]/rpm");
- for (int i = 0; i < acmodel_npropsettings; i++) {
- if (rpm >= acmodel_proprpms[i][0] &&
- rpm <= acmodel_proprpms[i][1]) {
- propsel_mask |= 1 << i;
- }
- }
- prop_selector->select(propsel_mask);
- }
- }
+ current_model.update(0); // FIXME: use real delta time
// $$$ begin - added VS Renganthan 17 Oct 2K
fgUpdateDCS();
// ADA
// temporary visible aircraft "own ship"
- acmodel_selector = new ssgSelector;
- acmodel_pos = new ssgTransform;
-
- ssgEntity *acmodel_obj = NULL;
- if (fgGetString("/sim/flight-model") == "ada") {
- // ada exteranl aircraft model loading
- if( !ship_pos[0]->getKid(0) ) {
- // fall back to default
- ssgEntity *acmodel_obj = ssgLoad( (char *)"glider.ac" );
- if( !acmodel_obj ) {
- SG_LOG( SG_GENERAL, SG_ALERT, "FAILED to LOAD an AC model! ..." );
- exit(-1);
- }
- acmodel_pos->addKid( acmodel_obj );
- } else {
- acmodel_obj = ship_pos[0]->getKid(0);
- }
- } else {
- // default aircraft model loading
-
- // Get the model location, and load textures from the same
- // directory. Use an absolute path for the model to avoid
- // incompatibilities in different versions of PLIB.
- string acmodel_path =
- fgGetString("/sim/model/path", "Models/Geometry/glider.ac");
- SGPath full_model = globals->get_fg_root();
- full_model.append(acmodel_path);
-
- ssgTexturePath( (char *)full_model.dir().c_str() );
- acmodel_obj = ssgLoad( (char *)full_model.c_str() );
- if( !acmodel_obj ) {
- // fall back to default
- acmodel_obj = ssgLoad( (char *)"Models/Geometry/glider.ac" );
- if( !acmodel_obj ) {
- SG_LOG( SG_GENERAL, SG_ALERT, "FAILED to LOAD an AC model! ..." );
- exit(-1);
- }
- }
- }
-
- // find moving parts (if this is an MDL model)
- flaps_selector = (ssgSelector*)fgFindNode( acmodel_obj, "FLAPS" );
- prop_selector = (ssgSelector*)fgFindNode( acmodel_obj, "PROP" );
-
- acmodel_npropsettings = 0;
- if (prop_selector != NULL) {
- for (ssgEntity* kid = prop_selector->getKid(0); kid != NULL;
- kid = prop_selector->getNextKid()) {
- int prop_low, prop_high;
- if ( sscanf(kid->getName(), "PROP_%d_%d",
- &prop_low, &prop_high) == 2 ) {
- prop_low = (int)((float)prop_low * (5000.0f / 32767.0f));
- prop_high = (int)((float)prop_high * (5000.0f / 32767.0f));
- acmodel_proprpms[acmodel_npropsettings][0] = prop_low ;
- acmodel_proprpms[acmodel_npropsettings][1] = prop_high;
- acmodel_npropsettings++;
-
- SG_LOG( SG_GENERAL, SG_INFO, "PROPELLER SETTING " << prop_low <<
- " " << prop_high );
- }
- }
- }
-
- // align the model properly for FGFS
- ssgTransform *acmodel_align = new ssgTransform;
- acmodel_align->addKid(acmodel_obj);
- sgMat4 rot_matrix;
- sgMat4 off_matrix;
- sgMat4 res_matrix;
- float h_rot = fgGetFloat("/sim/model/heading-offset-deg", 0.0);
- float p_rot = fgGetFloat("/sim/model/roll-offset-deg", 0.0);
- float r_rot = fgGetFloat("/sim/model/pitch-offset-deg", 0.0);
- float x_off = fgGetFloat("/sim/model/x-offset-m", 0.0);
- float y_off = fgGetFloat("/sim/model/y-offset-m", 0.0);
- float z_off = fgGetFloat("/sim/model/z-offset-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);
- acmodel_align->setTransform(res_matrix);
-
- acmodel_pos->addKid( acmodel_align );
- acmodel_selector->addKid( acmodel_pos );
- //ssgFlatten( acmodel_obj );
- //ssgStripify( acmodel_selector );
- acmodel_selector->clrTraversalMaskBits( SSGTRAV_HOT );
- scene->addKid( acmodel_selector );
+ current_model.init();
#ifdef FG_NETWORK_OLK
// Do the network intialization
--- /dev/null
+// 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 <config.h>
+#endif
+
+#include <plib/sg.h>
+#include <plib/ssg.h>
+
+#include <simgear/compiler.h>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/exception.hxx>
+
+#include "globals.hxx"
+#include "fg_props.hxx"
+#include "viewmgr.hxx"
+#include "model.hxx"
+
+extern unsigned long int fgSimTime; // FIXME: this is ugly
+
+extern ssgRoot * scene; // FIXME: from main.cxx
+
+FGAircraftModel current_model; // FIXME: add to globals
+
+
+static ssgEntity *
+find_named_node (ssgEntity * node, const string &name)
+{
+ char * node_name = node->getName();
+ if (node_name != 0 && 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;
+ }
+}
+
+FGAircraftModel::FGAircraftModel ()
+ : _object(0),
+ _selector(new ssgSelector),
+ _position(new ssgTransform),
+ _prop_position(0)
+{
+}
+
+FGAircraftModel::~FGAircraftModel ()
+{
+ // since the nodes are attached to the scene graph, they'll be
+ // deleted automatically
+}
+
+void
+FGAircraftModel::init ()
+{
+ // TODO: optionally load an XML file with a pointer to the 3D object
+ // and placement and animation info
+
+ // Load the 3D aircraft object itself
+ SGPath path = globals->get_fg_root();
+ path.append(fgGetString("/sim/model/path", "Models/Geometry/glider.ac"));
+ ssgTexturePath((char *)path.dir().c_str());
+ _object = ssgLoad((char *)path.c_str());
+ if (_object == 0) {
+ _object = ssgLoad((char *)"Models/Geometry/glider.ac");
+ if (_object == 0)
+ throw sg_exception("Failed to load an aircraft model");
+ }
+
+ // Find the propeller
+ ssgEntity * prop_node = find_named_node(_object, "Propeller");
+ if (prop_node != 0) {
+ std::cout << "Found propeller node" << std::endl;
+ std::cout << "User data is " << int(prop_node->getUserData()) << std::endl;
+ _prop_position = new ssgTransform;
+ int nParents = prop_node->getNumParents();
+ _prop_position->addKid(prop_node);
+ std::cout << "Found " << nParents << " parent(s)" << std::endl;
+ for (int i = 0; i < nParents; i++) {
+ ssgBranch * parent = prop_node->getParent(i);
+ parent->replaceKid(prop_node, _prop_position);
+ }
+ } else {
+ std::cout << "Did not find propeller node" << std::endl;
+ }
+
+ // Set up the alignment node
+ ssgTransform * align = new ssgTransform;
+ align->addKid(_object);
+ sgMat4 rot_matrix;
+ sgMat4 off_matrix;
+ sgMat4 res_matrix;
+ float h_rot = fgGetFloat("/sim/model/heading-offset-deg", 0.0);
+ float p_rot = fgGetFloat("/sim/model/roll-offset-deg", 0.0);
+ float r_rot = fgGetFloat("/sim/model/pitch-offset-deg", 0.0);
+ float x_off = fgGetFloat("/sim/model/x-offset-m", 0.0);
+ float y_off = fgGetFloat("/sim/model/y-offset-m", 0.0);
+ float z_off = fgGetFloat("/sim/model/z-offset-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);
+ scene->addKid(_selector);
+}
+
+void
+FGAircraftModel::bind ()
+{
+}
+
+void
+FGAircraftModel::unbind ()
+{
+}
+
+void
+FGAircraftModel::update (int dt)
+{
+ // START TEMPORARY KLUDGE
+ static float prop_rotation = 0;
+ static sgMat4 prop_matrix;
+
+ _current_timestamp.stamp();
+ long ms = (_current_timestamp - _last_timestamp) / 1000;
+ _last_timestamp.stamp();
+
+ double rpms = fgGetDouble("/engines/engine[0]/rpm") / 60000.0;
+ prop_rotation += (ms * rpms * 360);
+ while (prop_rotation >= 360)
+ prop_rotation -= 360;
+ // END TEMPORARY KLUDGE
+
+ if (globals->get_viewmgr()->get_current() == 0
+ && !fgGetBool("/sim/model/enable-interior")) {
+ _selector->select(false);
+ } else {
+ // TODO: use correct alignment in pilot
+ // view.
+ _selector->select(true);
+ FGViewerRPH *pilot_view =
+ (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
+
+ sgMat4 sgTRANS;
+ sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
+
+ sgVec3 ownship_up;
+ sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
+
+ sgMat4 sgROT;
+ sgMakeRotMat4( sgROT, -90.0, ownship_up );
+
+ sgMat4 sgTUX;
+ sgCopyMat4( sgTUX, sgROT );
+ sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
+ sgPostMultMat4( sgTUX, sgTRANS );
+
+ sgCoord tuxpos;
+ sgSetCoord( &tuxpos, sgTUX );
+ _position->setTransform( &tuxpos );
+
+ // START TEMPORARY KLUDGE
+ if (_prop_position != 0) {
+ double offset = fgGetDouble("/tmp/offset", -.75);
+ sgMat4 tmp;
+ sgMakeTransMat4(prop_matrix, 0, 0, offset);
+ sgMakeRotMat4(tmp, 0, 0, prop_rotation);
+ sgPostMultMat4(prop_matrix, tmp);
+ sgMakeTransMat4(tmp, 0, 0, -offset);
+ sgPostMultMat4(prop_matrix, tmp);
+ _prop_position->setTransform(prop_matrix);
+ }
+ // END_TEMPORARY KLUDGE
+ }
+}
+
+// end of model.cxx
--- /dev/null
+// 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 "fgfs.hxx"
+#include <simgear/timing/timestamp.hxx>
+
+class FGAircraftModel : public FGSubsystem
+{
+public:
+
+ FGAircraftModel ();
+ virtual ~FGAircraftModel ();
+
+ virtual void init ();
+ virtual void bind ();
+ virtual void unbind ();
+ virtual void update (int dt);
+
+private:
+
+ ssgEntity * _object;
+ ssgSelector * _selector;
+ ssgTransform * _position;
+
+ SGTimeStamp _last_timestamp;
+ SGTimeStamp _current_timestamp;
+
+ ssgTransform * _prop_position;
+
+};
+
+extern FGAircraftModel current_model;
+
+#endif // __MODEL_HXX
+