Aviator on the BBC Micro

# Flight model: ApplyFlightModel (Part 2 of 7)

```       Name: ApplyFlightModel (Part 2 of 7)                          [Show more]
Type: Subroutine
Category: Flight model
Summary: Convert velocity to the plane's perspective and calculate various
aerodynamic forces
Deep dive: The flight model
Context: See this subroutine in context in the source code
References: No direct references to this subroutine in this source file

This part does the following:

* Rotate the plane's velocity vector in (xVelocity, yVelocity, zVelocity) to
the plane's frame of reference using matrix 1, and store the result in
(xVelocityP, yVelocityP, zVelocityP):

[ xVelocityP ]             [ xVelocity ]
[ yVelocityP ] = matrix1 x [ yVelocity ]
[ zVelocityP ]             [ zVelocity ]

* Call the ApplyAerodynamics routine to check for stalling:

* If we are already stalling and not going fast enough to pull out of the
stall, make the stalling sound and move on.

* If we are not already stalling, or we are possibly going fast enough to
pull out of the stall (zVelocityPHi >= 11), we perform the stall check:

zVelocityP <= |yVelocityP| * 4

If this is true, then we are stalling.

* If we have just started stalling (i.e. we weren't already stalling but
we are now), check that we are not too close to the ground (so we check
that yPlaneLo >= 20), and assuming we aren't, apply a roll to the plane
to simulate one of the wings stalling before the other:

zTurn = zTurn +/- (A 0) >> 5

where:

* The +/- sign is the sign of yTurn

* A = xTurnTop EOR #%00111111

* The same routine calculates various aerodynamic forces, as follows:

[ xMoments ] = [ yVelocityP * 2 - xTurn * 250 / 256 ]
[ yMoments ] = [ xVelocityP * 2 - yTurn * 250 / 256 ] * maxv *
[ zMoments ] = [            -zTurn * 2              ]       airDensity

[ xLiftDrag ] = [ xVelocityP * 2 * 4 ]
[ yLiftDrag ] = [ yVelocityP * 2 * 4 ] * maxv * airDensity
[ zLiftDrag ] = [ zVelocityP * 2     ]

zSlipMoment = xLiftDrag

where:

airDensity = ~yPlaneHi * 2

maxv = max(|xVelocityP|, |yVelocityP|, |zVelocityP|)

If zLiftDrag is positive we also do:

yFlapsLift = zLiftDrag

xMoments = xMoments + (zLiftDrag * 8)       when the flaps are off

xMoments - (zLiftDrag * 4)       when the flaps are on

* Call the ApplyFlightControl routine to calculate the effects of the
primary flight controls (elevator, rudder and ailerons), as follows:

xControls = zLiftDrag * elevatorPosition  (pitch)

yControls = zLiftDrag * rudderPosition    (yaw)

zControls = zLiftDrag * aileronPosition   (roll)

This routine also implements the "instant centre" feature.

* Call the ScaleFlightForces routine to scale all the flight forces by the
relevant force and scale factors, as follows:

scaledForce = unscaledForce * forceFactor * 2 ^ scaleFactor

where the 11 forces are:

* (xLiftDrag, yLiftDrag, zLiftDrag)
* (xMoments, yMoments, zMoments)
* zSlipMoment
* yFlapsLift
* (xControls, yControls, zControls)

The scaled results are stored in xMomentsSc, xLiftDragSc and so on.

\ We now rotate (xVelocity, yVelocity, zVelocity), using
\ matrix 1, into (xVelocityP, yVelocityP, zVelocityP)
\
\ In other words, the following code takes the plane's
\ velocity vector in (xVelocity, yVelocity, zVelocity),
\ rotates it by the plane's orientation and stores the
\ result in the (xVelocityP, yVelocityP, zVelocityP)
\ vector
\
\ The (xVelocity, yVelocity, zVelocity) vector is the
\ velocity of the plane with respect to the outside
\ world, so yVelocity is the vertical speed of the plane
\ (as shown on the vertical speed indicator), which is
\ unaffected by how the plane is orientated (a plane
\ dropping out of the sky is still dropping out of the
\ sky, even when it's tumbling)
\
\ The (xVelocityP, yVelocityP, zVelocityP) vector is the
\ velocity of the plane with respect to the plane
\ itself, so zVelocityP is the forward speed of the
\ plane from the point of view of the pilot - it's the
\ speed of the air rushing past us as we fly, so this is
\ the speed we show on the airspeed indicator
\
\ The following code calculates the latter from the
\ former by setting point 255 to the speed vector,
\ rotating it by the plane's orientation angles, and
\ storing the result in the velocity vector

LDX #LO(xVelocityHi)   \ Set X so the call to CopyWorkToPoint copies the
\ coordinates from (xVelocity, yVelocity, zVelocity)

LDY #255               \ Set Y so the call to CopyWorkToPoint copies the
\ coordinates to point 255

STY GG                 \ Set GG to point ID 255, to pass to the call to
\ SetPointCoords

JSR CopyWorkToPoint    \ Copy the coordinates from (xVelocity, yVelocity,
\ zVelocity) to point 255

LDA #0                 \ Set the matrix number so the call to SetPointCoords
STA matrixNumber       \ uses matrix 1 in the calculation, which will rotate
\ the point by the plane's pitch, roll and yaw angles,
\ transforming it from the outside world's frame of
\ reference to the plane's frame of reference

JSR SetPointCoords     \ Calculate the coordinates for point 255

LDX #LO(xVelocityPLo)  \ Set X so the call to CopyPointToWork copies the
\ coordinates to (xVelocityP, yVelocityP, zVelocityP)

LDY #255               \ Set Y so the call to CopyPointToWork copies the
\ coordinates from point 255

JSR CopyPointToWork    \ Copy the coordinates from point 255 to
\ (xVelocityP, yVelocityP, zVelocityP)

JSR ApplyAerodynamics  \ Check for stalling and calculate various aerodynamic
\ forces

JSR ApplyFlightControl \ Calculate the effects of the primary flight controls
\ (elevator, rudder and ailerons), and implement the
\ "instant centre" feature

JSR ScaleFlightForces  \ Scale all the flight forces by the relevant force
\ and scale factors
```