~jtaylor/ubuntu/oneiric/flightgear/fix-749249

« back to all changes in this revision

Viewing changes to src/AIModel/AICarrier.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2005-11-26 12:31:23 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20051126123123-dhs3dijy6nd257up
Tags: 0.9.8-3ubuntu1
adapt gl/glu dependencies for Xorg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <simgear/math/point3d.hxx>
 
28
#include <simgear/math/sg_geodesy.hxx>
 
29
#include <math.h>
 
30
#include <Main/util.hxx>
 
31
#include <Main/viewer.hxx>
 
32
 
 
33
#include "AICarrier.hxx"
 
34
 
 
35
 
 
36
FGAICarrier::FGAICarrier(FGAIManager* mgr) : FGAIShip(mgr) {
 
37
}
 
38
 
 
39
FGAICarrier::~FGAICarrier() {
 
40
}
 
41
 
 
42
void FGAICarrier::setSolidObjects(const list<string>& so) {
 
43
  solid_objects = so;
 
44
}
 
45
 
 
46
void FGAICarrier::setWireObjects(const list<string>& wo) {
 
47
  wire_objects = wo;
 
48
}
 
49
 
 
50
void FGAICarrier::setCatapultObjects(const list<string>& co) {
 
51
  catapult_objects = co;
 
52
}
 
53
 
 
54
void FGAICarrier::getVelocityWrtEarth(sgVec3 v) {
 
55
  sgCopyVec3(v, vel_wrt_earth );
 
56
}
 
57
 
 
58
void FGAICarrier::update(double dt) {
 
59
   UpdateFlols(dt);
 
60
   FGAIShip::update(dt);
 
61
 
 
62
   // Update the velocity information stored in those nodes.
 
63
   double v_north = 0.51444444*speed*cos(hdg * SGD_DEGREES_TO_RADIANS);
 
64
   double v_east  = 0.51444444*speed*sin(hdg * SGD_DEGREES_TO_RADIANS);
 
65
 
 
66
   double sin_lat = sin(pos.lat() * SGD_DEGREES_TO_RADIANS);
 
67
   double cos_lat = cos(pos.lat() * SGD_DEGREES_TO_RADIANS);
 
68
   double sin_lon = sin(pos.lon() * SGD_DEGREES_TO_RADIANS);
 
69
   double cos_lon = cos(pos.lon() * SGD_DEGREES_TO_RADIANS);
 
70
   sgSetVec3( vel_wrt_earth,
 
71
              - cos_lon*sin_lat*v_north - sin_lon*v_east,
 
72
              - sin_lon*sin_lat*v_north + cos_lon*v_east,
 
73
                cos_lat*v_north );
 
74
 
 
75
}
 
76
 
 
77
bool FGAICarrier::init() {
 
78
   if (!FGAIShip::init())
 
79
      return false;
 
80
 
 
81
   // process the 3d model here
 
82
   // mark some objects solid, mark the wires ...
 
83
 
 
84
   // The model should be used for altitude computations.
 
85
   // To avoid that every detail in a carrier 3D model will end into
 
86
   // the aircraft local cache, only set the HOT traversal bit on
 
87
   // selected objects.
 
88
   ssgEntity *sel = aip.getSceneGraph();
 
89
   // Clear the HOT traversal flag
 
90
   mark_nohot(sel);
 
91
   // Selectively set that flag again for wires/cats/solid objects.
 
92
   // Attach a pointer to this carrier class to those objects.
 
93
   mark_wires(sel, wire_objects);
 
94
   mark_cat(sel, catapult_objects);
 
95
   mark_solid(sel, solid_objects);
 
96
 
 
97
   return true;
 
98
}
 
99
void FGAICarrier::bind() {
 
100
   FGAIBase::bind();
 
101
 
 
102
   props->tie("controls/flols/source-lights",
 
103
                SGRawValuePointer<int>(&source));
 
104
   props->tie("controls/flols/distance-m",
 
105
                SGRawValuePointer<double>(&dist));                            
 
106
   props->setBoolValue("controls/flols/cut-lights", false);
 
107
   props->setBoolValue("controls/flols/wave-off-lights", false);
 
108
   props->setBoolValue("controls/flols/cond-datum-lights", true);  
 
109
   }
 
110
 
 
111
void FGAICarrier::unbind() {
 
112
    FGAIBase::unbind();
 
113
    props->untie("controls/flols/source-lights");
 
114
}
 
115
   
 
116
void FGAICarrier::mark_nohot(ssgEntity* e) {
 
117
  if (e->isAKindOf(ssgTypeBranch())) {
 
118
    ssgBranch* br = (ssgBranch*)e;
 
119
    ssgEntity* kid;
 
120
    for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
 
121
      mark_nohot(kid);
 
122
 
 
123
    br->clrTraversalMaskBits(SSGTRAV_HOT);
 
124
    
 
125
  } else if (e->isAKindOf(ssgTypeLeaf())) {
 
126
 
 
127
    e->clrTraversalMaskBits(SSGTRAV_HOT);
 
128
 
 
129
  }
 
130
}
 
131
 
 
132
bool FGAICarrier::mark_wires(ssgEntity* e, const list<string>& wire_objects, bool mark) {
 
133
  bool found = false;
 
134
  if (e->isAKindOf(ssgTypeBranch())) {
 
135
    ssgBranch* br = (ssgBranch*)e;
 
136
    ssgEntity* kid;
 
137
 
 
138
    list<string>::const_iterator it;
 
139
    for (it = wire_objects.begin(); it != wire_objects.end(); ++it)
 
140
      mark = mark || (e->getName() && (*it) == e->getName());
 
141
 
 
142
    for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
 
143
      found = mark_wires(kid, wire_objects, mark) || found;
 
144
 
 
145
    if (found)
 
146
      br->setTraversalMaskBits(SSGTRAV_HOT);
 
147
    
 
148
  } else if (e->isAKindOf(ssgTypeLeaf())) {
 
149
    list<string>::const_iterator it;
 
150
    for (it = wire_objects.begin(); it != wire_objects.end(); ++it) {
 
151
      if (mark || (e->getName() && (*it) == e->getName())) {
 
152
        e->setTraversalMaskBits(SSGTRAV_HOT);
 
153
        ssgBase* ud = e->getUserData();
 
154
        if (ud) {
 
155
          FGAICarrierHardware* ch = dynamic_cast<FGAICarrierHardware*>(ud);
 
156
          if (ch) {
 
157
            SG_LOG(SG_GENERAL, SG_WARN,
 
158
                   "AICarrier: Carrier hardware gets marked twice!\n"
 
159
                   "           You have propably a whole branch marked as"
 
160
                   " a wire which also includes other carrier hardware."
 
161
                   );
 
162
          } else {
 
163
            SG_LOG(SG_GENERAL, SG_ALERT,
 
164
                   "AICarrier: Found user data attached to a leaf node which "
 
165
                   "should be marked as a wire!\n    ****Skipping!****");
 
166
          }
 
167
        } else {
 
168
          e->setUserData( FGAICarrierHardware::newWire( this ) );
 
169
          ssgLeaf *l = (ssgLeaf*)e;
 
170
          if ( l->getNumLines() != 1 ) {
 
171
            SG_LOG(SG_GENERAL, SG_ALERT,
 
172
                   "AICarrier: Found wires not modelled with exactly one line!");
 
173
          }
 
174
          found = true;
 
175
        }
 
176
      }
 
177
    }
 
178
  }
 
179
  return found;
 
180
}
 
181
 
 
182
bool FGAICarrier::mark_solid(ssgEntity* e, const list<string>& solid_objects, bool mark) {
 
183
  bool found = false;
 
184
  if (e->isAKindOf(ssgTypeBranch())) {
 
185
    ssgBranch* br = (ssgBranch*)e;
 
186
    ssgEntity* kid;
 
187
 
 
188
    list<string>::const_iterator it;
 
189
    for (it = solid_objects.begin(); it != solid_objects.end(); ++it)
 
190
      mark = mark || (e->getName() && (*it) == e->getName());
 
191
 
 
192
    for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
 
193
      found = mark_solid(kid, solid_objects, mark) || found;
 
194
 
 
195
    if (found)
 
196
      br->setTraversalMaskBits(SSGTRAV_HOT);
 
197
    
 
198
  } else if (e->isAKindOf(ssgTypeLeaf())) {
 
199
    list<string>::const_iterator it;
 
200
    for (it = solid_objects.begin(); it != solid_objects.end(); ++it) {
 
201
      if (mark || (e->getName() && (*it) == e->getName())) {
 
202
        e->setTraversalMaskBits(SSGTRAV_HOT);
 
203
        ssgBase* ud = e->getUserData();
 
204
        if (ud) {
 
205
          FGAICarrierHardware* ch = dynamic_cast<FGAICarrierHardware*>(ud);
 
206
          if (ch) {
 
207
            SG_LOG(SG_GENERAL, SG_WARN,
 
208
                   "AICarrier: Carrier hardware gets marked twice!\n"
 
209
                   "           You have propably a whole branch marked solid"
 
210
                   " which also includes other carrier hardware."
 
211
                   );
 
212
          } else {
 
213
            SG_LOG(SG_GENERAL, SG_ALERT,
 
214
                   "AICarrier: Found user data attached to a leaf node which "
 
215
                   "should be marked solid!\n    ****Skipping!****");
 
216
          }
 
217
        } else {
 
218
          e->setUserData( FGAICarrierHardware::newSolid( this ) );
 
219
          found = true;
 
220
        }
 
221
      }
 
222
    }
 
223
  }
 
224
  return found;
 
225
}
 
226
 
 
227
bool FGAICarrier::mark_cat(ssgEntity* e, const list<string>& cat_objects, bool mark) {
 
228
  bool found = false;
 
229
  if (e->isAKindOf(ssgTypeBranch())) {
 
230
    ssgBranch* br = (ssgBranch*)e;
 
231
    ssgEntity* kid;
 
232
 
 
233
    list<string>::const_iterator it;
 
234
    for (it = cat_objects.begin(); it != cat_objects.end(); ++it)
 
235
      mark = mark || (e->getName() && (*it) == e->getName());
 
236
 
 
237
    for ( kid = br->getKid(0); kid != NULL ; kid = br->getNextKid() )
 
238
      found = mark_cat(kid, cat_objects, mark) || found;
 
239
 
 
240
    if (found)
 
241
      br->setTraversalMaskBits(SSGTRAV_HOT);
 
242
    
 
243
  } else if (e->isAKindOf(ssgTypeLeaf())) {
 
244
    list<string>::const_iterator it;
 
245
    for (it = cat_objects.begin(); it != cat_objects.end(); ++it) {
 
246
      if (mark || (e->getName() && (*it) == e->getName())) {
 
247
        e->setTraversalMaskBits(SSGTRAV_HOT);
 
248
        ssgBase* ud = e->getUserData();
 
249
        if (ud) {
 
250
          FGAICarrierHardware* ch = dynamic_cast<FGAICarrierHardware*>(ud);
 
251
          if (ch) {
 
252
            SG_LOG(SG_GENERAL, SG_WARN,
 
253
                   "AICarrier: Carrier hardware gets marked twice!\n"
 
254
                   "           You have propably a whole branch marked as"
 
255
                   " a catapult which also includes other carrier hardware."
 
256
                   );
 
257
          } else {
 
258
            SG_LOG(SG_GENERAL, SG_ALERT,
 
259
                   "AICarrier: Found user data attached to a leaf node which "
 
260
                   "should be marked as a catapult!\n    ****Skipping!****");
 
261
          }
 
262
        } else {
 
263
          e->setUserData( FGAICarrierHardware::newCatapult( this ) );
 
264
          ssgLeaf *l = (ssgLeaf*)e;
 
265
          if ( l->getNumLines() != 1 ) {
 
266
            SG_LOG(SG_GENERAL, SG_ALERT,
 
267
                   "AICarrier: Found a cat not modelled with exactly "
 
268
                   "one line!");
 
269
          } else {
 
270
            // Now some special code to make sure the cat points in the right
 
271
            // direction. The 0 index must be the backward end, the 1 index
 
272
            // the forward end.
 
273
            // Forward is positive x-direction in our 3D model, also the model
 
274
            // as such is flattened when it is loaded, so we do not need to
 
275
            // care for transforms ...
 
276
            short v[2];
 
277
            l->getLine(0, v, v+1 );
 
278
            sgVec3 ends[2];
 
279
            for (int k=0; k<2; ++k)
 
280
              sgCopyVec3( ends[k], l->getVertex( v[k] ) );
 
281
            
 
282
            // When the 1 end is behind the 0 end, swap the coordinates.
 
283
            if (ends[0][0] < ends[1][0]) {
 
284
              sgCopyVec3( l->getVertex( v[0] ), ends[1] );
 
285
              sgCopyVec3( l->getVertex( v[1] ), ends[0] );
 
286
            }
 
287
 
 
288
            found = true;
 
289
          }
 
290
        }
 
291
      }
 
292
    }
 
293
  }
 
294
  return found;
 
295
}
 
296
 
 
297
void FGAICarrier::UpdateFlols( double dt) {
 
298
/*    cout << "x_offset " << flols_x_offset 
 
299
          << " y_offset " << flols_y_offset 
 
300
          << " z_offset " << flols_z_offset << endl;
 
301
        
 
302
     cout << "roll " << roll 
 
303
          << " heading " << hdg
 
304
          << " pitch " << pitch << endl;
 
305
        
 
306
     cout << "carrier lon " << pos[0] 
 
307
          << " lat " <<  pos[1]
 
308
          << " alt " << pos[2] << endl;*/
 
309
        
 
310
// set the Flols intitial position to the carrier position
 
311
 
 
312
  flolspos = pos;
 
313
  
 
314
/*  cout << "flols lon " << flolspos[0] 
 
315
          << " lat " <<  flolspos[1]
 
316
          << " alt " << flolspos[2] << endl;*/
 
317
          
 
318
// set the offsets in metres
 
319
 
 
320
/*  cout << "flols_x_offset " << flols_x_offset << endl
 
321
       << "flols_y_offset " << flols_y_offset << endl
 
322
       << "flols_z_offset " << flols_z_offset << endl;*/
 
323
     
 
324
  in[0] = flols_x_offset;  
 
325
  in[1] = flols_y_offset;
 
326
  in[2] = flols_z_offset;    
 
327
 
 
328
// pre-process the trig functions
 
329
 
 
330
    cosRx = cos(roll * SG_DEGREES_TO_RADIANS);
 
331
    sinRx = sin(roll * SG_DEGREES_TO_RADIANS);
 
332
    cosRy = cos(pitch * SG_DEGREES_TO_RADIANS);
 
333
    sinRy = sin(pitch * SG_DEGREES_TO_RADIANS);
 
334
    cosRz = cos(hdg * SG_DEGREES_TO_RADIANS);
 
335
    sinRz = sin(hdg * SG_DEGREES_TO_RADIANS);
 
336
 
 
337
// set up the transform matrix
 
338
 
 
339
    trans[0][0] =  cosRy * cosRz;
 
340
    trans[0][1] =  -1 * cosRx * sinRz + sinRx * sinRy * cosRz ;
 
341
    trans[0][2] =  sinRx * sinRz + cosRx * sinRy * cosRz;
 
342
 
 
343
    trans[1][0] =  cosRy * sinRz;
 
344
    trans[1][1] =  cosRx * cosRz + sinRx * sinRy * sinRz;
 
345
    trans[1][2] =  -1 * sinRx * cosRx + cosRx * sinRy * sinRz;
 
346
 
 
347
    trans[2][0] =  -1 * sinRy;
 
348
    trans[2][1] =  sinRx * cosRy;
 
349
    trans[2][2] =  cosRx * cosRy;
 
350
 
 
351
// multiply the input and transform matrices
 
352
 
 
353
   out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2];
 
354
   out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2];
 
355
   out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2];
 
356
 
 
357
// convert meters to ft to degrees of latitude
 
358
   out[0] = (out[0] * 3.28083989501) /(366468.96 - 3717.12 * cos(flolspos[0] * SG_DEGREES_TO_RADIANS));
 
359
 
 
360
// convert meters to ft to degrees of longitude
 
361
   out[1] = (out[1] * 3.28083989501)/(365228.16 * cos(flolspos[1] * SG_DEGREES_TO_RADIANS));
 
362
 
 
363
//print out the result
 
364
/*   cout  << "lat adjust deg" << out[0] 
 
365
        << " lon adjust deg " << out[1] 
 
366
        << " alt adjust m " << out[2]  << endl;*/
 
367
 
 
368
// adjust Flols position    
 
369
   flolspos[0] += out[0];
 
370
   flolspos[1] += out[1];
 
371
   flolspos[2] += out[2];   
 
372
 
 
373
// convert flols position to cartesian co-ordinates 
 
374
 
 
375
  sgGeodToCart(flolspos[1] * SG_DEGREES_TO_RADIANS,
 
376
               flolspos[0] * SG_DEGREES_TO_RADIANS,
 
377
               flolspos[2] , flolsXYZ );
 
378
 
 
379
 
 
380
/*  cout << "flols X " << flolsXYZ[0] 
 
381
       << " Y " <<  flolsXYZ[1]
 
382
       << " Z " << flolsXYZ[2] << endl; 
 
383
 
 
384
// check the conversion
 
385
         
 
386
  sgCartToGeod(flolsXYZ, &lat, &lon, &alt);
 
387
 
 
388
  cout << "flols check lon " << lon   
 
389
        << " lat " << lat 
 
390
        << " alt " << alt << endl;      */
 
391
               
 
392
//get the current position of the pilot's eyepoint (cartesian cordinates)
 
393
 
 
394
  sgdCopyVec3( eyeXYZ, globals->get_current_view()->get_absolute_view_pos() );
 
395
  
 
396
 /* cout  << "Eye_X "  << eyeXYZ[0] 
 
397
        << " Eye_Y " << eyeXYZ[1] 
 
398
        << " Eye_Z " << eyeXYZ[2]  << endl; */
 
399
        
 
400
  sgCartToGeod(eyeXYZ, &lat, &lon, &alt);
 
401
  
 
402
  eyepos[0] = lon * SG_RADIANS_TO_DEGREES;
 
403
  eyepos[1] = lat * SG_RADIANS_TO_DEGREES;
 
404
  eyepos[2] = alt;
 
405
  
 
406
/*  cout << "eye lon " << eyepos[0]
 
407
        << " eye lat " << eyepos[1] 
 
408
        << " eye alt " << eyepos[2] << endl; */
 
409
 
 
410
//calculate the ditance from eye to flols
 
411
      
 
412
  dist = sgdDistanceVec3( flolsXYZ, eyeXYZ );
 
413
  
 
414
  //cout << "distance " << dist << endl; 
 
415
  
 
416
  if ( dist < 5000 ) {
 
417
       // calculate height above FLOLS 
 
418
       double y = eyepos[2] - flolspos[2];
 
419
       
 
420
       // calculate the angle from the flols to eye
 
421
       // above the horizontal
 
422
       double angle;
 
423
       if ( dist != 0 ) {
 
424
           angle = asin( y / dist );
 
425
         } else {
 
426
           angle = 0.0;
 
427
         }
 
428
        
 
429
       angle *= SG_RADIANS_TO_DEGREES;
 
430
        
 
431
      
 
432
  // cout << " height " << y << " angle " << angle ;
 
433
 
 
434
// set the value of source  
 
435
        
 
436
       if ( angle <= 4.35 && angle > 4.01 )
 
437
         { source = 1; }
 
438
         else if ( angle <= 4.01 && angle > 3.670 )
 
439
         { source = 2; }
 
440
         else if ( angle <= 3.670 && angle > 3.330 )
 
441
         { source = 3; }
 
442
         else if ( angle <= 3.330 && angle > 2.990 )
 
443
         { source = 4; }
 
444
         else if ( angle <= 2.990 && angle > 2.650 )
 
445
         { source = 5; }
 
446
         else if ( angle <= 2.650  )
 
447
         { source = 6; }
 
448
         else
 
449
         { source = 0; }
 
450
         
 
451
//         cout << " source " << source << endl;
 
452
                     
 
453
   }   
 
454
} // end updateflols
 
455
 
 
456
int FGAICarrierHardware::unique_id = 1;