1 // model.cxx - manage a 3D aircraft model.
2 // Written by David Megginson, started 2002.
4 // This file is in the Public Domain, and comes with no warranty.
13 #include <simgear/compiler.h>
14 #include <simgear/debug/logstream.hxx>
15 #include <simgear/misc/exception.hxx>
17 #include "globals.hxx"
18 #include "fg_props.hxx"
19 #include "viewmgr.hxx"
22 extern unsigned long int fgSimTime; // FIXME: this is ugly
24 extern ssgRoot * scene; // FIXME: from main.cxx
26 FGAircraftModel current_model; // FIXME: add to globals
30 find_named_node (ssgEntity * node, const string &name)
32 char * node_name = node->getName();
33 if (node_name != 0 && name == node_name)
35 else if (node->isAKindOf(ssgTypeBranch())) {
36 int nKids = node->getNumKids();
37 for (int i = 0; i < nKids; i++) {
39 find_named_node(((ssgBranch*)node)->getKid(i), name);
47 FGAircraftModel::FGAircraftModel ()
49 _selector(new ssgSelector),
50 _position(new ssgTransform),
55 FGAircraftModel::~FGAircraftModel ()
57 // since the nodes are attached to the scene graph, they'll be
58 // deleted automatically
62 FGAircraftModel::init ()
64 // TODO: optionally load an XML file with a pointer to the 3D object
65 // and placement and animation info
67 // Load the 3D aircraft object itself
68 SGPath path = globals->get_fg_root();
69 path.append(fgGetString("/sim/model/path", "Models/Geometry/glider.ac"));
70 ssgTexturePath((char *)path.dir().c_str());
71 _object = ssgLoad((char *)path.c_str());
73 _object = ssgLoad((char *)"Models/Geometry/glider.ac");
75 throw sg_exception("Failed to load an aircraft model");
79 ssgEntity * prop_node = find_named_node(_object, "Propeller");
81 std::cout << "Found propeller node" << std::endl;
82 std::cout << "User data is " << int(prop_node->getUserData()) << std::endl;
83 _prop_position = new ssgTransform;
84 int nParents = prop_node->getNumParents();
85 _prop_position->addKid(prop_node);
86 std::cout << "Found " << nParents << " parent(s)" << std::endl;
87 for (int i = 0; i < nParents; i++) {
88 ssgBranch * parent = prop_node->getParent(i);
89 parent->replaceKid(prop_node, _prop_position);
92 std::cout << "Did not find propeller node" << std::endl;
95 // Set up the alignment node
96 ssgTransform * align = new ssgTransform;
97 align->addKid(_object);
101 float h_rot = fgGetFloat("/sim/model/heading-offset-deg", 0.0);
102 float p_rot = fgGetFloat("/sim/model/roll-offset-deg", 0.0);
103 float r_rot = fgGetFloat("/sim/model/pitch-offset-deg", 0.0);
104 float x_off = fgGetFloat("/sim/model/x-offset-m", 0.0);
105 float y_off = fgGetFloat("/sim/model/y-offset-m", 0.0);
106 float z_off = fgGetFloat("/sim/model/z-offset-m", 0.0);
107 sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot);
108 sgMakeTransMat4(off_matrix, x_off, y_off, z_off);
109 sgMultMat4(res_matrix, off_matrix, rot_matrix);
110 align->setTransform(res_matrix);
112 // Set up the position node
113 _position->addKid(align);
115 // Set up the selector node
116 _selector->addKid(_position);
117 _selector->clrTraversalMaskBits(SSGTRAV_HOT);
118 scene->addKid(_selector);
122 FGAircraftModel::bind ()
127 FGAircraftModel::unbind ()
132 FGAircraftModel::update (int dt)
134 // START TEMPORARY KLUDGE
135 static float prop_rotation = 0;
136 static sgMat4 prop_matrix;
138 _current_timestamp.stamp();
139 long ms = (_current_timestamp - _last_timestamp) / 1000;
140 _last_timestamp.stamp();
142 double rpms = fgGetDouble("/engines/engine[0]/rpm") / 60000.0;
143 prop_rotation += (ms * rpms * 360);
144 while (prop_rotation >= 360)
145 prop_rotation -= 360;
146 // END TEMPORARY KLUDGE
148 if (globals->get_viewmgr()->get_current() == 0
149 && !fgGetBool("/sim/model/enable-interior")) {
150 _selector->select(false);
152 // TODO: use correct alignment in pilot
154 _selector->select(true);
155 FGViewerRPH *pilot_view =
156 (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
159 sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
162 sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
165 sgMakeRotMat4( sgROT, -90.0, ownship_up );
168 sgCopyMat4( sgTUX, sgROT );
169 sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
170 sgPostMultMat4( sgTUX, sgTRANS );
173 sgSetCoord( &tuxpos, sgTUX );
174 _position->setTransform( &tuxpos );
176 // START TEMPORARY KLUDGE
177 if (_prop_position != 0) {
178 double offset = fgGetDouble("/tmp/offset", -.75);
180 sgMakeTransMat4(prop_matrix, 0, 0, offset);
181 sgMakeRotMat4(tmp, 0, 0, prop_rotation);
182 sgPostMultMat4(prop_matrix, tmp);
183 sgMakeTransMat4(tmp, 0, 0, -offset);
184 sgPostMultMat4(prop_matrix, tmp);
185 _prop_position->setTransform(prop_matrix);
187 // END_TEMPORARY KLUDGE