]> git.mxchange.org Git - flightgear.git/blob - src/Main/model.cxx
If the model path specified ends with .xml, then read properties from
[flightgear.git] / src / Main / model.cxx
1 // model.cxx - manage a 3D aircraft model.
2 // Written by David Megginson, started 2002.
3 //
4 // This file is in the Public Domain, and comes with no warranty.
5
6 #ifdef HAVE_CONFIG_H
7 #  include <config.h>
8 #endif
9
10 #include <plib/sg.h>
11 #include <plib/ssg.h>
12
13 #include <simgear/compiler.h>
14 #include <simgear/debug/logstream.hxx>
15 #include <simgear/misc/exception.hxx>
16 #include <simgear/misc/sg_path.hxx>
17
18 #include "globals.hxx"
19 #include "fg_props.hxx"
20 #include "viewmgr.hxx"
21 #include "model.hxx"
22
23 extern unsigned long int fgSimTime; // FIXME: this is ugly
24
25 extern ssgRoot * scene;         // FIXME: from main.cxx
26
27 FGAircraftModel current_model;  // FIXME: add to globals
28
29
30 static ssgEntity *
31 find_named_node (ssgEntity * node, const string &name)
32 {
33   char * node_name = node->getName();
34   if (node_name != 0 && name == node_name)
35     return node;
36   else if (node->isAKindOf(ssgTypeBranch())) {
37     int nKids = node->getNumKids();
38     for (int i = 0; i < nKids; i++) {
39       ssgEntity * result =
40         find_named_node(((ssgBranch*)node)->getKid(i), name);
41       if (result != 0)
42         return result;
43     }
44   } 
45   return 0;
46 }
47
48 FGAircraftModel::FGAircraftModel ()
49   : _props(new SGPropertyNode),
50     _object(0),
51     _selector(new ssgSelector),
52     _position(new ssgTransform),
53     _prop_position(0)
54 {
55 }
56
57 FGAircraftModel::~FGAircraftModel ()
58 {
59   delete _props;
60   // since the nodes are attached to the scene graph, they'll be
61   // deleted automatically
62 }
63
64 void 
65 FGAircraftModel::init ()
66 {
67   // TODO: optionally load an XML file with a pointer to the 3D object
68   // and placement and animation info
69
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"));
73
74   if (path.str().substr(path.str().size() - 4, 4) == ".xml") {
75     readProperties(path.str(), _props);
76     if (_props->hasValue("/path")) {
77       path = path.dir();;
78       path.append(_props->getStringValue("/path"));
79     } else {
80       path = globals->get_fg_root();
81       path.append("Models/Geometry/glider.ac");
82     }
83   }
84
85   ssgTexturePath((char *)path.dir().c_str());
86   _object = ssgLoad((char *)path.c_str());
87   if (_object == 0) {
88     _object = ssgLoad((char *)"Models/Geometry/glider.ac");
89     if (_object == 0)
90       throw sg_exception("Failed to load an aircraft model");
91   }
92
93                                 // Find the propeller
94   ssgEntity * prop_node = find_named_node(_object, "Propeller");
95   if (prop_node != 0) {
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);
102     }
103   }
104
105                                 // Set up the alignment node
106   ssgTransform * align = new ssgTransform;
107   align->addKid(_object);
108   sgMat4 rot_matrix;
109   sgMat4 off_matrix;
110   sgMat4 res_matrix;
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);
121
122                                 // Set up the position node
123   _position->addKid(align);
124
125                                 // Set up the selector node
126   _selector->addKid(_position);
127   _selector->clrTraversalMaskBits(SSGTRAV_HOT);
128   scene->addKid(_selector);
129 }
130
131 void 
132 FGAircraftModel::bind ()
133 {
134 }
135
136 void 
137 FGAircraftModel::unbind ()
138 {
139 }
140
141 void
142 FGAircraftModel::update (int dt)
143 {
144   // START TEMPORARY KLUDGE
145   static float prop_rotation = 0;
146   static sgMat4 prop_matrix;
147
148   _current_timestamp.stamp();
149   long ms = (_current_timestamp - _last_timestamp) / 1000;
150   _last_timestamp.stamp();
151
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
157
158   if (globals->get_viewmgr()->get_current() == 0) {
159     _selector->select(false);
160   } else {
161     _selector->select(true);
162     FGViewerRPH *pilot_view =
163       (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
164     
165     sgMat4 sgTRANS;
166     sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
167     
168     sgVec3 ownship_up;
169     sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
170     
171     sgMat4 sgROT;
172     sgMakeRotMat4( sgROT, -90.0, ownship_up );
173     
174     sgMat4 sgTUX;
175     sgCopyMat4( sgTUX, sgROT );
176     sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
177     sgPostMultMat4( sgTUX, sgTRANS );
178     
179     sgCoord tuxpos;
180     sgSetCoord( &tuxpos, sgTUX );
181     _position->setTransform( &tuxpos );
182
183     // START TEMPORARY KLUDGE
184     if (_prop_position != 0) {
185       double offset = -.75;
186       sgMat4 tmp;
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);
193     }
194     // END_TEMPORARY KLUDGE
195   }
196 }
197
198 // end of model.cxx