]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AICarrier.cxx
Mathias Fröhlich:
[flightgear.git] / src / AIModel / AICarrier.cxx
1 // FGAICarrier - FGAIShip-derived class creates an AI aircraft carrier
2 //
3 // Written by David Culp, started October 2004.
4 // - davidculp2@comcast.net
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 #ifdef HAVE_CONFIG_H
21 #  include <config.h>
22 #endif
23
24 #include <string>
25 #include <vector>
26
27 #include "AICarrier.hxx"
28
29
30 FGAICarrier::FGAICarrier(FGAIManager* mgr) : FGAIShip(mgr) {
31 }
32
33 FGAICarrier::~FGAICarrier() {
34 }
35
36 void FGAICarrier::setSolidObjects(const list<string>& so) {
37   solid_objects = so;
38 }
39
40 void FGAICarrier::setWireObjects(const list<string>& wo) {
41   wire_objects = wo;
42 }
43
44 void FGAICarrier::setCatapultObjects(const list<string>& co) {
45   catapult_objects = co;
46 }
47
48 void FGAICarrier::getVelocityWrtEarth(sgVec3 v) {
49   sgCopyVec3(v, vel_wrt_earth );
50 }
51
52 void FGAICarrier::update(double dt) {
53    FGAIShip::update(dt);
54
55    // Update the velocity information stored in those nodes.
56    double v_north = 0.51444444*speed*cos(hdg * SGD_DEGREES_TO_RADIANS);
57    double v_east  = 0.51444444*speed*sin(hdg * SGD_DEGREES_TO_RADIANS);
58
59    double sin_lat = sin(pos.lat() * SGD_DEGREES_TO_RADIANS);
60    double cos_lat = cos(pos.lat() * SGD_DEGREES_TO_RADIANS);
61    double sin_lon = sin(pos.lon() * SGD_DEGREES_TO_RADIANS);
62    double cos_lon = cos(pos.lon() * SGD_DEGREES_TO_RADIANS);
63    sgSetVec3( vel_wrt_earth,
64               - cos_lon*sin_lat*v_north - sin_lon*v_east,
65               - sin_lon*sin_lat*v_north + cos_lon*v_east,
66                 cos_lat*v_north );
67
68 }
69
70 bool FGAICarrier::init() {
71    if (!FGAIShip::init())
72       return false;
73
74    // process the 3d model here
75    // mark some objects solid, mark the wires ...
76
77    // The model should be used for altitude computations.
78    // To avoid that every detail in a carrier 3D model will end into
79    // the aircraft local cache, only set the HOT traversal bit on
80    // selected objects.
81    ssgEntity *sel = aip.getSceneGraph();
82    // Clear the HOT traversal flag
83    mark_nohot(sel);
84    // Selectively set that flag again for wires/cats/solid objects.
85    // Attach a pointer to this carrier class to those objects.
86    mark_wires(sel, wire_objects);
87    mark_cat(sel, catapult_objects);
88    mark_solid(sel, solid_objects);
89
90    return true;
91 }
92
93 void FGAICarrier::mark_nohot(ssgEntity* e) {
94   if (e->isAKindOf(ssgTypeBranch())) {
95     ssgBranch* br = (ssgBranch*)e;
96     ssgEntity* kid;
97     for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
98       mark_nohot(kid);
99
100     br->clrTraversalMaskBits(SSGTRAV_HOT);
101     
102   } else if (e->isAKindOf(ssgTypeLeaf())) {
103
104     e->clrTraversalMaskBits(SSGTRAV_HOT);
105
106   }
107 }
108
109 bool FGAICarrier::mark_wires(ssgEntity* e, const list<string>& wire_objects) {
110   bool found = false;
111   if (e->isAKindOf(ssgTypeBranch())) {
112
113     ssgBranch* br = (ssgBranch*)e;
114     ssgEntity* kid;
115     for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
116       found = mark_wires(kid, wire_objects) || found;
117
118     if (found)
119       br->setTraversalMaskBits(SSGTRAV_HOT);
120     
121   } else if (e->isAKindOf(ssgTypeLeaf())) {
122     list<string>::const_iterator it;
123     for (it = wire_objects.begin(); it != wire_objects.end(); ++it) {
124       if (e->getName() && (*it) == e->getName()) {
125         e->setTraversalMaskBits(SSGTRAV_HOT);
126         e->setUserData( FGAICarrierHardware::newWire( this ) );
127         ssgLeaf *l = (ssgLeaf*)e;
128         if ( l->getNumLines() != 1 ) {
129           SG_LOG(SG_GENERAL, SG_ALERT,
130                  "AICarrier: Found wires not modelled with exactly one line!");
131         }
132
133         found = true;
134       }
135     }
136   }
137   return found;
138 }
139
140 bool FGAICarrier::mark_solid(ssgEntity* e, const list<string>& solid_objects) {
141   bool found = false;
142   if (e->isAKindOf(ssgTypeBranch())) {
143     ssgBranch* br = (ssgBranch*)e;
144     ssgEntity* kid;
145     for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
146       found = mark_solid(kid, solid_objects) || found;
147
148     if (found)
149       br->setTraversalMaskBits(SSGTRAV_HOT);
150     
151   } else if (e->isAKindOf(ssgTypeLeaf())) {
152     list<string>::const_iterator it;
153     for (it = solid_objects.begin(); it != solid_objects.end(); ++it) {
154       if (e->getName() && (*it) == e->getName()) {
155         e->setTraversalMaskBits(SSGTRAV_HOT);
156         e->setUserData( FGAICarrierHardware::newSolid( this ) );
157         found = true;
158       }
159     }
160   }
161   return found;
162 }
163
164 bool FGAICarrier::mark_cat(ssgEntity* e, const list<string>& cat_objects) {
165   bool found = false;
166   if (e->isAKindOf(ssgTypeBranch())) {
167     ssgBranch* br = (ssgBranch*)e;
168     ssgEntity* kid;
169     for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
170       found = mark_cat(kid, cat_objects) || found;
171
172     if (found)
173       br->setTraversalMaskBits(SSGTRAV_HOT);
174     
175   } else if (e->isAKindOf(ssgTypeLeaf())) {
176     list<string>::const_iterator it;
177     for (it = cat_objects.begin(); it != cat_objects.end(); ++it) {
178       if (e->getName() && (*it) == e->getName()) {
179         e->setTraversalMaskBits(SSGTRAV_HOT);
180         e->setUserData( FGAICarrierHardware::newCatapult( this ) );
181         ssgLeaf *l = (ssgLeaf*)e;
182         if ( l->getNumLines() != 1 ) {
183           SG_LOG(SG_GENERAL, SG_ALERT,
184                  "AICarrier: Found a cat not modelled with exactly one line!");
185         }
186         // Now some special code to make shure the cat points in the right
187         // direction. The 0 index must be the backward end, the 1 index
188         // the forward end.
189         // Forward is positive x-direction in our 3D model, also the model
190         // as such is flattened when it is loaded, so we do not need to care
191         // for transforms ...
192         short v[2];
193         l->getLine(0, v, v+1 );
194         sgVec3 ends[2];
195         for (int k=0; k<2; ++k)
196           sgCopyVec3( ends[k], l->getVertex( v[k] ) );
197
198         // When the 1 end is behind the 0 end, swap the coordinates.
199         if (ends[0][0] < ends[1][0]) {
200           sgCopyVec3( l->getVertex( v[0] ), ends[1] );
201           sgCopyVec3( l->getVertex( v[1] ), ends[0] );
202         }
203
204         found = true;
205       }
206     }
207   }
208   return found;
209 }
210
211 int FGAICarrierHardware::unique_id = 1;