]> git.mxchange.org Git - flightgear.git/blob - src/Main/model.cxx
Separated 3D model-handling code from main.cxx out into its own
[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
17 #include "globals.hxx"
18 #include "fg_props.hxx"
19 #include "viewmgr.hxx"
20 #include "model.hxx"
21
22 extern unsigned long int fgSimTime; // FIXME: this is ugly
23
24 extern ssgRoot * scene;         // FIXME: from main.cxx
25
26 FGAircraftModel current_model;  // FIXME: add to globals
27
28
29 static ssgEntity *
30 find_named_node (ssgEntity * node, const string &name)
31 {
32   char * node_name = node->getName();
33   if (node_name != 0 && name == node_name)
34     return node;
35   else if (node->isAKindOf(ssgTypeBranch())) {
36     int nKids = node->getNumKids();
37     for (int i = 0; i < nKids; i++) {
38       ssgEntity * result =
39         find_named_node(((ssgBranch*)node)->getKid(i), name);
40       if (result != 0)
41         return result;
42     }
43     return 0;
44   }
45 }
46
47 FGAircraftModel::FGAircraftModel ()
48   : _object(0),
49     _selector(new ssgSelector),
50     _position(new ssgTransform),
51     _prop_position(0)
52 {
53 }
54
55 FGAircraftModel::~FGAircraftModel ()
56 {
57   // since the nodes are attached to the scene graph, they'll be
58   // deleted automatically
59 }
60
61 void 
62 FGAircraftModel::init ()
63 {
64   // TODO: optionally load an XML file with a pointer to the 3D object
65   // and placement and animation info
66
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());
72   if (_object == 0) {
73     _object = ssgLoad((char *)"Models/Geometry/glider.ac");
74     if (_object == 0)
75       throw sg_exception("Failed to load an aircraft model");
76   }
77
78                                 // Find the propeller
79   ssgEntity * prop_node = find_named_node(_object, "Propeller");
80   if (prop_node != 0) {
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);
90     }
91   } else {
92     std::cout << "Did not find propeller node" << std::endl;
93   }
94
95                                 // Set up the alignment node
96   ssgTransform * align = new ssgTransform;
97   align->addKid(_object);
98   sgMat4 rot_matrix;
99   sgMat4 off_matrix;
100   sgMat4 res_matrix;
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);
111
112                                 // Set up the position node
113   _position->addKid(align);
114
115                                 // Set up the selector node
116   _selector->addKid(_position);
117   _selector->clrTraversalMaskBits(SSGTRAV_HOT);
118   scene->addKid(_selector);
119 }
120
121 void 
122 FGAircraftModel::bind ()
123 {
124 }
125
126 void 
127 FGAircraftModel::unbind ()
128 {
129 }
130
131 void
132 FGAircraftModel::update (int dt)
133 {
134   // START TEMPORARY KLUDGE
135   static float prop_rotation = 0;
136   static sgMat4 prop_matrix;
137
138   _current_timestamp.stamp();
139   long ms = (_current_timestamp - _last_timestamp) / 1000;
140   _last_timestamp.stamp();
141
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
147
148   if (globals->get_viewmgr()->get_current() == 0
149       && !fgGetBool("/sim/model/enable-interior")) {
150     _selector->select(false);
151   } else {
152                                 // TODO: use correct alignment in pilot
153                                 // view.
154     _selector->select(true);
155     FGViewerRPH *pilot_view =
156       (FGViewerRPH *)globals->get_viewmgr()->get_view( 0 );
157     
158     sgMat4 sgTRANS;
159     sgMakeTransMat4( sgTRANS, pilot_view->get_view_pos() );
160     
161     sgVec3 ownship_up;
162     sgSetVec3( ownship_up, 0.0, 0.0, 1.0);
163     
164     sgMat4 sgROT;
165     sgMakeRotMat4( sgROT, -90.0, ownship_up );
166     
167     sgMat4 sgTUX;
168     sgCopyMat4( sgTUX, sgROT );
169     sgPostMultMat4( sgTUX, pilot_view->get_VIEW_ROT() );
170     sgPostMultMat4( sgTUX, sgTRANS );
171     
172     sgCoord tuxpos;
173     sgSetCoord( &tuxpos, sgTUX );
174     _position->setTransform( &tuxpos );
175
176     // START TEMPORARY KLUDGE
177     if (_prop_position != 0) {
178       double offset = fgGetDouble("/tmp/offset", -.75);
179       sgMat4 tmp;
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);
186     }
187     // END_TEMPORARY KLUDGE
188   }
189 }
190
191 // end of model.cxx