1 /*****************************************************************************
2  * $LastChangedDate: 2010-06-24 10:22:48 -0400 (Thu, 24 Jun 2010) $
3  * @file
4  * @author  Jim E. Brooks  http://www.palomino3d.org
5  * @brief   Aircraft classes.
6  *//*
7  * LEGAL:   COPYRIGHT (C) 2007 JIM E. BROOKS
8  *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
9  *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
10  *****************************************************************************/
11 
12 // Enable this when editing an aircraft model's control surfaces.
13 // This causes the spec file to be reloaded continually after being edited.
14 #if DEBUG
15 //#define COMPILE_EDITING_MODEL 1
16 #endif
17 
18 #define PROGRAM_AIRCRAFT_CC 1
19 #include "base/module.hh"
20 using namespace base;
21 #include "math/module.hh"
22 #include "math/funcs_trig.hh"
23 #include "math/funcs_vector.hh"
24 using namespace math;
25 #include "gfx/module.hh"
26 using namespace gfx;
27 #include "graph/module.hh"
28 #include "graph/subgraph.hh"
29 #include "graph/shadow_scene_graph.hh"
30 using namespace graph;
31 #include "object/module.hh"
32 #include "object/aircraft.hh"
33 using namespace object;
34 #include "control/module.hh"
35 #include "control/defs_axis.hh"
36 using namespace control;
37 #include "physics/module.hh"
38 using namespace physics;
39 #include "program/module.hh"
40 #include "program/aircraft_models.hh"
41 
42 namespace program {
43 
44 INTERN const fp THROTTLE_PROPELLER              = 0.2f;  // when propeller begins to spin
45 INTERN const fp THROTTLE_FLAME_LOW              = 0.3f;  // most models lack this
46 INTERN const fp THROTTLE_FLAME_HIGH             = 0.7f;
47 INTERN const fp THROTTLE_FLAME                  = THROTTLE_FLAME_HIGH;
48 INTERN const fp F14_AILERONS_ACTIVE_SWING_WINGS = 0.75f;
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 ///////////////////////////////  functions  ////////////////////////////////////
52 ////////////////////////////////////////////////////////////////////////////////
53 
54 #if COMPILE_EDITING_MODEL
55 #define CODE_CLASS_GET_SPECS( CONF_FILENAME )                               \
56 {                                                                           \
57     BEGIN_ONCE {                                                            \
58     CDEBUG << "Note: COMPILE_EDITING_MODEL enabled (slows program)" << endl;\
59     } END_ONCE                                                              \
60                                                                             \
61     /* Reload every time. */                                                \
62     PERSISTENT AircraftSpecs sAircraftSpecs;                                \
63     sAircraftSpecs.ReadSpecsFromConfFile( CONF_FILENAME );                  \
64     return sAircraftSpecs;                                                  \
65 }
66 #else
67 #define CODE_CLASS_GET_SPECS( CONF_FILENAME )                               \
68 {                                                                           \
69     /* Load specs from a .conf file once. */                                \
70     PERSISTENT AircraftSpecs sAircraftSpecs;                                \
71     BEGIN_ONCE {                                                            \
72         sAircraftSpecs.ReadSpecsFromConfFile( CONF_FILENAME );              \
73     } END_ONCE                                                              \
74     return sAircraftSpecs;                                                  \
75 }
76 #endif
77 
78 /*****************************************************************************
79  * Make specified kind of aircraft.
80  * Some 3D models were defined with its center at the nose.
81  * physics_*.conf redefines an offset.
82  * @param   aircraftType
83  * @param   pos
84  * @param   loadCopy
85  *          Pass ModelCache::LOAD_SHARED or LOAD_COPY.
86  *          To save memory, pass false for dummy (non-dynamic) aircraft
87  *          such as those parked on the carrier.
88  *****************************************************************************/
89 shptr<Aircraft>
MakeAircraft(eAircraftType aircraftType,const WorldVertex & pos,const bool loadCopy)90 MakeAircraft( eAircraftType aircraftType, const WorldVertex& pos, const bool loadCopy )
91 {
92     shptr0<Aircraft> aircraft = NULL;
93     shptr0<Graph>    graph    = NULL;
94 
95 #define MAKE_AIRCRAFT( CLASS )                                                  \
96 {                                                                               \
97     graph = Aircraft::LoadModel( CLASS::ClassGetSpecs(), loadCopy ).PTR();      \
98     aircraft = new CLASS( graph.PTR(), pos );                                   \
99 }
100 
101     switch ( aircraftType )
102     {
103         case eAircraftType_Spitfire:
104         {
105             MAKE_AIRCRAFT( SpitfireAircraft );
106         }
107         break;
108 
109         case eAircraftType_Corsair:
110         {
111             MAKE_AIRCRAFT( CorsairAircraft );
112         }
113         break;
114 
115         case eAircraftType_P51:
116         {
117             MAKE_AIRCRAFT( P51Aircraft );
118         }
119         break;
120 
121         case eAircraftType_F82:
122         {
123             MAKE_AIRCRAFT( F82Aircraft );
124         }
125         break;
126 
127         case eAircraftType_F86:
128         {
129             MAKE_AIRCRAFT( F86Aircraft );
130         }
131         break;
132 
133         case eAircraftType_A4:
134         {
135             MAKE_AIRCRAFT( A4Aircraft );
136         }
137         break;
138 
139         case eAircraftType_F14:
140         {
141             MAKE_AIRCRAFT( F14Aircraft );
142         }
143         break;
144 
145         case eAircraftType_F15:
146         {
147             MAKE_AIRCRAFT( F15Aircraft );
148         }
149         break;
150 
151         case eAircraftType_F16:
152         {
153             MAKE_AIRCRAFT( F16Aircraft );
154         }
155         break;
156 
157         case eAircraftType_F18:
158         {
159             MAKE_AIRCRAFT( F18Aircraft );
160         }
161         break;
162 
163         case eAircraftType_SR71:
164         {
165             MAKE_AIRCRAFT( SR71Aircraft );
166         }
167         break;
168 
169         case eAircraftType_Mirage2000:
170         {
171             MAKE_AIRCRAFT( Mirage2000Aircraft );
172         }
173         break;
174 
175         case eAircraftType_SU37:
176         {
177             MAKE_AIRCRAFT( SU37Aircraft );
178         }
179         break;
180 
181         case eAircraftType_Sikorsky:
182         {
183             MAKE_AIRCRAFT( SikorskyAircraft );
184         }
185         break;
186 
187         case eAircraftType_SpaceShuttle:
188         {
189             MAKE_AIRCRAFT( SpaceShuttleAircraft );
190         }
191         break;
192 
193         default:
194         {
195             ASSERT(0);  // oops
196         }
197         break;
198     }
199 
200     // Return Aircraft.
201     return aircraft.PTR();
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 ////////////////////////////  SpitfireAircraft  ////////////////////////////////
206 ////////////////////////////////////////////////////////////////////////////////
207 
208 /*****************************************************************************
209  * ctor/dtor.
210  *****************************************************************************/
SpitfireAircraft(shptr<Graph> graph,const WorldVertex & pos)211 SpitfireAircraft::SpitfireAircraft( shptr<Graph> graph, const WorldVertex& pos )
212 :   Parent(graph,pos,SpitfireAircraft::ClassGetSpecs()),
213     mSubgraphPropeller1(new Subgraph(graph,"Propeller1")),
214     mSubgraphPropeller2(new Subgraph(graph,"Propeller2")),
215     mSubgraphPropeller3(new Subgraph(graph,"Propeller3")),
216     mSubgraphPropeller4(new Subgraph(graph,"Propeller4")),
217     mSubgraphPropellerDisc(new Subgraph(graph,"noshadow.PropellerDisk")),  // transparent
218     mSubgraphGear0(new Subgraph(graph,"Leg-Assembly-L")),
219     mSubgraphGear1(new Subgraph(graph,"Leg-Assembly-R")),
220     mSubgraphGear2(new Subgraph(graph,"Tail-Wheel-Assembly")),
221     //
222     mSubgraphAileronLeft(new Subgraph(graph,"Aileron-T")),
223     mSubgraphAileronRight(new Subgraph(graph,"Aileron-T.001")),
224     mSubgraphElevatorLeft(new Subgraph(graph,"Elevator-T.001")),
225     mSubgraphElevatorRight(new Subgraph(graph,"Elevator-T")),
226     mSubgraphRudder(new Subgraph(graph,"Rudder"))
227 {
228     ShadowSceneGraph::DisableShadows( mSubgraphPropellerDisc->GetRootNode() );
229 }
230 
~SpitfireAircraft()231 SpitfireAircraft::~SpitfireAircraft()
232 {
233     // NOP
234 }
235 
236 /*****************************************************************************
237  * @return Aircraft specifications struct.
238  *****************************************************************************/
239 const AircraftSpecs&
GetSpecs(void)240 SpitfireAircraft::GetSpecs( void )  // virtual method
241 {
242 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
243 
244     return SpitfireAircraft::ClassGetSpecs();
245 }
246 
247 const AircraftSpecs&
ClassGetSpecs(void)248 SpitfireAircraft::ClassGetSpecs( void )  // class method
249 {
250     CODE_CLASS_GET_SPECS( "physics_spitfire.conf" )
251 }
252 
253 /*****************************************************************************
254  * Tick that pulses animation.
255  *****************************************************************************/
256 void
Tick(const Milliseconds millisecElapsed)257 SpitfireAircraft::Tick( const Milliseconds millisecElapsed )
258 {
259 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
260 
261     Parent::Tick( millisecElapsed );
262 
263     RotatePropeller();
264 }
265 
266 /*****************************************************************************
267  * Rotate propeller.
268  *****************************************************************************/
269 // Rotate both propeller Groups.
270 void
RotatePropeller(void)271 SpitfireAircraft::RotatePropeller( void )
272 {
273 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
274 
275     // Degree of rotation correlates to throttle.
276     const Degree degree = 35.0f * GetThrottle();
277     const Radian radian = Deg2Rad( -degree );
278     mSubgraphPropeller1->Rotate( XX, radian );
279     mSubgraphPropeller2->Rotate( XX, radian );
280     mSubgraphPropeller3->Rotate( XX, radian );
281     mSubgraphPropeller4->Rotate( XX, radian );
282 }
283 
284 /*****************************************************************************
285  * Retract/extend landing gear.
286  *****************************************************************************/
287 void
SetLandingGear(const bool down)288 SpitfireAircraft::SetLandingGear( const bool down )
289 {
290 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
291 
292     if ( IfCanSetLandingGear( down ) )
293     {
294         Parent::SetLandingGear( down );
295 
296         mSubgraphGear0->Enable( down );
297         mSubgraphGear1->Enable( down );
298         mSubgraphGear2->Enable( down );
299     }
300 }
301 
302 /*****************************************************************************
303  * When throttle is increased, spin propeller.
304  *****************************************************************************/
305 void
SetThrottle(const fp throttle)306 SpitfireAircraft::SetThrottle( const fp throttle )
307 {
308 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
309 
310     Parent::SetThrottle( throttle );
311     mSubgraphPropellerDisc->Enable( throttle >= THROTTLE_PROPELLER );  // disable transparent disc
312 }
313 
314 /*****************************************************************************
315  * Rotate control surfaces (ailerons etc).
316  *****************************************************************************/
317 void
RotateControlSurfaces(const uint axis,const fp controlFraction)318 SpitfireAircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
319 {
320 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
321 ASSERT_AXIS3(axis);
322 
323     switch ( axis )
324     {
325         case AXIS_PITCH:
326         {
327             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
328             RotateElevator( *mSubgraphElevatorRight, controlFraction );
329         }
330         break;
331 
332         case AXIS_ROLL:
333         {
334             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
335             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
336         }
337         break;
338 
339         case AXIS_YAW:
340         {
341             RotateRudder( *mSubgraphRudder, controlFraction );
342         }
343         break;
344     }
345 }
346 
347 ////////////////////////////////////////////////////////////////////////////////
348 /////////////////////////////  CorsairAircraft  ////////////////////////////////
349 ////////////////////////////////////////////////////////////////////////////////
350 
351 /*****************************************************************************
352  * ctor/dtor.
353  *****************************************************************************/
CorsairAircraft(shptr<Graph> graph,const WorldVertex & pos)354 CorsairAircraft::CorsairAircraft( shptr<Graph> graph, const WorldVertex& pos )
355 :   Parent(graph,pos,CorsairAircraft::ClassGetSpecs()),
356     mSubgraphPropeller0(new Subgraph(graph,"prop_0")),
357     mSubgraphPropeller1(new Subgraph(graph,"prop_1")),
358     mSubgraphGear0(new Subgraph(graph,"gearp2.L")),
359     mSubgraphGear1(new Subgraph(graph,"gearp2.R")),
360     mSubgraphGear2(new Subgraph(graph,"gearp3.L")),
361     mSubgraphGear3(new Subgraph(graph,"gearp3.R")),
362     mSubgraphGear4(new Subgraph(graph,"gearcylinder.L")),
363     mSubgraphGear5(new Subgraph(graph,"gearcylinder.R")),
364     mSubgraphGear6(new Subgraph(graph,"gearleg.L")),
365     mSubgraphGear7(new Subgraph(graph,"gearleg.R")),
366     mSubgraphGear8(new Subgraph(graph,"gearleg2.L")),
367     mSubgraphGear9(new Subgraph(graph,"gearleg2.R")),
368     mSubgraphGear10(new Subgraph(graph,"gearp1.L")),
369     mSubgraphGear11(new Subgraph(graph,"gearp1.R")),
370     mSubgraphGear12(new Subgraph(graph,"gearsc1.L")),
371     mSubgraphGear13(new Subgraph(graph,"gearsc2.L")),
372     mSubgraphGear14(new Subgraph(graph,"tailgear1")),
373     mSubgraphGear15(new Subgraph(graph,"tailgear2")),
374     mSubgraphGear16(new Subgraph(graph,"stopwheel.L")),
375     mSubgraphGear17(new Subgraph(graph,"stopwheel.R")),
376     mSubgraphGear18(new Subgraph(graph,"wheel.L")),
377     mSubgraphGear19(new Subgraph(graph,"wheel.R")),
378     mSubgraphGear20(new Subgraph(graph,"tailwheel")),
379     // Control surfaces:
380     mSubgraphAileronLeft(new Subgraph(graph,"aileron.L")),
381     mSubgraphAileronRight(new Subgraph(graph,"aileron.R")),
382     mSubgraphElevatorLeft(new Subgraph(graph,"elevator.L")),
383     mSubgraphElevatorRight(new Subgraph(graph,"elevator.R")),
384     mSubgraphRudder(new Subgraph(graph,"rudder"))
385 {
386     // NOP
387 }
388 
~CorsairAircraft()389 CorsairAircraft::~CorsairAircraft()
390 {
391     // NOP
392 }
393 
394 /*****************************************************************************
395  * @return Aircraft specifications struct.
396  *****************************************************************************/
397 const AircraftSpecs&
GetSpecs(void)398 CorsairAircraft::GetSpecs( void )  // virtual method
399 {
400 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
401     return CorsairAircraft::ClassGetSpecs();
402 }
403 
404 const AircraftSpecs&
ClassGetSpecs(void)405 CorsairAircraft::ClassGetSpecs( void )  // class method
406 {
407     CODE_CLASS_GET_SPECS( "physics_corsair.conf" )
408 }
409 
410 /*****************************************************************************
411  * Tick that pulses animation.
412  *****************************************************************************/
413 void
Tick(const Milliseconds millisecElapsed)414 CorsairAircraft::Tick( const Milliseconds millisecElapsed )
415 {
416 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
417 
418     Parent::Tick( millisecElapsed );
419 
420     RotatePropeller();
421 }
422 
423 /*****************************************************************************
424  * Rotate propeller.
425  *****************************************************************************/
426 void
RotatePropeller(void)427 CorsairAircraft::RotatePropeller( void )
428 {
429 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
430 
431     // Degree of rotation correlates to throttle.
432     const Degree degree = 35.0f * GetThrottle();
433     const Radian radian = Deg2Rad( -degree );
434     mSubgraphPropeller0->Rotate( XX, radian );
435     mSubgraphPropeller1->Rotate( XX, radian );
436 }
437 
438 /*****************************************************************************
439  * Retract/extend landing gear.
440  *****************************************************************************/
441 void
SetLandingGear(const bool down)442 CorsairAircraft::SetLandingGear( const bool down )
443 {
444 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
445 
446     if ( IfCanSetLandingGear( down ) )
447     {
448         Parent::SetLandingGear( down );
449 
450         mSubgraphGear0->Enable( down ); mSubgraphGear1->Enable( down );
451         mSubgraphGear2->Enable( down ); mSubgraphGear3->Enable( down );
452         mSubgraphGear4->Enable( down ); mSubgraphGear5->Enable( down );
453         mSubgraphGear6->Enable( down ); mSubgraphGear7->Enable( down );
454         mSubgraphGear8->Enable( down ); mSubgraphGear9->Enable( down );
455         mSubgraphGear10->Enable( down ); mSubgraphGear11->Enable( down );
456         mSubgraphGear12->Enable( down ); mSubgraphGear13->Enable( down );
457         mSubgraphGear14->Enable( down ); mSubgraphGear15->Enable( down );
458         mSubgraphGear16->Enable( down ); mSubgraphGear17->Enable( down );
459         mSubgraphGear18->Enable( down ); mSubgraphGear19->Enable( down );
460         mSubgraphGear20->Enable( down );
461     }
462 }
463 
464 /*****************************************************************************
465  * Rotate control surfaces (ailerons etc).
466  *****************************************************************************/
467 void
RotateControlSurfaces(const uint axis,const fp controlFraction)468 CorsairAircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
469 {
470 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
471 ASSERT_AXIS3(axis);
472 
473     switch ( axis )
474     {
475         case AXIS_PITCH:
476         {
477             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
478             RotateElevator( *mSubgraphElevatorRight, controlFraction );
479         }
480         break;
481 
482         case AXIS_ROLL:
483         {
484             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
485             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
486         }
487         break;
488 
489         case AXIS_YAW:
490         {
491             RotateRudder( *mSubgraphRudder, controlFraction );
492         }
493         break;
494     }
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 ///////////////////////////////  P51Aircraft  //////////////////////////////////
499 ////////////////////////////////////////////////////////////////////////////////
500 
501 /*****************************************************************************
502  * ctor/dtor.
503  *****************************************************************************/
P51Aircraft(shptr<Graph> graph,const WorldVertex & pos)504 P51Aircraft::P51Aircraft( shptr<Graph> graph, const WorldVertex& pos )
505 :   Parent(graph,pos,P51Aircraft::ClassGetSpecs()),
506     mSubgraphPropeller1(new Subgraph(graph,"Propeller1")),
507     mSubgraphPropeller2(new Subgraph(graph,"Propeller2")),
508     //
509     mSubgraphLeftGearWheel(new Subgraph(graph,"LeftGearWheel")),
510     mSubgraphLeftGearStrut(new Subgraph(graph,"LeftGearStrut")),
511     mSubgraphLeftInnerGearCover(new Subgraph(graph,"LeftInnerGearCover")),
512     mSubgraphLeftOuterGearCover(new Subgraph(graph,"LeftOuterGearCover")),
513     mSubgraphLeftTailGearDoor(new Subgraph(graph,"LeftTailGearDoor")),
514     //
515     mSubgraphRightGearWheel(new Subgraph(graph,"RightGearWheel")),
516     mSubgraphRightGearStrut(new Subgraph(graph,"RightGearStrut")),
517     mSubgraphRightInnerGearCover(new Subgraph(graph,"RightInnerGearCover")),
518     mSubgraphRightOuterGearCover(new Subgraph(graph,"RightOuterGearCover")),
519     mSubgraphRightTailGearDoor(new Subgraph(graph,"RightTailGearDoor")),
520     //
521     mSubgraphTailGearWheel(new Subgraph(graph,"TailGearWheel")),
522     mSubgraphTailGearStrut(new Subgraph(graph,"TailGearStrut")),
523     //
524     mSubgraphAileronLeft(new Subgraph(graph,"LeftAileron")),
525     mSubgraphAileronRight(new Subgraph(graph,"RightAileron")),
526     mSubgraphElevatorLeft(new Subgraph(graph,"LeftElevator")),
527     mSubgraphElevatorRight(new Subgraph(graph,"RightElevator")),
528     mSubgraphRudder(new Subgraph(graph,"Rudder")),
529     //
530     mSubgraphJunk0(new Subgraph(graph,"TailNavLightOff")),
531     mSubgraphJunk1(new Subgraph(graph,"TailNavLightOn"))
532 {
533     // Disable junk parts.
534     mSubgraphJunk0->Enable( false );
535     mSubgraphJunk1->Enable( false );
536 }
537 
~P51Aircraft()538 P51Aircraft::~P51Aircraft()
539 {
540     // NOP
541 }
542 
543 /*****************************************************************************
544  * @return Aircraft specifications struct.
545  *****************************************************************************/
546 const AircraftSpecs&
GetSpecs(void)547 P51Aircraft::GetSpecs( void )  // virtual method
548 {
549 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
550     return P51Aircraft::ClassGetSpecs();
551 }
552 
553 const AircraftSpecs&
ClassGetSpecs(void)554 P51Aircraft::ClassGetSpecs( void )  // class method
555 {
556     CODE_CLASS_GET_SPECS( "physics_p51.conf" )
557 }
558 
559 /*****************************************************************************
560  * Tick that pulses animation.
561  *****************************************************************************/
562 void
Tick(const Milliseconds millisecElapsed)563 P51Aircraft::Tick( const Milliseconds millisecElapsed )
564 {
565 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
566 
567     Parent::Tick( millisecElapsed );
568 
569     RotatePropeller();
570 }
571 
572 /*****************************************************************************
573  * Rotate propeller.
574  *****************************************************************************/
575 void
RotatePropeller(void)576 P51Aircraft::RotatePropeller( void )
577 {
578 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
579 
580     // Rotate both propeller Groups.
581     // Degree of rotation correlates to throttle.
582     const Degree degree = 35.0f * GetThrottle();
583     const Radian radian = Deg2Rad( -degree );
584     mSubgraphPropeller1->Rotate( XX, radian );  // this p51d-jw model splits propeller
585     mSubgraphPropeller2->Rotate( XX, radian );  // into two subgraphs
586 }
587 
588 /*****************************************************************************
589  * Retract/extend landing gear.
590  *****************************************************************************/
591 void
SetLandingGear(const bool down)592 P51Aircraft::SetLandingGear( const bool down )
593 {
594 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
595 
596     // The p51d-nw model apparently defines the origin of the landing gear
597     // at the center of the fuselage instead of the strut pivot.
598     // For now, just disable the nodes instead of doing rotation.
599 
600     if ( IfCanSetLandingGear( down ) )
601     {
602         Parent::SetLandingGear( down );
603 
604         mSubgraphLeftGearWheel->Enable( down );
605         mSubgraphLeftGearStrut->Enable( down );
606         mSubgraphLeftInnerGearCover->Enable( down );
607         mSubgraphLeftOuterGearCover->Enable( down );
608         mSubgraphLeftTailGearDoor->Enable( down );
609 
610         mSubgraphRightGearWheel->Enable( down );
611         mSubgraphRightGearStrut->Enable( down );
612         mSubgraphRightInnerGearCover->Enable( down );
613         mSubgraphRightOuterGearCover->Enable( down );
614         mSubgraphRightTailGearDoor->Enable( down );
615 
616         mSubgraphTailGearWheel->Enable( down );
617         mSubgraphTailGearStrut->Enable( down );
618     }
619 }
620 
621 /*****************************************************************************
622  * Rotate control surfaces (ailerons etc).
623  *****************************************************************************/
624 void
RotateControlSurfaces(const uint axis,const fp controlFraction)625 P51Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
626 {
627 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
628 ASSERT_AXIS3(axis);
629 
630     switch ( axis )
631     {
632         case AXIS_PITCH:
633         {
634             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
635             RotateElevator( *mSubgraphElevatorRight, controlFraction );
636         }
637         break;
638 
639         case AXIS_ROLL:
640         {
641             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
642             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
643         }
644         break;
645 
646         case AXIS_YAW:
647         {
648             RotateRudder( *mSubgraphRudder, controlFraction );
649         }
650         break;
651     }
652 }
653 
654 ////////////////////////////////////////////////////////////////////////////////
655 ///////////////////////////////  F82Aircraft  //////////////////////////////////
656 ////////////////////////////////////////////////////////////////////////////////
657 
658 /*****************************************************************************
659  * ctor/dtor.
660  *****************************************************************************/
F82Aircraft(shptr<Graph> graph,const WorldVertex & pos)661 F82Aircraft::F82Aircraft( shptr<Graph> graph, const WorldVertex& pos )
662 :   Parent(graph,pos,F82Aircraft::ClassGetSpecs()),
663     mSubgraphPropeller1(new Subgraph(graph,"Propeller1")),
664     mSubgraphPropeller2(new Subgraph(graph,"Propeller2")),
665     mSubgraphPropeller3(new Subgraph(graph,"Propeller1.002")),
666     mSubgraphPropeller4(new Subgraph(graph,"Propeller2.001")),
667     //
668     mSubgraphLeftGearWheel(new Subgraph(graph,"LeftGearWheel")),
669     mSubgraphLeftGearStrut(new Subgraph(graph,"LeftGearStrut")),
670     mSubgraphLeftInnerGearCover(new Subgraph(graph,"LeftInnerGearCover")),
671     mSubgraphLeftInnerGearCover2(new Subgraph(graph,"LeftInnerGearCove")),  // sic/truncation
672     mSubgraphLeftOuterGearCover(new Subgraph(graph,"LeftOuterGearCover")),
673     mSubgraphLeftTailGearDoor(new Subgraph(graph,"LeftTailGearDoor")),
674     //
675     mSubgraphRightGearWheel(new Subgraph(graph,"RightGearWheel")),
676     mSubgraphRightGearStrut(new Subgraph(graph,"RightGearStrut")),
677     mSubgraphRightInnerGearCover(new Subgraph(graph,"RightInnerGearCover")),
678     mSubgraphRightInnerGearCover2(new Subgraph(graph,"RightInnerGearCov")),  // sic/truncation
679     mSubgraphRightOuterGearCover(new Subgraph(graph,"RightOuterGearCover")),
680     mSubgraphRightTailGearDoor(new Subgraph(graph,"RightTailGearDoor")),
681     //
682     mSubgraphTailGearWheel(new Subgraph(graph,"TailGearWheel")),
683     mSubgraphTailGearStrut(new Subgraph(graph,"TailGearStrut")),
684     mSubgraphTailGearWheel2(new Subgraph(graph,"TailGearWheel.001")),
685     mSubgraphTailGearStrut2(new Subgraph(graph,"TailGearStrut.001")),
686     //
687     mSubgraphAileronLeft(new Subgraph(graph,"LeftAileron")),
688     mSubgraphAileronRight(new Subgraph(graph,"RightAileron")),
689     mSubgraphElevator(new Subgraph(graph,"LeftElevator.001")),  // misnomer
690     mSubgraphRudderLeft(new Subgraph(graph,"Rudder")),
691     mSubgraphRudderRight(new Subgraph(graph,"Rudder.001")),
692     //
693     mSubgraphJunk0(new Subgraph(graph,"TailNavLightOff")),
694     mSubgraphJunk1(new Subgraph(graph,"TailNavLightOn"))
695 {
696     // Disable junk parts.
697     mSubgraphJunk0->Enable( false );
698     mSubgraphJunk1->Enable( false );
699 }
700 
~F82Aircraft()701 F82Aircraft::~F82Aircraft()
702 {
703     // NOP
704 }
705 
706 /*****************************************************************************
707  * @return Aircraft specifications struct.
708  *****************************************************************************/
709 const AircraftSpecs&
GetSpecs(void)710 F82Aircraft::GetSpecs( void )  // virtual method
711 {
712 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
713     return F82Aircraft::ClassGetSpecs();
714 }
715 
716 const AircraftSpecs&
ClassGetSpecs(void)717 F82Aircraft::ClassGetSpecs( void )  // class method
718 {
719     CODE_CLASS_GET_SPECS( "physics_f82.conf" )
720 }
721 
722 /*****************************************************************************
723  * Tick that pulses animation.
724  *****************************************************************************/
725 void
Tick(const Milliseconds millisecElapsed)726 F82Aircraft::Tick( const Milliseconds millisecElapsed )
727 {
728 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
729 
730     Parent::Tick( millisecElapsed );
731 
732     RotatePropeller();
733 }
734 
735 /*****************************************************************************
736  * Rotate propeller.
737  *****************************************************************************/
738 void
TranslatePropeller(const fp dir)739 F82Aircraft::TranslatePropeller( const fp dir )
740 {
741     // In the F-82 model, the origin of the two propellers aren't centered correctly.
742     // This C++ code temporarily shifts the matrix origin.
743     //
744     // Using constants for translation is ok as they are scaled
745     // by the matrix scale set in the Object's Graph.
746 
747     const uint outwardAxis  = ZZ;
748     const fp   outwardTrans = dir * 1.875f;  // constant ok
749     mSubgraphPropeller1->Translate( outwardAxis,  outwardTrans );
750     mSubgraphPropeller2->Translate( outwardAxis,  outwardTrans );
751     mSubgraphPropeller3->Translate( outwardAxis, -outwardTrans );
752     mSubgraphPropeller4->Translate( outwardAxis, -outwardTrans );
753 
754     const uint upwardAxis  = YY;
755     const fp   upwardTrans = dir * 0.1f;  // constant ok
756     mSubgraphPropeller1->Translate( upwardAxis, upwardTrans );
757     mSubgraphPropeller2->Translate( upwardAxis, upwardTrans );
758     mSubgraphPropeller3->Translate( upwardAxis, upwardTrans );
759     mSubgraphPropeller4->Translate( upwardAxis, upwardTrans );
760 }
761 
762 void
RotatePropeller(void)763 F82Aircraft::RotatePropeller( void )
764 {
765 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
766 
767     // Rotate both propeller Groups.
768     // Degree of rotation correlates to throttle.
769     const Degree degree = 35.0f * GetThrottle();
770     const Radian radian = Deg2Rad( -degree );
771 
772     TranslatePropeller( 1.0f );
773 
774     mSubgraphPropeller1->Rotate( XX, radian );  // the p51d-jw model splits propeller
775     mSubgraphPropeller2->Rotate( XX, radian );  // into 2 subgraphs so the F-82 model has 4
776     mSubgraphPropeller3->Rotate( XX, radian );
777     mSubgraphPropeller4->Rotate( XX, radian );
778 
779     TranslatePropeller( -1.0f );  // undo translation
780 }
781 
782 /*****************************************************************************
783  * Retract/extend landing gear.
784  *****************************************************************************/
785 void
SetLandingGear(const bool down)786 F82Aircraft::SetLandingGear( const bool down )
787 {
788 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
789 
790     // The model apparently defines the origin of the landing gear
791     // at the center of the fuselage instead of the strut pivot.
792     // For now, just disable the nodes instead of doing rotation.
793 
794     if ( IfCanSetLandingGear( down ) )
795     {
796         Parent::SetLandingGear( down );
797 
798         mSubgraphLeftGearWheel->Enable( down );
799         mSubgraphLeftGearStrut->Enable( down );
800         mSubgraphLeftInnerGearCover->Enable( down );
801         mSubgraphLeftInnerGearCover2->Enable( down );
802         mSubgraphLeftOuterGearCover->Enable( down );
803         mSubgraphLeftTailGearDoor->Enable( down );
804 
805         mSubgraphRightGearWheel->Enable( down );
806         mSubgraphRightGearStrut->Enable( down );
807         mSubgraphRightInnerGearCover->Enable( down );
808         mSubgraphRightInnerGearCover2->Enable( down );
809         mSubgraphRightOuterGearCover->Enable( down );
810         mSubgraphRightTailGearDoor->Enable( down );
811 
812         mSubgraphTailGearWheel->Enable( down );
813         mSubgraphTailGearStrut->Enable( down );
814         mSubgraphTailGearWheel2->Enable( down );
815         mSubgraphTailGearStrut2->Enable( down );
816     }
817 }
818 
819 /*****************************************************************************
820  * Rotate control surfaces (ailerons etc).
821  *****************************************************************************/
822 void
RotateControlSurfaces(const uint axis,const fp controlFraction)823 F82Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
824 {
825 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
826 ASSERT_AXIS3(axis);
827 
828     switch ( axis )
829     {
830         case AXIS_PITCH:
831         {
832             RotateElevator( *mSubgraphElevator, controlFraction );
833         }
834         break;
835 
836         case AXIS_ROLL:
837         {
838             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
839             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
840         }
841         break;
842 
843         case AXIS_YAW:
844         {
845             RotateRudder( *mSubgraphRudderLeft,  controlFraction, LEFT_RUDDER  );
846             RotateRudder( *mSubgraphRudderRight, controlFraction, RIGHT_RUDDER );
847         }
848         break;
849     }
850 }
851 
852 ////////////////////////////////////////////////////////////////////////////////
853 ///////////////////////////////  F86Aircraft  //////////////////////////////////
854 ////////////////////////////////////////////////////////////////////////////////
855 
856 /*****************************************************************************
857  * ctor/dtor.
858  *****************************************************************************/
F86Aircraft(shptr<Graph> graph,const WorldVertex & pos)859 F86Aircraft::F86Aircraft( shptr<Graph> graph, const WorldVertex& pos )
860 :   Parent(graph,pos,F86Aircraft::ClassGetSpecs()),
861     mSubgraphGear0(new Subgraph(graph,"nosegear1")),
862     mSubgraphGear1(new Subgraph(graph,"nosewheel")),
863     mSubgraphGear2(new Subgraph(graph,"gear.L")),
864     mSubgraphGear3(new Subgraph(graph,"gear.R")),
865     mSubgraphGear4(new Subgraph(graph,"wheel.L")),
866     mSubgraphGear5(new Subgraph(graph,"wheel.R")),
867     // Control surfaces:
868     mSubgraphAileronLeft(new Subgraph(graph,"aileron.L")),
869     mSubgraphAileronRight(new Subgraph(graph,"aileron.R")),
870     mSubgraphElevatorLeft(new Subgraph(graph,"elevator.L")),
871     mSubgraphElevatorRight(new Subgraph(graph,"elevator.R")),
872     mSubgraphRudder(new Subgraph(graph,"rudder_1"))
873     // (no flame)
874 {
875     SetThrottle( 0.0f );
876 }
877 
~F86Aircraft()878 F86Aircraft::~F86Aircraft()
879 {
880     // NOP
881 }
882 
883 /*****************************************************************************
884  * @return Aircraft specifications struct.
885  *****************************************************************************/
886 const AircraftSpecs&
GetSpecs(void)887 F86Aircraft::GetSpecs( void )  // virtual method
888 {
889 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
890     return F86Aircraft::ClassGetSpecs();
891 }
892 
893 const AircraftSpecs&
ClassGetSpecs(void)894 F86Aircraft::ClassGetSpecs( void )  // class method
895 {
896     CODE_CLASS_GET_SPECS( "physics_f86.conf" )
897 }
898 
899 /*****************************************************************************
900  * Retract/extend landing gear.
901  *****************************************************************************/
902 void
SetLandingGear(const bool down)903 F86Aircraft::SetLandingGear( const bool down )
904 {
905 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
906 
907     if ( IfCanSetLandingGear( down ) )
908     {
909         Parent::SetLandingGear( down );
910 
911         mSubgraphGear0->Enable( down ); mSubgraphGear1->Enable( down );
912         mSubgraphGear2->Enable( down ); mSubgraphGear3->Enable( down );
913         mSubgraphGear4->Enable( down ); mSubgraphGear5->Enable( down );
914     }
915 }
916 
917 /*****************************************************************************
918  * Rotate control surfaces (ailerons etc).
919  *****************************************************************************/
920 void
RotateControlSurfaces(const uint axis,const fp controlFraction)921 F86Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
922 {
923 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
924 ASSERT_AXIS3(axis);
925 
926     switch ( axis )
927     {
928         case AXIS_PITCH:
929         {
930             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
931             RotateElevator( *mSubgraphElevatorRight, controlFraction );
932         }
933         break;
934 
935         case AXIS_ROLL:
936         {
937             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
938             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
939         }
940         break;
941 
942         case AXIS_YAW:
943         {
944             RotateRudder( *mSubgraphRudder, controlFraction );
945         }
946         break;
947     }
948 }
949 
950 ////////////////////////////////////////////////////////////////////////////////
951 ////////////////////////////////  A4Aircraft  //////////////////////////////////
952 ////////////////////////////////////////////////////////////////////////////////
953 
954 /*****************************************************************************
955  * ctor/dtor.
956  *****************************************************************************/
A4Aircraft(shptr<Graph> graph,const WorldVertex & pos)957 A4Aircraft::A4Aircraft( shptr<Graph> graph, const WorldVertex& pos )
958 :   Parent(graph,pos,A4Aircraft::ClassGetSpecs()),
959     mSubgraphGear0(new Subgraph(graph,"LeftWheel")),
960     mSubgraphGear1(new Subgraph(graph,"LeftLowerLeg")),
961     mSubgraphGear2(new Subgraph(graph,"LeftUpperLeg")),
962     mSubgraphGear3(new Subgraph(graph,"LeftGearDoor")),
963     mSubgraphGear4(new Subgraph(graph,"LeftGearStrut")),
964     mSubgraphGear5(new Subgraph(graph,"LeftLowerLegAssmbly")),
965     mSubgraphGear6(new Subgraph(graph,"RightWheel")),
966     mSubgraphGear7(new Subgraph(graph,"RightLowerLeg")),
967     mSubgraphGear8(new Subgraph(graph,"RightUpperLeg")),
968     mSubgraphGear9(new Subgraph(graph,"RightGearDoor")),
969     mSubgraphGear10(new Subgraph(graph,"RightGearStrut")),
970     mSubgraphGear11(new Subgraph(graph,"RightLowerLegAssmbly")),
971     mSubgraphGear12(new Subgraph(graph,"LandingLight")),    // unique to left wheel
972     mSubgraphGear13(new Subgraph(graph,"NoseWheel")),       // front wheel
973     mSubgraphGear14(new Subgraph(graph,"Upper-Leg-Nose")),  // front wheel
974     mSubgraphGear15(new Subgraph(graph,"Lower-Leg")),       // front wheel
975     mSubgraphGear16(new Subgraph(graph,"NoseGearStrut")),   // front wheel
976     mSubgraphGear17(new Subgraph(graph,"NoseGearDoor")),    // front wheel
977     // Control surfaces:
978     // This model lacks real ailerons.
979     mSubgraphAileronLeft(new Subgraph(graph,"LeftSpoiler")),
980     mSubgraphAileronRight(new Subgraph(graph,"RightSpoiler")),
981     mSubgraphAileronLeft2(new Subgraph(graph,"LeftFlap-New")),
982     mSubgraphAileronRight2(new Subgraph(graph,"RightFlap-New")),
983     mSubgraphElevatorLeft(new Subgraph(graph,"LeftElevator")),
984     mSubgraphElevatorRight(new Subgraph(graph,"RightElevator")),
985     mSubgraphRudder(new Subgraph(graph,"Rudder"))
986 // (no flame)
987 {
988     SetThrottle( 0.0f );
989 }
990 
~A4Aircraft()991 A4Aircraft::~A4Aircraft()
992 {
993     // NOP
994 }
995 
996 /*****************************************************************************
997  * @return Aircraft specifications struct.
998  *****************************************************************************/
999 const AircraftSpecs&
GetSpecs(void)1000 A4Aircraft::GetSpecs( void )  // virtual method
1001 {
1002 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1003     return A4Aircraft::ClassGetSpecs();
1004 }
1005 
1006 const AircraftSpecs&
ClassGetSpecs(void)1007 A4Aircraft::ClassGetSpecs( void )  // class method
1008 {
1009     CODE_CLASS_GET_SPECS( "physics_a4.conf" )
1010 }
1011 
1012 /*****************************************************************************
1013  * Retract/extend landing gear.
1014  *****************************************************************************/
1015 void
SetLandingGear(const bool down)1016 A4Aircraft::SetLandingGear( const bool down )
1017 {
1018 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1019 
1020     if ( IfCanSetLandingGear( down ) )
1021     {
1022         Parent::SetLandingGear( down );
1023 
1024         mSubgraphGear0->Enable( down );  mSubgraphGear1->Enable( down );
1025         mSubgraphGear2->Enable( down );  mSubgraphGear3->Enable( down );
1026         mSubgraphGear4->Enable( down );  mSubgraphGear5->Enable( down );
1027         mSubgraphGear6->Enable( down );  mSubgraphGear7->Enable( down );
1028         mSubgraphGear8->Enable( down );  mSubgraphGear9->Enable( down );
1029         mSubgraphGear10->Enable( down ); mSubgraphGear11->Enable( down );
1030         mSubgraphGear12->Enable( down ); mSubgraphGear13->Enable( down );
1031         mSubgraphGear14->Enable( down ); mSubgraphGear15->Enable( down );
1032         mSubgraphGear16->Enable( down ); mSubgraphGear17->Enable( down );
1033     }
1034 }
1035 
1036 /*****************************************************************************
1037  * Rotate control surfaces (ailerons etc).
1038  *****************************************************************************/
1039 void
RotateControlSurfaces(const uint axis,const fp controlFraction)1040 A4Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
1041 {
1042 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1043 ASSERT_AXIS3(axis);
1044 
1045     switch ( axis )
1046     {
1047         case AXIS_PITCH:
1048         {
1049             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
1050             RotateElevator( *mSubgraphElevatorRight, controlFraction );
1051         }
1052         break;
1053 
1054         case AXIS_ROLL:
1055         {
1056             RotateAileron( *mSubgraphAileronLeft,   controlFraction, LEFT_AILERON );
1057             RotateAileron( *mSubgraphAileronLeft2,  controlFraction, LEFT_AILERON );
1058             RotateAileron( *mSubgraphAileronRight,  controlFraction, RIGHT_AILERON );
1059             RotateAileron( *mSubgraphAileronRight2, controlFraction, RIGHT_AILERON );
1060         }
1061         break;
1062 
1063         case AXIS_YAW:
1064         {
1065             // Subgraph is the entire rudder.
1066           //RotateRudder( *mSubgraphRudder, controlFraction );
1067         }
1068         break;
1069     }
1070 }
1071 
1072 ////////////////////////////////////////////////////////////////////////////////
1073 ///////////////////////////////  F14Aircraft  //////////////////////////////////
1074 ////////////////////////////////////////////////////////////////////////////////
1075 
1076 /*****************************************************************************
1077  * ctor/dtor.
1078  *****************************************************************************/
F14Aircraft(shptr<Graph> graph,const WorldVertex & pos)1079 F14Aircraft::F14Aircraft( shptr<Graph> graph, const WorldVertex& pos )
1080 :   Parent(graph,pos,F14Aircraft::ClassGetSpecs()),
1081     // gear:
1082     mSubgraphGear0(new Subgraph(graph,"MainWheelL")),
1083     mSubgraphGear1(new Subgraph(graph,"MainWheelR")),
1084     mSubgraphGear2(new Subgraph(graph,"NsWheel")),
1085     mSubgraphGear3(new Subgraph(graph,"FwdNsGrDoor")),
1086     mSubgraphGear4(new Subgraph(graph,"MidNsGrDoor")),
1087     mSubgraphGear5(new Subgraph(graph,"CatBar")),
1088     mSubgraphGear6(new Subgraph(graph,"CatBarLink")),
1089     mSubgraphGear7(new Subgraph(graph,"NsGearStrut")),
1090     mSubgraphGear8(new Subgraph(graph,"Tube.006")),
1091     mSubgraphGear9(new Subgraph(graph,"Tube.007")),
1092     mSubgraphGear10(new Subgraph(graph,"Tube.013")),
1093     mSubgraphGear11(new Subgraph(graph,"Tube.014")),
1094     mSubgraphGear12(new Subgraph(graph,"NsGrRotatingSleeve")),
1095     mSubgraphGear13(new Subgraph(graph,"RotatingSleeve-L")),
1096     mSubgraphGear14(new Subgraph(graph,"RotatingSleeve-R")),
1097     mSubgraphGear15(new Subgraph(graph,"MnGrStrut-L")),
1098     mSubgraphGear16(new Subgraph(graph,"MnGrStrut.001")),
1099     mSubgraphGear17(new Subgraph(graph,"Brace1")),
1100     mSubgraphGear18(new Subgraph(graph,"Brace1.001")),
1101     mSubgraphGear19(new Subgraph(graph,"Brace1.002")),
1102     mSubgraphGear20(new Subgraph(graph,"Brace1.003")),
1103     mSubgraphGear21(new Subgraph(graph,"HiCompassL")),
1104     mSubgraphGear22(new Subgraph(graph,"HiCompassR")),
1105     mSubgraphGear23(new Subgraph(graph,"LShock")),
1106     mSubgraphGear24(new Subgraph(graph,"RShock")),
1107     mSubgraphGear25(new Subgraph(graph,"NsShock")),
1108     mSubgraphGear26(new Subgraph(graph,"LoCompassL")),
1109     mSubgraphGear27(new Subgraph(graph,"LoCompassR")),
1110     mSubgraphGear28(new Subgraph(graph,"LoNsCompass")),
1111     mSubgraphGear29(new Subgraph(graph,"UpNsCompass")),
1112     mSubgraphGear30(new Subgraph(graph,"Downlock")),
1113     mSubgraphGear31(new Subgraph(graph,"Downlock.001")),
1114     mSubgraphGear32(new Subgraph(graph,"LandingLight")),
1115     mSubgraphGear33(new Subgraph(graph,"WheelBrake")),
1116     mSubgraphGear34(new Subgraph(graph,"WheelBrake.001")),
1117     //
1118     mSubgraphWingLeft0(new Subgraph(graph,"Wing_0")),
1119     mSubgraphWingLeft1(new Subgraph(graph,"Wing_1")),
1120     mSubgraphWingLeft2(new Subgraph(graph,"Flap1_0")),
1121     mSubgraphWingLeft3(new Subgraph(graph,"Flap1_1")),
1122     mSubgraphWingLeft4(new Subgraph(graph,"Flap2_0")),
1123     mSubgraphWingLeft5(new Subgraph(graph,"Flap2_1")),
1124     mSubgraphWingLeft6(new Subgraph(graph,"Flap3_0")),
1125     mSubgraphWingLeft7(new Subgraph(graph,"Flap3_1")),
1126     mSubgraphWingLeft8(new Subgraph(graph,"Flap1Brow")),
1127     mSubgraphWingLeft9(new Subgraph(graph,"Flap2Brow")),
1128     mSubgraphWingLeft10(new Subgraph(graph,"Flap3Brow")),
1129     mSubgraphWingLeft11(new Subgraph(graph,"FlapSeal1_0")),
1130     mSubgraphWingLeft12(new Subgraph(graph,"FlapSeal1_1")),
1131     mSubgraphWingLeft13(new Subgraph(graph,"FlapSeal2_0")),
1132     mSubgraphWingLeft14(new Subgraph(graph,"FlapSeal2_1")),
1133     mSubgraphWingLeft15(new Subgraph(graph,"FlapSeal3_0")),
1134     mSubgraphWingLeft16(new Subgraph(graph,"FlapSeal3_1")),
1135     mSubgraphWingLeft17(new Subgraph(graph,"Spoiler1_0")),
1136     mSubgraphWingLeft18(new Subgraph(graph,"Spoiler1_1")),
1137     mSubgraphWingLeft19(new Subgraph(graph,"Spoiler2_0")),
1138     mSubgraphWingLeft20(new Subgraph(graph,"Spoiler2_1")),
1139     mSubgraphWingLeft21(new Subgraph(graph,"Spoiler3_0")),
1140     mSubgraphWingLeft22(new Subgraph(graph,"Spoiler3_1")),
1141     mSubgraphWingLeft23(new Subgraph(graph,"Spoiler4_0")),
1142     mSubgraphWingLeft24(new Subgraph(graph,"Spoiler4_1")),
1143     mSubgraphWingLeft25(new Subgraph(graph,"Slat1_0")),
1144     mSubgraphWingLeft26(new Subgraph(graph,"Slat1_1")),
1145     mSubgraphWingLeft27(new Subgraph(graph,"Slat2_0")),
1146     mSubgraphWingLeft28(new Subgraph(graph,"Slat2_1")),
1147     mSubgraphWingLeft29(new Subgraph(graph,"LWingSlimmer")),
1148     //
1149     mSubgraphWingRight0(new Subgraph(graph,"Wing.001_0")),
1150     mSubgraphWingRight1(new Subgraph(graph,"Wing.001_1")),
1151     mSubgraphWingRight2(new Subgraph(graph,"Flap1.001_0")),
1152     mSubgraphWingRight3(new Subgraph(graph,"Flap1.001_1")),
1153     mSubgraphWingRight4(new Subgraph(graph,"Flap2.001_0")),
1154     mSubgraphWingRight5(new Subgraph(graph,"Flap2.001_1")),
1155     mSubgraphWingRight6(new Subgraph(graph,"Flap3.001_0")),
1156     mSubgraphWingRight7(new Subgraph(graph,"Flap3.001_1")),
1157     mSubgraphWingRight8(new Subgraph(graph,"Flap1Brow.001")),
1158     mSubgraphWingRight9(new Subgraph(graph,"Flap2Brow.001")),
1159     mSubgraphWingRight10(new Subgraph(graph,"Flap3Brow.001")),
1160     mSubgraphWingRight11(new Subgraph(graph,"FlapSeal1.001_0")),
1161     mSubgraphWingRight12(new Subgraph(graph,"FlapSeal1.001_1")),
1162     mSubgraphWingRight13(new Subgraph(graph,"FlapSeal2.001_0")),
1163     mSubgraphWingRight14(new Subgraph(graph,"FlapSeal2.001_1")),
1164     mSubgraphWingRight15(new Subgraph(graph,"FlapSeal3.001_0")),
1165     mSubgraphWingRight16(new Subgraph(graph,"FlapSeal3.001_1")),
1166     mSubgraphWingRight17(new Subgraph(graph,"Spoiler1.001_0")),
1167     mSubgraphWingRight18(new Subgraph(graph,"Spoiler1.001_1")),
1168     mSubgraphWingRight19(new Subgraph(graph,"Spoiler2.001_0")),
1169     mSubgraphWingRight20(new Subgraph(graph,"Spoiler2.001_1")),
1170     mSubgraphWingRight21(new Subgraph(graph,"Spoiler3.001_0")),
1171     mSubgraphWingRight22(new Subgraph(graph,"Spoiler3.001_1")),
1172     mSubgraphWingRight23(new Subgraph(graph,"Spoiler4.001_0")),
1173     mSubgraphWingRight24(new Subgraph(graph,"Spoiler4.001_1")),
1174     mSubgraphWingRight25(new Subgraph(graph,"Slat1.001_0")),
1175     mSubgraphWingRight26(new Subgraph(graph,"Slat1.001_1")),
1176     mSubgraphWingRight27(new Subgraph(graph,"Slat2.001_0")),
1177     mSubgraphWingRight28(new Subgraph(graph,"Slat2.001_1")),
1178     mSubgraphWingRight29(new Subgraph(graph,"RWingSlimmer")),
1179     mSubgraphTaileronLeft(new Subgraph(graph,"Stabilator")),
1180     mSubgraphTaileronRight(new Subgraph(graph,"Stabilator.001")),
1181     mSubgraphRudderLeft(new Subgraph(graph,"RudderL")),
1182     mSubgraphRudderRight(new Subgraph(graph,"RudderR")),
1183     //
1184     mSubgraphLadder0(new Subgraph(graph,"Ladder")),
1185     mSubgraphLadder1(new Subgraph(graph,"Ladder.001")),
1186     mSubgraphLadder2(new Subgraph(graph,"Ladder.002")),
1187     mSubgraphRefuelProbe(new Subgraph(graph,"RefuelProbe")),
1188     mSubgraphFlameInner0(new Subgraph(graph,"InnerFlameL")),
1189     mSubgraphFlameInner1(new Subgraph(graph,"InnerFlameR")),
1190     mSubgraphFlameOuter0(new Subgraph(graph,"outerFlame")),
1191     mSubgraphFlameOuter1(new Subgraph(graph,"outerFlame.001")),
1192     mSubgraphShockWave(new Subgraph(graph,"ShockWave")),
1193     mSubgraphManeuverVortexLeft(new Subgraph(graph,"ManeuverVortexL")),
1194     mSubgraphManeuverVortexRight(new Subgraph(graph,"ManeuverVortexR")),
1195     //
1196     mGearSubgraphs(), mLeftWingSubgraphs(), mRightWingSubgraphs(),
1197     //
1198     mSwingWingsFraction(0.0f),
1199     mAileronFraction(0.0f)
1200 {
1201     SetThrottle( 0.0f );
1202 
1203     // Hide superfluous parts.
1204     mSubgraphLadder0->Enable( false );
1205     mSubgraphLadder1->Enable( false );
1206     mSubgraphLadder2->Enable( false );
1207     mSubgraphRefuelProbe->Enable( false );
1208     mSubgraphShockWave->Enable( false );
1209     mSubgraphManeuverVortexLeft->Enable( false );
1210     mSubgraphManeuverVortexRight->Enable( false );
1211 
1212     // Build list of gear subgraphs.
1213     mLeftWingSubgraphs.reserve(  50 );
1214     mRightWingSubgraphs.reserve( 50 );
1215     #define F14_PUSH_GEAR_SUBGRAPH( NUM )                           \
1216         mGearSubgraphs.push_back( mSubgraphGear##NUM );
1217     F14_PUSH_GEAR_SUBGRAPH( 0 );  F14_PUSH_GEAR_SUBGRAPH( 1 );
1218     F14_PUSH_GEAR_SUBGRAPH( 2 );  F14_PUSH_GEAR_SUBGRAPH( 3 );
1219     F14_PUSH_GEAR_SUBGRAPH( 4 );  F14_PUSH_GEAR_SUBGRAPH( 5 );
1220     F14_PUSH_GEAR_SUBGRAPH( 6 );  F14_PUSH_GEAR_SUBGRAPH( 7 );
1221     F14_PUSH_GEAR_SUBGRAPH( 8 );  F14_PUSH_GEAR_SUBGRAPH( 9 );
1222     F14_PUSH_GEAR_SUBGRAPH( 10 ); F14_PUSH_GEAR_SUBGRAPH( 11 );
1223     F14_PUSH_GEAR_SUBGRAPH( 12 ); F14_PUSH_GEAR_SUBGRAPH( 13 );
1224     F14_PUSH_GEAR_SUBGRAPH( 14 ); F14_PUSH_GEAR_SUBGRAPH( 15 );
1225     F14_PUSH_GEAR_SUBGRAPH( 16 ); F14_PUSH_GEAR_SUBGRAPH( 17 );
1226     F14_PUSH_GEAR_SUBGRAPH( 18 ); F14_PUSH_GEAR_SUBGRAPH( 19 );
1227     F14_PUSH_GEAR_SUBGRAPH( 20 ); F14_PUSH_GEAR_SUBGRAPH( 21 );
1228     F14_PUSH_GEAR_SUBGRAPH( 22 ); F14_PUSH_GEAR_SUBGRAPH( 23 );
1229     F14_PUSH_GEAR_SUBGRAPH( 24 ); F14_PUSH_GEAR_SUBGRAPH( 25 );
1230     F14_PUSH_GEAR_SUBGRAPH( 26 ); F14_PUSH_GEAR_SUBGRAPH( 27 );
1231     F14_PUSH_GEAR_SUBGRAPH( 28 ); F14_PUSH_GEAR_SUBGRAPH( 29 );
1232     F14_PUSH_GEAR_SUBGRAPH( 30 ); F14_PUSH_GEAR_SUBGRAPH( 31 );
1233     F14_PUSH_GEAR_SUBGRAPH( 32 ); F14_PUSH_GEAR_SUBGRAPH( 33 );
1234     F14_PUSH_GEAR_SUBGRAPH( 34 );
1235 
1236     // Build list of wing subgraphs.
1237     mLeftWingSubgraphs.reserve(  50 );
1238     mRightWingSubgraphs.reserve( 50 );
1239     #define F14_PUSH_WING_SUBGRAPH( NUM )                           \
1240         mLeftWingSubgraphs.push_back(  mSubgraphWingLeft##NUM );    \
1241         mRightWingSubgraphs.push_back( mSubgraphWingRight##NUM );
1242     F14_PUSH_WING_SUBGRAPH( 0 );  F14_PUSH_WING_SUBGRAPH( 1 );
1243     F14_PUSH_WING_SUBGRAPH( 2 );  F14_PUSH_WING_SUBGRAPH( 3 );
1244     F14_PUSH_WING_SUBGRAPH( 4 );  F14_PUSH_WING_SUBGRAPH( 5 );
1245     F14_PUSH_WING_SUBGRAPH( 6 );  F14_PUSH_WING_SUBGRAPH( 7 );
1246     F14_PUSH_WING_SUBGRAPH( 8 );  F14_PUSH_WING_SUBGRAPH( 9 );
1247     F14_PUSH_WING_SUBGRAPH( 10 ); F14_PUSH_WING_SUBGRAPH( 11 );
1248     F14_PUSH_WING_SUBGRAPH( 12 ); F14_PUSH_WING_SUBGRAPH( 13 );
1249     F14_PUSH_WING_SUBGRAPH( 14 ); F14_PUSH_WING_SUBGRAPH( 15 );
1250     F14_PUSH_WING_SUBGRAPH( 16 ); F14_PUSH_WING_SUBGRAPH( 17 );
1251     F14_PUSH_WING_SUBGRAPH( 18 ); F14_PUSH_WING_SUBGRAPH( 19 );
1252     F14_PUSH_WING_SUBGRAPH( 20 ); F14_PUSH_WING_SUBGRAPH( 21 );
1253     F14_PUSH_WING_SUBGRAPH( 22 ); F14_PUSH_WING_SUBGRAPH( 23 );
1254     F14_PUSH_WING_SUBGRAPH( 24 ); F14_PUSH_WING_SUBGRAPH( 25 );
1255     F14_PUSH_WING_SUBGRAPH( 26 ); F14_PUSH_WING_SUBGRAPH( 27 );
1256     F14_PUSH_WING_SUBGRAPH( 28 ); F14_PUSH_WING_SUBGRAPH( 29 );
1257 
1258     // Exhaust flame shouldn't cast shadows.
1259     ShadowSceneGraph::DisableShadows( mSubgraphFlameInner0->GetRootNode() );
1260     ShadowSceneGraph::DisableShadows( mSubgraphFlameInner1->GetRootNode() );
1261     ShadowSceneGraph::DisableShadows( mSubgraphFlameOuter0->GetRootNode() );
1262     ShadowSceneGraph::DisableShadows( mSubgraphFlameOuter1->GetRootNode() );
1263 }
1264 
~F14Aircraft()1265 F14Aircraft::~F14Aircraft()
1266 {
1267     // NOP
1268 }
1269 
1270 /*****************************************************************************
1271  * Reset.
1272  *****************************************************************************/
1273 void
Reset(void)1274 F14Aircraft::Reset( void )
1275 {
1276     Parent::Reset();
1277 
1278     // Swing wings forward.
1279     SwingWings( 0.0f );
1280 }
1281 
1282 /*****************************************************************************
1283  * @return Aircraft specifications struct.
1284  *****************************************************************************/
1285 const AircraftSpecs&
GetSpecs(void)1286 F14Aircraft::GetSpecs( void )  // virtual method
1287 {
1288 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1289     return F14Aircraft::ClassGetSpecs();
1290 }
1291 
1292 const AircraftSpecs&
ClassGetSpecs(void)1293 F14Aircraft::ClassGetSpecs( void )  // class method
1294 {
1295     CODE_CLASS_GET_SPECS( "physics_f14.conf" )
1296 }
1297 
1298 /*****************************************************************************
1299  * Retract/extend landing gear.
1300  *****************************************************************************/
1301 void
SetLandingGear(const bool down)1302 F14Aircraft::SetLandingGear( const bool down )
1303 {
1304 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1305 
1306     if ( IfCanSetLandingGear( down ) )
1307     {
1308         Parent::SetLandingGear( down );
1309 
1310         for ( uint i = 0; i < mGearSubgraphs.size(); ++i )
1311             mGearSubgraphs[i]->Enable( down );
1312     }
1313 }
1314 
1315 /*****************************************************************************
1316  * When throttle is changed, animate jet exhaust flame.
1317  *****************************************************************************/
1318 void
SetThrottle(const fp throttle)1319 F14Aircraft::SetThrottle( const fp throttle )
1320 {
1321 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1322 
1323     Parent::SetThrottle( throttle );
1324     const bool flameInner = (throttle >= THROTTLE_FLAME_LOW);
1325     const bool flameOuter = (throttle >= THROTTLE_FLAME_HIGH);
1326     mSubgraphFlameInner0->Enable( flameInner );
1327     mSubgraphFlameInner1->Enable( flameInner );
1328     mSubgraphFlameOuter0->Enable( flameOuter );
1329     mSubgraphFlameOuter1->Enable( flameOuter );
1330 }
1331 
1332 /*****************************************************************************
1333  * Swing wings { 0.0:forward...1.0:back }
1334  *****************************************************************************/
1335 void
SwingWings(const float fraction)1336 F14Aircraft::SwingWings( const float fraction )
1337 {
1338 ASSERT( mLeftWingSubgraphs.size() == mRightWingSubgraphs.size() );
1339 
1340     mSwingWingsFraction = Clamp1( fraction );
1341 
1342     // Undo rotation/translation of wing subgraphs from previous call.
1343     for ( uint i = 0; i < mLeftWingSubgraphs.size(); ++i )
1344     {
1345         mLeftWingSubgraphs[i]->Reset();
1346         mRightWingSubgraphs[i]->Reset();
1347     }
1348 
1349     // deg = 0  fully forward
1350     // deg = 45 fully back
1351     const Degree deg = mSwingWingsFraction * 45.0f;
1352     const Radian rad = Deg2Rad( deg );
1353 
1354     // This particular 3D model requires translating the position
1355     // of the subgraphs as a function of swing-wings.
1356     // offset_x =   0.00 swing forward
1357     // offset_z =   0.00 swing forward
1358     // offset_x =  -1.40 swing back
1359     // offset_z = +-1.75 swing back (+- for left/right wing)
1360     const fp offset_x = mSwingWingsFraction * -1.40f;
1361     const fp offset_z = mSwingWingsFraction *  1.75f;
1362     for ( uint i = 0; i < mLeftWingSubgraphs.size(); ++i )
1363     {
1364         mLeftWingSubgraphs[i]->Translate(  XX, offset_x );  // move along fuselage
1365         mRightWingSubgraphs[i]->Translate( XX, offset_x );
1366 
1367         mLeftWingSubgraphs[i]->Translate(  ZZ,  offset_z );  // move outwards (along wings)
1368         mRightWingSubgraphs[i]->Translate( ZZ, -offset_z );
1369 
1370         mLeftWingSubgraphs[i]->Rotate(  YY,  rad );
1371         mRightWingSubgraphs[i]->Rotate( YY, -rad );
1372     }
1373 }
1374 
1375 /*****************************************************************************
1376  * Rotate control surfaces (ailerons etc).
1377  *****************************************************************************/
1378 void
RotateControlSurfaces(const uint axis,const fp controlFraction)1379 F14Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
1380 {
1381 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1382 ASSERT_AXIS3(axis);
1383 
1384     const AircraftSpecs& specs = GetSpecs();
1385 
1386     switch ( axis )
1387     {
1388         case AXIS_PITCH:
1389         {
1390             RotateElevator( *mSubgraphTaileronLeft,  controlFraction );
1391             RotateElevator( *mSubgraphTaileronRight, controlFraction );
1392         }
1393         break;
1394 
1395         case AXIS_ROLL:
1396         {
1397             // F-14 wings are complex.
1398 
1399             // Tailerons:
1400             RotateAileron( *mSubgraphTaileronLeft,  controlFraction, LEFT_AILERON,  specs.mElevatorOffset );
1401             RotateAileron( *mSubgraphTaileronRight, controlFraction, RIGHT_AILERON, specs.mElevatorOffset );
1402 
1403             // Ailerons (outer flaps) if wings are straight-out.
1404             if ( mSwingWingsFraction <= F14_AILERONS_ACTIVE_SWING_WINGS )
1405             {
1406                 // Specially rotate the F-14 ailerons.
1407                 #define F14_ROTATE_AILERONS( SUBGRAPH, CONTROL_FRACTION, AILERON )              \
1408                 {{                                                                              \
1409                     (SUBGRAPH).Translate( specs.mAileronOffset );                               \
1410                     (SUBGRAPH).Rotate( MODEL_AXIS_PITCH,                                        \
1411                                        specs.mAileronROF * (CONTROL_FRACTION) * int(AILERON) ); \
1412                     (SUBGRAPH).Translate( -specs.mAileronOffset );                              \
1413                 }}
1414 
1415                 // Undo previous rotation.
1416                 F14_ROTATE_AILERONS( *mSubgraphWingLeft3,  -mAileronFraction, LEFT_AILERON );
1417                 F14_ROTATE_AILERONS( *mSubgraphWingRight3, -mAileronFraction, RIGHT_AILERON );
1418 
1419                 // Apply current rotation.
1420                 F14_ROTATE_AILERONS( *mSubgraphWingLeft3,  controlFraction, LEFT_AILERON );
1421                 F14_ROTATE_AILERONS( *mSubgraphWingRight3, controlFraction, RIGHT_AILERON );
1422 
1423                 // Remember for next time.
1424                 mAileronFraction = controlFraction;
1425             }
1426         }
1427         break;
1428 
1429         case AXIS_YAW:
1430         {
1431             RotateRudder( *mSubgraphRudderLeft,  controlFraction, LEFT_RUDDER  );
1432             RotateRudder( *mSubgraphRudderRight, controlFraction, RIGHT_RUDDER );
1433         }
1434         break;
1435     }
1436 }
1437 
1438 ////////////////////////////////////////////////////////////////////////////////
1439 ///////////////////////////////  F15Aircraft  //////////////////////////////////
1440 ////////////////////////////////////////////////////////////////////////////////
1441 
1442 /*****************************************************************************
1443  * ctor/dtor.
1444  *****************************************************************************/
F15Aircraft(shptr<Graph> graph,const WorldVertex & pos)1445 F15Aircraft::F15Aircraft( shptr<Graph> graph, const WorldVertex& pos )
1446 :   Parent(graph,pos,F15Aircraft::ClassGetSpecs()),
1447     // gear:
1448     mSubgraphGear0(new Subgraph(graph,"LeftWheel")),
1449     mSubgraphGear1(new Subgraph(graph,"LeftWheelTire")),
1450     mSubgraphGear2(new Subgraph(graph,"RightWheel")),
1451     mSubgraphGear3(new Subgraph(graph,"RightWheelTire")),
1452     mSubgraphGear4(new Subgraph(graph,"FrontWheel")),
1453     mSubgraphGear5(new Subgraph(graph,"FrontWheelTire")),
1454     // exhaust flame:
1455     mSubgraphFlame0(new Subgraph(graph,"InternalFlame")),
1456     mSubgraphFlame1(new Subgraph(graph,"ExternalFlame")),
1457     // control surfaces:
1458     mSubgraphAileronLeft(new Subgraph(graph,"AileronLeft")),
1459     mSubgraphAileronRight(new Subgraph(graph,"AileronRight")),
1460     mSubgraphElevatorLeft(new Subgraph(graph,"ElevatorLeft")),
1461     mSubgraphElevatorRight(new Subgraph(graph,"ElevatorRight")),
1462     mSubgraphRudderLeft(new Subgraph(graph,"RudderLeft")),
1463     mSubgraphRudderRight(new Subgraph(graph,"RudderRight"))
1464 {
1465     SetThrottle( 0.0f );
1466 
1467     // Exhaust flame shouldn't cast shadows.
1468     ShadowSceneGraph::DisableShadows( mSubgraphFlame0->GetRootNode() );
1469     ShadowSceneGraph::DisableShadows( mSubgraphFlame1->GetRootNode() );
1470 }
1471 
~F15Aircraft()1472 F15Aircraft::~F15Aircraft()
1473 {
1474     // NOP
1475 }
1476 
1477 /*****************************************************************************
1478  * @return Aircraft specifications struct.
1479  *****************************************************************************/
1480 const AircraftSpecs&
GetSpecs(void)1481 F15Aircraft::GetSpecs( void )  // virtual method
1482 {
1483 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1484     return F15Aircraft::ClassGetSpecs();
1485 }
1486 
1487 const AircraftSpecs&
ClassGetSpecs(void)1488 F15Aircraft::ClassGetSpecs( void )  // class method
1489 {
1490     CODE_CLASS_GET_SPECS( "physics_f15.conf" )
1491 }
1492 
1493 /*****************************************************************************
1494  * Retract/extend landing gear.
1495  *****************************************************************************/
1496 void
SetLandingGear(const bool down)1497 F15Aircraft::SetLandingGear( const bool down )
1498 {
1499 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1500 
1501     if ( IfCanSetLandingGear( down ) )
1502     {
1503         Parent::SetLandingGear( down );
1504 
1505         mSubgraphGear0->Enable( down );
1506         mSubgraphGear1->Enable( down );
1507         mSubgraphGear2->Enable( down );
1508         mSubgraphGear3->Enable( down );
1509         mSubgraphGear4->Enable( down );
1510         mSubgraphGear5->Enable( down );
1511     }
1512 }
1513 
1514 /*****************************************************************************
1515  * When throttle is changed, animate jet exhaust flame.
1516  *****************************************************************************/
1517 void
SetThrottle(const fp throttle)1518 F15Aircraft::SetThrottle( const fp throttle )
1519 {
1520 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1521 
1522     Parent::SetThrottle( throttle );
1523     mSubgraphFlame0->Enable( throttle >= THROTTLE_FLAME_LOW );
1524     mSubgraphFlame1->Enable( throttle >= THROTTLE_FLAME_HIGH );  // afterburner
1525 }
1526 
1527 /*****************************************************************************
1528  * Rotate control surfaces (ailerons etc).
1529  *****************************************************************************/
1530 void
RotateControlSurfaces(const uint axis,const fp controlFraction)1531 F15Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
1532 {
1533 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1534 ASSERT_AXIS3(axis);
1535 
1536     switch ( axis )
1537     {
1538         case AXIS_PITCH:
1539         {
1540             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
1541             RotateElevator( *mSubgraphElevatorRight, controlFraction );
1542         }
1543         break;
1544 
1545         case AXIS_ROLL:
1546         {
1547             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
1548             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
1549         }
1550         break;
1551 
1552         case AXIS_YAW:
1553         {
1554             RotateRudder( *mSubgraphRudderLeft,  controlFraction, LEFT_RUDDER  );
1555             RotateRudder( *mSubgraphRudderRight, controlFraction, RIGHT_RUDDER );
1556         }
1557         break;
1558     }
1559 }
1560 
1561 ////////////////////////////////////////////////////////////////////////////////
1562 ///////////////////////////////  F16Aircraft  //////////////////////////////////
1563 ////////////////////////////////////////////////////////////////////////////////
1564 
1565 /*****************************************************************************
1566  * ctor/dtor.
1567  *****************************************************************************/
F16Aircraft(shptr<Graph> graph,const WorldVertex & pos)1568 F16Aircraft::F16Aircraft( shptr<Graph> graph, const WorldVertex& pos )
1569 :   Parent(graph,pos,F16Aircraft::ClassGetSpecs()),
1570     // gear:
1571     mSubgraphGear0(new Subgraph(graph,"internal_front_gear_door")),
1572     mSubgraphGear1(new Subgraph(graph,"internal_right_main_door")),
1573     mSubgraphGear2(new Subgraph(graph,"internal_left_main_door")),
1574     //
1575     mSubgraphGear3(new Subgraph(graph,"front_tire")),
1576     mSubgraphGear4(new Subgraph(graph,"front_aft_strut")),
1577     mSubgraphGear5(new Subgraph(graph,"front_lower_strut")),
1578     mSubgraphGear6(new Subgraph(graph,"front_upper_strut")),
1579     //
1580     mSubgraphGear7(new Subgraph(graph,"left_main_strut")),
1581     mSubgraphGear8(new Subgraph(graph,"left_main_tire")),
1582     mSubgraphGear9(new Subgraph(graph,"left_lower_main_strut")),
1583     mSubgraphGear10(new Subgraph(graph,"left_upper_main_strut")),
1584     //
1585     mSubgraphGear11(new Subgraph(graph,"right_main_strut")),
1586     mSubgraphGear12(new Subgraph(graph,"right_main_tire")),
1587     mSubgraphGear13(new Subgraph(graph,"right_lower_main_strut")),
1588     mSubgraphGear14(new Subgraph(graph,"right_upper_main_strut")),
1589     //
1590     mSubgraphGear15(new Subgraph(graph,"external_front_gear_door")),
1591     mSubgraphGear16(new Subgraph(graph,"external_left_main_door")),
1592     mSubgraphGear17(new Subgraph(graph,"external_right_main_door")),
1593     // exhaust flame:
1594     mSubgraphFlame0(new Subgraph(graph,"internal_flame")),
1595     mSubgraphFlame1(new Subgraph(graph,"external_flame")),
1596     // control surfaces:
1597     mSubgraphAileronLeft(new Subgraph(graph,"left_upper_aileron")),
1598     mSubgraphAileronRight(new Subgraph(graph,"right_upper_aileron")),
1599     mSubgraphFlapLeft(new Subgraph(graph,"left_upper_flap")),
1600     mSubgraphFlapRight(new Subgraph(graph,"right_upper_flap")),
1601     mSubgraphElevatorLeft(new Subgraph(graph,"left_upper_horizontal_tail")),
1602     mSubgraphElevatorRight(new Subgraph(graph,"right_upper_horizontal_tail")),
1603     mSubgraphRudder0(new Subgraph(graph,"rudder2")),
1604     mSubgraphRudder1(new Subgraph(graph,"rudder3")),
1605     mSubgraphRudder2(new Subgraph(graph,"rudder5")),
1606     mSubgraphRudder3(new Subgraph(graph,"rudder6")),
1607     // junk:
1608     mSubgraphJunk0(new Subgraph(graph,"lhocondenscone")),
1609     mSubgraphJunk1(new Subgraph(graph,"rhocondenscone"))
1610 {
1611     SetThrottle( 0.0f );
1612 
1613     // Exhaust flame shouldn't cast shadows.
1614     ShadowSceneGraph::DisableShadows( mSubgraphFlame0->GetRootNode() );
1615     ShadowSceneGraph::DisableShadows( mSubgraphFlame1->GetRootNode() );
1616 
1617     // Disable junk parts of F-16 model.
1618     mSubgraphJunk0->Enable( false );
1619     mSubgraphJunk1->Enable( false );
1620 }
1621 
~F16Aircraft()1622 F16Aircraft::~F16Aircraft()
1623 {
1624     // NOP
1625 }
1626 
1627 /*****************************************************************************
1628  * @return Aircraft specifications struct.
1629  *****************************************************************************/
1630 const AircraftSpecs&
GetSpecs(void)1631 F16Aircraft::GetSpecs( void )  // virtual method
1632 {
1633 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1634     return F16Aircraft::ClassGetSpecs();
1635 }
1636 
1637 const AircraftSpecs&
ClassGetSpecs(void)1638 F16Aircraft::ClassGetSpecs( void )  // class method
1639 {
1640     CODE_CLASS_GET_SPECS( "physics_f16.conf" )
1641 }
1642 
1643 /*****************************************************************************
1644  * Retract/extend landing gear.
1645  *****************************************************************************/
1646 void
SetLandingGear(const bool down)1647 F16Aircraft::SetLandingGear( const bool down )
1648 {
1649 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1650 
1651     // Known problem: The door for the front wheel should be rotated
1652     // into the fuselage but isn't implemented.
1653 
1654     if ( IfCanSetLandingGear( down ) )
1655     {
1656         Parent::SetLandingGear( down );
1657 
1658         mSubgraphGear0->Enable( down );  mSubgraphGear1->Enable( down );
1659         mSubgraphGear2->Enable( down );  mSubgraphGear3->Enable( down );
1660         mSubgraphGear4->Enable( down );  mSubgraphGear5->Enable( down );
1661         mSubgraphGear6->Enable( down );  mSubgraphGear7->Enable( down );
1662         mSubgraphGear8->Enable( down );  mSubgraphGear9->Enable( down );
1663         mSubgraphGear10->Enable( down ); mSubgraphGear11->Enable( down );
1664         mSubgraphGear12->Enable( down ); mSubgraphGear13->Enable( down );
1665         mSubgraphGear14->Enable( down ); mSubgraphGear15->Enable( down );
1666       //mSubgraphGear16->Enable( down ); mSubgraphGear17->Enable( down );
1667     }
1668 }
1669 
1670 /*****************************************************************************
1671  * When throttle is changed, animate jet exhaust flame.
1672  *****************************************************************************/
1673 void
SetThrottle(const fp throttle)1674 F16Aircraft::SetThrottle( const fp throttle )
1675 {
1676 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1677 
1678     Parent::SetThrottle( throttle );
1679 //  mSubgraphFlame0->Enable( throttle >= THROTTLE_FLAME_LOW );  // see-thru problem
1680     mSubgraphFlame1->Enable( throttle >= THROTTLE_FLAME_HIGH );  // afterburner
1681 }
1682 
1683 /*****************************************************************************
1684  * Rotate control surfaces (ailerons etc).
1685  *****************************************************************************/
1686 void
RotateControlSurfaces(const uint axis,const fp controlFraction)1687 F16Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
1688 {
1689 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1690 ASSERT_AXIS3(axis);
1691 
1692     switch ( axis )
1693     {
1694         case AXIS_PITCH:
1695         {
1696             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
1697             RotateElevator( *mSubgraphElevatorRight, controlFraction );
1698         }
1699         break;
1700 
1701         case AXIS_ROLL:
1702         {
1703             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
1704             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
1705 #if 0
1706             RotateAileron( *mSubgraphFlapLeft,  controlFraction, LEFT_AILERON );
1707             RotateAileron( *mSubgraphFlapRight, controlFraction, RIGHT_AILERON );
1708 #endif
1709         }
1710         break;
1711 
1712         case AXIS_YAW:
1713         {
1714             RotateRudder( *mSubgraphRudder0, controlFraction );
1715             RotateRudder( *mSubgraphRudder1, controlFraction );
1716             RotateRudder( *mSubgraphRudder2, controlFraction );
1717             RotateRudder( *mSubgraphRudder3, controlFraction );
1718         }
1719         break;
1720     }
1721 }
1722 
1723 ////////////////////////////////////////////////////////////////////////////////
1724 ///////////////////////////////  F18Aircraft  //////////////////////////////////
1725 ////////////////////////////////////////////////////////////////////////////////
1726 
1727 /*****************************************************************************
1728  * ctor/dtor.
1729  *****************************************************************************/
F18Aircraft(shptr<Graph> graph,const WorldVertex & pos)1730 F18Aircraft::F18Aircraft( shptr<Graph> graph, const WorldVertex& pos )
1731 :   Parent(graph,pos,F18Aircraft::ClassGetSpecs()),
1732     // gear:
1733     mSubgraphGear0(new Subgraph(graph,"LeftWheel")),
1734     mSubgraphGear1(new Subgraph(graph,"LeftDoor")),
1735     mSubgraphGear2(new Subgraph(graph,"RightWheel")),
1736     mSubgraphGear3(new Subgraph(graph,"RightDoor")),
1737     mSubgraphGear4(new Subgraph(graph,"FrontWheel")),
1738     mSubgraphGear5(new Subgraph(graph,"FrontDoor")),
1739     // exhaust flame:
1740     mSubgraphFlame0(new Subgraph(graph,"InternalFlame")),
1741     mSubgraphFlame1(new Subgraph(graph,"ExternalFlame")),
1742     // control surfaces:
1743     mSubgraphAileronLeft(new Subgraph(graph,"AileronLeft")),
1744     mSubgraphAileronRight(new Subgraph(graph,"AileronRight")),
1745     mSubgraphElevatorLeft(new Subgraph(graph,"ElevatorLeft")),
1746     mSubgraphElevatorRight(new Subgraph(graph,"ElevatorRight")),
1747     mSubgraphRudderLeft(new Subgraph(graph,"RudderLeft")),
1748     mSubgraphRudderRight(new Subgraph(graph,"RudderRight"))
1749 {
1750     SetThrottle( 0.0f );
1751 
1752     // Exhaust flame shouldn't cast shadows.
1753     ShadowSceneGraph::DisableShadows( mSubgraphFlame0->GetRootNode() );
1754     ShadowSceneGraph::DisableShadows( mSubgraphFlame1->GetRootNode() );
1755 }
1756 
~F18Aircraft()1757 F18Aircraft::~F18Aircraft()
1758 {
1759     // NOP
1760 }
1761 
1762 /*****************************************************************************
1763  * @return Aircraft specifications struct.
1764  *****************************************************************************/
1765 const AircraftSpecs&
GetSpecs(void)1766 F18Aircraft::GetSpecs( void )  // virtual method
1767 {
1768 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1769     return F18Aircraft::ClassGetSpecs();
1770 }
1771 
1772 const AircraftSpecs&
ClassGetSpecs(void)1773 F18Aircraft::ClassGetSpecs( void )  // class method
1774 {
1775     CODE_CLASS_GET_SPECS( "physics_f18.conf" )
1776 }
1777 
1778 /*****************************************************************************
1779  * Retract/extend landing gear.
1780  *****************************************************************************/
1781 void
SetLandingGear(const bool down)1782 F18Aircraft::SetLandingGear( const bool down )
1783 {
1784 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1785 
1786     if ( IfCanSetLandingGear( down ) )
1787     {
1788         Parent::SetLandingGear( down );
1789 
1790         mSubgraphGear0->Enable( down );
1791         mSubgraphGear1->Enable( down );
1792         mSubgraphGear2->Enable( down );
1793         mSubgraphGear3->Enable( down );
1794         mSubgraphGear4->Enable( down );
1795         mSubgraphGear5->Enable( down );
1796     }
1797 }
1798 
1799 /*****************************************************************************
1800  * When throttle is changed, animate jet exhaust flame.
1801  *****************************************************************************/
1802 void
SetThrottle(const fp throttle)1803 F18Aircraft::SetThrottle( const fp throttle )
1804 {
1805 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1806 
1807     Parent::SetThrottle( throttle );
1808   //mSubgraphFlame0->Enable( throttle >= THROTTLE_FLAME_LOW );  // see-thru problem
1809     mSubgraphFlame1->Enable( throttle >= THROTTLE_FLAME_HIGH );  // afterburner
1810 }
1811 
1812 /*****************************************************************************
1813  * Rotate control surfaces (ailerons etc).
1814  *****************************************************************************/
1815 void
RotateControlSurfaces(const uint axis,const fp controlFraction)1816 F18Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
1817 {
1818 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1819 ASSERT_AXIS3(axis);
1820 
1821     switch ( axis )
1822     {
1823         case AXIS_PITCH:
1824         {
1825             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
1826             RotateElevator( *mSubgraphElevatorRight, controlFraction );
1827         }
1828         break;
1829 
1830         case AXIS_ROLL:
1831         {
1832             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
1833             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
1834         }
1835         break;
1836 
1837         case AXIS_YAW:
1838         {
1839             RotateRudder( *mSubgraphRudderLeft,  controlFraction, LEFT_RUDDER  );
1840             RotateRudder( *mSubgraphRudderRight, controlFraction, RIGHT_RUDDER );
1841         }
1842         break;
1843     }
1844 }
1845 
1846 ////////////////////////////////////////////////////////////////////////////////
1847 ///////////////////////////////  SR71Aircraft  //////////////////////////////////
1848 ////////////////////////////////////////////////////////////////////////////////
1849 
1850 /*****************************************************************************
1851  * ctor/dtor.
1852  *****************************************************************************/
SR71Aircraft(shptr<Graph> graph,const WorldVertex & pos)1853 SR71Aircraft::SR71Aircraft( shptr<Graph> graph, const WorldVertex& pos )
1854 :   Parent(graph,pos,SR71Aircraft::ClassGetSpecs()),
1855     // gear:
1856     mSubgraphGear0(new Subgraph(graph,"roueA")),  // roue means wheel in French
1857     mSubgraphGear1(new Subgraph(graph,"roueD")),
1858     mSubgraphGear2(new Subgraph(graph,"roueG")),
1859     // struts:
1860     mSubgraphStrut0(new Subgraph(graph,"axeA")),
1861     mSubgraphStrut1(new Subgraph(graph,"axeD")),
1862     mSubgraphStrut2(new Subgraph(graph,"axeG")),
1863     mSubgraphStrut3(new Subgraph(graph,"barrebasA")),
1864     mSubgraphStrut4(new Subgraph(graph,"barrebasD")),
1865     mSubgraphStrut5(new Subgraph(graph,"barrebasG")),
1866     mSubgraphStrut6(new Subgraph(graph,"barrehautA")),
1867     mSubgraphStrut7(new Subgraph(graph,"barrehautD")),
1868     mSubgraphStrut8(new Subgraph(graph,"barrehautG")),
1869     mSubgraphStrut9(new Subgraph(graph,"porteD1")),
1870     mSubgraphStrut10(new Subgraph(graph,"porteD2")),
1871     mSubgraphStrut11(new Subgraph(graph,"porteG1")),
1872     mSubgraphStrut12(new Subgraph(graph,"porteG2")),
1873     mSubgraphStrut13(new Subgraph(graph,"verrinA")),
1874     mSubgraphStrut14(new Subgraph(graph,"verrinD")),
1875     mSubgraphStrut15(new Subgraph(graph,"verrinG")),
1876     // parachute:
1877     mSubgraphParachute(new Subgraph(graph,"parachute")),
1878     // exhaust flame:
1879     mSubgraphFlame0(new Subgraph(graph,"flammeD1")),
1880     mSubgraphFlame1(new Subgraph(graph,"flammeD2")),
1881     mSubgraphFlame2(new Subgraph(graph,"flammeD3")),
1882     mSubgraphFlame3(new Subgraph(graph,"flammeG1")),
1883     mSubgraphFlame4(new Subgraph(graph,"flammeG2")),
1884     mSubgraphFlame5(new Subgraph(graph,"flammeG3")),
1885     // Control surfaces:
1886     mSubgraphAileronLeft(new Subgraph(graph,"aileronG")),
1887     mSubgraphAileronRight(new Subgraph(graph,"aileronD")),
1888     mSubgraphElevatorLeft(new Subgraph(graph,"profondeurG")),
1889     mSubgraphElevatorRight(new Subgraph(graph,"profondeurD"))
1890     // (rudder omitted)
1891 {
1892     SetThrottle( 0.0f );
1893 
1894     // Exhaust flame shouldn't cast shadows.
1895     ShadowSceneGraph::DisableShadows( mSubgraphFlame0->GetRootNode() );
1896     ShadowSceneGraph::DisableShadows( mSubgraphFlame1->GetRootNode() );
1897     ShadowSceneGraph::DisableShadows( mSubgraphFlame2->GetRootNode() );
1898     ShadowSceneGraph::DisableShadows( mSubgraphFlame3->GetRootNode() );
1899     ShadowSceneGraph::DisableShadows( mSubgraphFlame4->GetRootNode() );
1900     ShadowSceneGraph::DisableShadows( mSubgraphFlame5->GetRootNode() );
1901 
1902     mSubgraphParachute->Enable( false );
1903 }
1904 
~SR71Aircraft()1905 SR71Aircraft::~SR71Aircraft()
1906 {
1907     // NOP
1908 }
1909 
1910 /*****************************************************************************
1911  * @return Aircraft specifications struct.
1912  *****************************************************************************/
1913 const AircraftSpecs&
GetSpecs(void)1914 SR71Aircraft::GetSpecs( void )  // virtual method
1915 {
1916 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1917     return SR71Aircraft::ClassGetSpecs();
1918 }
1919 
1920 const AircraftSpecs&
ClassGetSpecs(void)1921 SR71Aircraft::ClassGetSpecs( void )  // class method
1922 {
1923     CODE_CLASS_GET_SPECS( "physics_sr71.conf" )
1924 }
1925 
1926 /*****************************************************************************
1927  * Retract/extend landing gear.
1928  *****************************************************************************/
1929 void
SetLandingGear(const bool down)1930 SR71Aircraft::SetLandingGear( const bool down )
1931 {
1932 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1933 
1934     if ( IfCanSetLandingGear( down ))
1935     {
1936         Parent::SetLandingGear( down );
1937 
1938         mSubgraphGear0->Enable( down );
1939         mSubgraphGear1->Enable( down );
1940         mSubgraphGear2->Enable( down );
1941 
1942         mSubgraphStrut0->Enable( down );
1943         mSubgraphStrut1->Enable( down );
1944         mSubgraphStrut2->Enable( down );
1945         mSubgraphStrut3->Enable( down );
1946         mSubgraphStrut4->Enable( down );
1947         mSubgraphStrut5->Enable( down );
1948         mSubgraphStrut6->Enable( down );
1949         mSubgraphStrut7->Enable( down );
1950         mSubgraphStrut8->Enable( down );
1951         mSubgraphStrut9->Enable( down );
1952         mSubgraphStrut10->Enable( down );
1953         mSubgraphStrut11->Enable( down );
1954         mSubgraphStrut12->Enable( down );
1955         mSubgraphStrut13->Enable( down );
1956         mSubgraphStrut14->Enable( down );
1957         mSubgraphStrut15->Enable( down );
1958     }
1959 }
1960 
1961 /*****************************************************************************
1962  * When throttle is changed, animate jet exhaust flame.
1963  *****************************************************************************/
1964 void
SetThrottle(const fp throttle)1965 SR71Aircraft::SetThrottle( const fp throttle )
1966 {
1967 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1968 
1969     Parent::SetThrottle( throttle );
1970     const bool flame = (throttle >= THROTTLE_FLAME);
1971     mSubgraphFlame0->Enable( flame );
1972     mSubgraphFlame1->Enable( flame );
1973     mSubgraphFlame2->Enable( flame );
1974     mSubgraphFlame3->Enable( flame );
1975     mSubgraphFlame4->Enable( flame );
1976     mSubgraphFlame5->Enable( flame );
1977 }
1978 
1979 /*****************************************************************************
1980  * Rotate control surfaces (ailerons etc).
1981  *****************************************************************************/
1982 void
RotateControlSurfaces(const uint axis,const fp controlFraction)1983 SR71Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
1984 {
1985 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
1986 ASSERT_AXIS3(axis);
1987 
1988     switch ( axis )
1989     {
1990         case AXIS_PITCH:
1991         {
1992             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
1993             RotateElevator( *mSubgraphElevatorRight, controlFraction );
1994         }
1995         break;
1996 
1997         case AXIS_ROLL:
1998         {
1999             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
2000             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
2001         }
2002         break;
2003 
2004 #if 0
2005         case AXIS_YAW:
2006         {
2007             RotateRudder( *mSubgraphRudder, controlFraction );
2008         }
2009         break;
2010 #endif
2011     }
2012 }
2013 
2014 ////////////////////////////////////////////////////////////////////////////////
2015 ////////////////////////////  Mirage2000Aircraft  //////////////////////////////
2016 ////////////////////////////////////////////////////////////////////////////////
2017 
2018 /*****************************************************************************
2019  * ctor/dtor.
2020  *****************************************************************************/
Mirage2000Aircraft(shptr<Graph> graph,const WorldVertex & pos)2021 Mirage2000Aircraft::Mirage2000Aircraft( shptr<Graph> graph, const WorldVertex& pos )
2022 :   Parent(graph,pos,Mirage2000Aircraft::ClassGetSpecs()),
2023     // gear:
2024     mSubgraphGear0(new Subgraph(graph,"front_tire")),
2025     mSubgraphGear1(new Subgraph(graph,"front_wheel")),
2026     mSubgraphGear2(new Subgraph(graph,"front_door_fwd")),
2027     mSubgraphGear3(new Subgraph(graph,"left_wheel")),
2028     mSubgraphGear4(new Subgraph(graph,"left_tire")),
2029     mSubgraphGear5(new Subgraph(graph,"left_door")),
2030     mSubgraphGear6(new Subgraph(graph,"right_wheel")),
2031     mSubgraphGear7(new Subgraph(graph,"right_tire")),
2032     mSubgraphGear8(new Subgraph(graph,"right_door")),
2033     // exhaust flame:
2034     mSubgraphFlame0(new Subgraph(graph,"internal_flame")),
2035     mSubgraphFlame1(new Subgraph(graph,"external_flame")),
2036     // Control surfaces:
2037     mSubgraphAileronLeft(new Subgraph(graph,"VoletGauche")),  // are elevators too
2038     mSubgraphAileronRight(new Subgraph(graph,"VoletDroit")),
2039     mSubgraphRudder(new Subgraph(graph,"rudder"))
2040 {
2041     SetThrottle( 0.0f );
2042 
2043     // Exhaust flame shouldn't cast shadows.
2044     ShadowSceneGraph::DisableShadows( mSubgraphFlame0->GetRootNode() );
2045     ShadowSceneGraph::DisableShadows( mSubgraphFlame1->GetRootNode() );
2046 }
2047 
~Mirage2000Aircraft()2048 Mirage2000Aircraft::~Mirage2000Aircraft()
2049 {
2050     // NOP
2051 }
2052 
2053 /*****************************************************************************
2054  * @return Aircraft specifications struct.
2055  *****************************************************************************/
2056 const AircraftSpecs&
GetSpecs(void)2057 Mirage2000Aircraft::GetSpecs( void )  // virtual method
2058 {
2059 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2060     return Mirage2000Aircraft::ClassGetSpecs();
2061 }
2062 
2063 const AircraftSpecs&
ClassGetSpecs(void)2064 Mirage2000Aircraft::ClassGetSpecs( void )  // class method
2065 {
2066     CODE_CLASS_GET_SPECS( "physics_mirage2000.conf" )
2067 }
2068 
2069 /*****************************************************************************
2070  * Retract/extend landing gear.
2071  *****************************************************************************/
2072 void
SetLandingGear(const bool down)2073 Mirage2000Aircraft::SetLandingGear( const bool down )
2074 {
2075 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2076 
2077     if ( IfCanSetLandingGear( down ))
2078     {
2079         Parent::SetLandingGear( down );
2080 
2081         mSubgraphGear0->Enable( down );
2082         mSubgraphGear1->Enable( down );
2083         mSubgraphGear2->Enable( down );
2084         mSubgraphGear3->Enable( down );
2085         mSubgraphGear4->Enable( down );
2086         mSubgraphGear5->Enable( down );
2087         mSubgraphGear6->Enable( down );
2088         mSubgraphGear7->Enable( down );
2089         mSubgraphGear8->Enable( down );
2090     }
2091 }
2092 
2093 /*****************************************************************************
2094  * When throttle is changed, animate jet exhaust flame.
2095  *****************************************************************************/
2096 void
SetThrottle(const fp throttle)2097 Mirage2000Aircraft::SetThrottle( const fp throttle )
2098 {
2099 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2100 
2101     Parent::SetThrottle( throttle );
2102 //  mSubgraphFlame0->Enable( throttle >= THROTTLE_FLAME_LOW ); // see-thru problem
2103     mSubgraphFlame1->Enable( throttle >= THROTTLE_FLAME );  // afterburner
2104 }
2105 
2106 /*****************************************************************************
2107  * Rotate control surfaces (ailerons etc).
2108  *****************************************************************************/
2109 void
RotateControlSurfaces(const uint axis,const fp controlFraction)2110 Mirage2000Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
2111 {
2112 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2113 ASSERT_AXIS3(axis);
2114 
2115     switch ( axis )
2116     {
2117         // On Mirage, ailerons are also elevators.
2118         case AXIS_PITCH:
2119         {
2120             RotateElevator( *mSubgraphAileronLeft,  controlFraction );
2121             RotateElevator( *mSubgraphAileronRight, controlFraction );
2122         }
2123         break;
2124 
2125         case AXIS_ROLL:
2126         {
2127             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
2128             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
2129         }
2130         break;
2131 
2132         case AXIS_YAW:
2133         {
2134             RotateRudder( *mSubgraphRudder, controlFraction );
2135         }
2136         break;
2137     }
2138 }
2139 
2140 ////////////////////////////////////////////////////////////////////////////////
2141 ///////////////////////////////  SU37Aircraft  /////////////////////////////////
2142 ////////////////////////////////////////////////////////////////////////////////
2143 
2144 /*****************************************************************************
2145  * ctor/dtor.
2146  *****************************************************************************/
SU37Aircraft(shptr<Graph> graph,const WorldVertex & pos)2147 SU37Aircraft::SU37Aircraft( shptr<Graph> graph, const WorldVertex& pos )
2148 :   Parent(graph,pos,SU37Aircraft::ClassGetSpecs()),
2149     // gear:
2150     mSubgraphGear0(new Subgraph(graph,"UC")),  // under carriage
2151     // exhaust flame:
2152     mSubgraphFlame0(new Subgraph(graph,"L_Reheat")),
2153     mSubgraphFlame1(new Subgraph(graph,"R_Reheat")),
2154     // control surfaces:
2155     mSubgraphAileronLeft(new Subgraph(graph,"WNG_Left_Flaperon")),
2156     mSubgraphAileronRight(new Subgraph(graph,"WNG_Right_Flaperon")),
2157     mSubgraphElevatorLeft(new Subgraph(graph,"ELV_Elevon_Left")),
2158     mSubgraphElevatorRight(new Subgraph(graph,"ELV_Elevon_Right")),
2159     mSubgraphRudderLeft(new Subgraph(graph,"TF_Left_Rudder")),
2160     mSubgraphRudderRight(new Subgraph(graph,"TF_Right_Rudder"))
2161 
2162 {
2163     SetThrottle( 0.0f );
2164 
2165     // Exhaust flame shouldn't cast shadows.
2166     ShadowSceneGraph::DisableShadows( mSubgraphFlame0->GetRootNode() );
2167     ShadowSceneGraph::DisableShadows( mSubgraphFlame1->GetRootNode() );
2168 }
2169 
~SU37Aircraft()2170 SU37Aircraft::~SU37Aircraft()
2171 {
2172     // NOP
2173 }
2174 
2175 /*****************************************************************************
2176  * @return Aircraft specifications struct.
2177  *****************************************************************************/
2178 const AircraftSpecs&
GetSpecs(void)2179 SU37Aircraft::GetSpecs( void )  // virtual method
2180 {
2181 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2182     return SU37Aircraft::ClassGetSpecs();
2183 }
2184 
2185 const AircraftSpecs&
ClassGetSpecs(void)2186 SU37Aircraft::ClassGetSpecs( void )  // class method
2187 {
2188     CODE_CLASS_GET_SPECS( "physics_su37.conf" )
2189 }
2190 
2191 /*****************************************************************************
2192  * Retract/extend landing gear.
2193  *****************************************************************************/
2194 void
SetLandingGear(const bool down)2195 SU37Aircraft::SetLandingGear( const bool down )
2196 {
2197 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2198 
2199     if ( IfCanSetLandingGear( down ))
2200     {
2201         Parent::SetLandingGear( down );
2202 
2203         mSubgraphGear0->Enable( down );
2204     }
2205 }
2206 
2207 /*****************************************************************************
2208  * When throttle is changed, animate jet exhaust flame.
2209  *****************************************************************************/
2210 void
SetThrottle(const fp throttle)2211 SU37Aircraft::SetThrottle( const fp throttle )
2212 {
2213 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2214 
2215     Parent::SetThrottle( throttle );
2216     const bool flame = (throttle >= THROTTLE_FLAME);
2217     mSubgraphFlame0->Enable( flame );
2218     mSubgraphFlame1->Enable( flame );
2219 }
2220 
2221 /*****************************************************************************
2222  * Rotate control surfaces (ailerons etc).
2223  *****************************************************************************/
2224 void
RotateControlSurfaces(const uint axis,const fp controlFraction)2225 SU37Aircraft::RotateControlSurfaces( const uint axis, const fp controlFraction )
2226 {
2227 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2228 ASSERT_AXIS3(axis);
2229 
2230     switch ( axis )
2231     {
2232         case AXIS_PITCH:
2233         {
2234             RotateElevator( *mSubgraphElevatorLeft,  controlFraction );
2235             RotateElevator( *mSubgraphElevatorRight, controlFraction );
2236         }
2237         break;
2238 
2239         case AXIS_ROLL:
2240         {
2241             RotateAileron( *mSubgraphAileronLeft,  controlFraction, LEFT_AILERON );
2242             RotateAileron( *mSubgraphAileronRight, controlFraction, RIGHT_AILERON );
2243         }
2244         break;
2245 
2246         case AXIS_YAW:
2247         {
2248             RotateRudder( *mSubgraphRudderLeft,  controlFraction, LEFT_RUDDER  );
2249             RotateRudder( *mSubgraphRudderRight, controlFraction, RIGHT_RUDDER );
2250         }
2251         break;
2252     }
2253 }
2254 
2255 ////////////////////////////////////////////////////////////////////////////////
2256 //////////////////////////  SpaceShuttleAircraft  //////////////////////////////
2257 ////////////////////////////////////////////////////////////////////////////////
2258 
2259 /*****************************************************************************
2260  * ctor/dtor.
2261  *****************************************************************************/
SpaceShuttleAircraft(shptr<Graph> graph,const WorldVertex & pos)2262 SpaceShuttleAircraft::SpaceShuttleAircraft( shptr<Graph> graph, const WorldVertex& pos )
2263 :   Parent(graph,pos,SpaceShuttleAircraft::ClassGetSpecs()),
2264     mSubgraphBayDoorLeft(new Subgraph(graph,"bay_door_left")),
2265     mSubgraphBayDoorRight(new Subgraph(graph,"bay_door_right")),
2266     mBayDoorsFraction(0.0f)
2267 {
2268     // NOP
2269 }
2270 
~SpaceShuttleAircraft()2271 SpaceShuttleAircraft::~SpaceShuttleAircraft()
2272 {
2273     // NOP
2274 }
2275 
2276 /*****************************************************************************
2277  * Reset.
2278  *****************************************************************************/
2279 void
Reset(void)2280 SpaceShuttleAircraft::Reset( void )
2281 {
2282     Parent::Reset();
2283 
2284     // Close bay doors.
2285     SwingBayDoors( 0.0f );
2286 }
2287 
2288 /*****************************************************************************
2289  * @return Aircraft specifications struct.
2290  *****************************************************************************/
2291 const AircraftSpecs&
GetSpecs(void)2292 SpaceShuttleAircraft::GetSpecs( void )  // virtual method
2293 {
2294 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2295 
2296     return SpaceShuttleAircraft::ClassGetSpecs();
2297 }
2298 
2299 const AircraftSpecs&
ClassGetSpecs(void)2300 SpaceShuttleAircraft::ClassGetSpecs( void )  // class method
2301 {
2302     CODE_CLASS_GET_SPECS( "physics_spaceShuttle.conf" )
2303 }
2304 
2305 /*****************************************************************************
2306  * Really open bay doors.
2307  * Reason for this subterfuge is to reuse keyboard control for swinging wings.
2308  *****************************************************************************/
2309 void
SwingWings(const float fraction)2310 SpaceShuttleAircraft::SwingWings( const float fraction )
2311 {
2312 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2313 
2314     SwingBayDoors( fraction );
2315 }
2316 
2317 /*****************************************************************************
2318  * Open bay doors { 0.0:closed ... 1.0:open }
2319  *****************************************************************************/
2320 void
SwingBayDoors(const float fraction)2321 SpaceShuttleAircraft::SwingBayDoors( const float fraction )
2322 {
2323 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2324 
2325     mBayDoorsFraction = Clamp1( fraction );
2326 
2327     // Undo rotation/translation of wing subgraphs from previous call.
2328     mSubgraphBayDoorLeft->Reset();
2329     mSubgraphBayDoorRight->Reset();
2330 
2331     // deg = 0  fully closed
2332     // deg = 70 fully open
2333     const Degree deg = mBayDoorsFraction * 70.0f;
2334     const Radian rad = Deg2Rad( deg );
2335 
2336     // Translate to center the pivot at door hinges.
2337     fp offset0 = 0.03f;
2338     fp offset1 = 0.08f;
2339     mSubgraphBayDoorLeft->Translate(  YY,  offset0 );  // up
2340     mSubgraphBayDoorRight->Translate( YY,  offset0 );  // up
2341     mSubgraphBayDoorLeft->Translate(  XX, -offset1 );  // horz
2342     mSubgraphBayDoorRight->Translate( XX,  offset1 );  // horz
2343 
2344     mSubgraphBayDoorLeft->Rotate(  ZZ,  rad );
2345     mSubgraphBayDoorRight->Rotate( ZZ, -rad );
2346 
2347     // Undo translation.
2348     offset0 = -offset0;
2349     offset1 = -offset1;
2350     mSubgraphBayDoorLeft->Translate(  YY,  offset0 );  // up
2351     mSubgraphBayDoorRight->Translate( YY,  offset0 );  // up
2352     mSubgraphBayDoorLeft->Translate(  XX, -offset1 );  // horz
2353     mSubgraphBayDoorRight->Translate( XX,  offset1 );  // horz
2354 }
2355 
2356 ////////////////////////////////////////////////////////////////////////////////
2357 ////////////////////////////  SikorskyAircraft  ////////////////////////////////
2358 ////////////////////////////////////////////////////////////////////////////////
2359 
2360 /*****************************************************************************
2361  * ctor/dtor.
2362  *****************************************************************************/
SikorskyAircraft(shptr<Graph> graph,const WorldVertex & pos)2363 SikorskyAircraft::SikorskyAircraft( shptr<Graph> graph, const WorldVertex& pos )
2364 :   Parent(graph,pos,SikorskyAircraft::ClassGetSpecs()),
2365     mSubgraphRotor0(new Subgraph(graph,"blade1")),
2366     mSubgraphRotor1(new Subgraph(graph,"blade2")),
2367     mSubgraphRotor2(new Subgraph(graph,"blade3")),
2368     mSubgraphRotor3(new Subgraph(graph,"blade4")),
2369     mSubgraphRotor4(new Subgraph(graph,"fastblade1")),  // blurred
2370     mSubgraphRotor5(new Subgraph(graph,"fastblade2")),  // blurred
2371     mSubgraphRotor6(new Subgraph(graph,"fastblade3")),  // blurred
2372     mSubgraphRotor7(new Subgraph(graph,"fastblade4")),  // blurred
2373     mSubgraphTailRotor(new Subgraph(graph,"TailRotor"))
2374 {
2375     // NOP
2376 }
2377 
~SikorskyAircraft()2378 SikorskyAircraft::~SikorskyAircraft()
2379 {
2380     // NOP
2381 }
2382 
2383 /*****************************************************************************
2384  * @return Aircraft specifications struct.
2385  *****************************************************************************/
2386 const AircraftSpecs&
GetSpecs(void)2387 SikorskyAircraft::GetSpecs( void )  // virtual method
2388 {
2389 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2390 
2391     return SikorskyAircraft::ClassGetSpecs();
2392 }
2393 
2394 const AircraftSpecs&
ClassGetSpecs(void)2395 SikorskyAircraft::ClassGetSpecs( void )  // class method
2396 {
2397     CODE_CLASS_GET_SPECS( "physics_sikorsky.conf" )
2398 }
2399 
2400 /*****************************************************************************
2401  * Tick that pulses animation.
2402  *****************************************************************************/
2403 void
Tick(const Milliseconds millisecElapsed)2404 SikorskyAircraft::Tick( const Milliseconds millisecElapsed )
2405 {
2406 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2407 
2408     Parent::Tick( millisecElapsed );
2409 
2410     RotateRotors();
2411 }
2412 
2413 /*****************************************************************************
2414  * Rotate propeller.
2415  *****************************************************************************/
2416 void
RotateRotors(void)2417 SikorskyAircraft::RotateRotors( void )
2418 {
2419 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2420 
2421     const uint   axisRotor     = YY;  // main rotors
2422 //  const uint   axisTailRotor = ZZ;
2423   {
2424     const Radian radian = Deg2Rad( Degree(10.0f) );
2425     mSubgraphRotor0->Rotate( axisRotor, radian );
2426     mSubgraphRotor1->Rotate( axisRotor, radian );
2427     mSubgraphRotor2->Rotate( axisRotor, radian );
2428     mSubgraphRotor3->Rotate( axisRotor, radian );
2429   }
2430   {
2431     const Radian radian = Deg2Rad( Degree(5.0f) );  // blurred rotors
2432     mSubgraphRotor4->Rotate( axisRotor, radian );
2433     mSubgraphRotor5->Rotate( axisRotor, radian );
2434     mSubgraphRotor6->Rotate( axisRotor, radian );
2435     mSubgraphRotor7->Rotate( axisRotor, radian );
2436   }
2437 
2438     // The origin of the tail rotor is the center of the helicopter
2439     // rather than the rotor's hub, so just toggle enablement.
2440 #if 1
2441     mSubgraphTailRotor->Enable( not mSubgraphTailRotor->IfEnabled() );
2442 #else
2443   {
2444     const Radian radian = Deg2Rad( Degree(30.0f) );
2445     mSubgraphTailRotor->Rotate( axisTailRotor, radian );
2446   }
2447 #endif
2448 }
2449 
2450 /*****************************************************************************
2451  * Retract/extend landing gear.
2452  *****************************************************************************/
2453 void
SetLandingGear(const bool down)2454 SikorskyAircraft::SetLandingGear( const bool down )
2455 {
2456 CHECK_TYPESIG(this,TYPESIG_AIRCRAFT);
2457 
2458     if ( IfCanSetLandingGear( down ) )
2459     {
2460         Parent::SetLandingGear( down );
2461 
2462         Parent::mLandingGearDown = true;  // override
2463     }
2464 }
2465 
2466 } // namespace program
2467