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>
16 #include <simgear/misc/sg_path.hxx>
18 #include "globals.hxx"
19 #include "fg_props.hxx"
20 #include "viewmgr.hxx"
23 extern unsigned long int fgSimTime; // FIXME: this is ugly
25 extern ssgRoot * scene; // FIXME: from main.cxx
27 FGAircraftModel current_model; // FIXME: add to globals
31 find_named_node (ssgEntity * node, const string &name)
33 char * node_name = node->getName();
34 if (node_name != 0 && name == node_name)
36 else if (node->isAKindOf(ssgTypeBranch())) {
37 int nKids = node->getNumKids();
38 for (int i = 0; i < nKids; i++) {
40 find_named_node(((ssgBranch*)node)->getKid(i), name);
48 FGAircraftModel::FGAircraftModel ()
49 : _props(new SGPropertyNode),
51 _selector(new ssgSelector),
52 _position(new ssgTransform),
57 FGAircraftModel::~FGAircraftModel ()
60 // since the nodes are attached to the scene graph, they'll be
61 // deleted automatically
65 FGAircraftModel::init ()
67 // TODO: optionally load an XML file with a pointer to the 3D object
68 // and placement and animation info
70 // Load the 3D aircraft object itself
71 SGPath path = globals->get_fg_root();
72 path.append(fgGetString("/sim/model/path", "Models/Geometry/glider.ac"));
74 if (path.str().substr(path.str().size() - 4, 4) == ".xml") {
75 readProperties(path.str(), _props);
76 if (_props->hasValue("/path")) {
78 path.append(_props->getStringValue("/path"));
80 path = globals->get_fg_root();
81 path.append("Models/Geometry/glider.ac");
85 ssgTexturePath((char *)path.dir().c_str());
86 _object = ssgLoad((char *)path.c_str());
88 _object = ssgLoad((char *)"Models/Geometry/glider.ac");
90 throw sg_exception("Failed to load an aircraft model");
94 ssgEntity * prop_node = find_named_node(_object, "Propeller");
96 _prop_position = new ssgTransform;
97 int nParents = prop_node->getNumParents();
98 _prop_position->addKid(prop_node);
99 for (int i = 0; i < nParents; i++) {
100 ssgBranch * parent = prop_node->getParent(i);
101 parent->replaceKid(prop_node, _prop_position);
105 // Set up the alignment node
106 ssgTransform * align = new ssgTransform;
107 align->addKid(_object);
111 float h_rot = _props->getFloatValue("/offsets/heading-deg", 0.0);
112 float p_rot = _props->getFloatValue("/offsets/roll-deg", 0.0);
113 float r_rot = _props->getFloatValue("/offsets/pitch-deg", 0.0);
114 float x_off = _props->getFloatValue("/offsets/x-m", 0.0);
115 float y_off = _props->getFloatValue("/offsets/y-m", 0.0);
116 float z_off = _props->getFloatValue("/offsets/z-m", 0.0);
117 sgMakeRotMat4(rot_matrix, h_rot, p_rot, r_rot);
118 sgMakeTransMat4(off_matrix, x_off, y_off, z_off);
119 sgMultMat4(res_matrix, off_matrix, rot_matrix);
120 align->setTransform(res_matrix);
122 // Set up the position node
123 _position->addKid(align);
125 // Set up the selector node
126 _selector->addKid(_position);
127 _selector->clrTraversalMaskBits(SSGTRAV_HOT);
128 scene->addKid(_selector);
132 FGAircraftModel::bind ()
137 FGAircraftModel::unbind ()
142 FGAircraftModel::update (int dt)
144 // START TEMPORARY KLUDGE
145 static float prop_rotation = 0;
146 static sgMat4 prop_matrix;
148 _current_timestamp.stamp();
149 long ms = (_current_timestamp - _last_timestamp) / 1000;
150 _last_timestamp.stamp();
152 double rpms = fgGetDouble("/engines/engine[0]/rpm") / 60000.0;
153 prop_rotation += (ms * rpms * 360);
154 while (prop_rotation >= 360)
155 prop_rotation -= 360;
156 // END TEMPORARY KLUDGE
158 if (globals->get_viewmgr()->get_current() == 0) {
159 _selector->select(false);
161 _selector->select(true);
162 FGViewerRPH *pilot_view =
163 (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
166 sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
169 sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
172 sgMakeRotMat4( sgROT, -90.0, ownship_up );
175 sgCopyMat4( sgTUX, sgROT );
176 sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
177 sgPostMultMat4( sgTUX, sgTRANS );
180 sgSetCoord( &tuxpos, sgTUX );
181 _position->setTransform( &tuxpos );
183 // START TEMPORARY KLUDGE
184 if (_prop_position != 0) {
185 double offset = -.75;
187 sgMakeTransMat4(prop_matrix, 0, 0, offset);
188 sgMakeRotMat4(tmp, 0, 0, prop_rotation);
189 sgPostMultMat4(prop_matrix, tmp);
190 sgMakeTransMat4(tmp, 0, 0, -offset);
191 sgPostMultMat4(prop_matrix, tmp);
192 _prop_position->setTransform(prop_matrix);
194 // END_TEMPORARY KLUDGE