Revs on the BBC Micro

# Maths (Geometry): GetRotationMatrix (Part 1 of 5)

```       Name: GetRotationMatrix (Part 1 of 5)                         [Show more]
Type: Subroutine
Category: Maths (Geometry)
Summary: Calculate the rotation matrix for rotating the player's yaw angle
into the global 3D coordinate system
Deep dive: The core driving model
Trigonometry
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* ApplyDrivingModel calls GetRotationMatrix

This routine calculates the following:

sinYawAngle = sin(playerYawAngle)
cosYawAngle = cos(playerYawAngle)

We can use these to create a rotation matrix that rotates the yaw angle from
the player's frame of reference into the global 3D coordinate system.

Arguments:

(A X)                Player yaw angle in (playerYawAngleHi playerYawAngleLo)

.GetRotationMatrix

STA J                  \ Set (J T) = (A X)
STX T                  \           = playerYawAngle

JSR GetAngleInRadians  \ Set (U A) to the playerYawAngle, reduced to a quarter
\ circle, converted to radians, and halved
\
\ the reduced player yaw angle in radians

STA G                  \ Set (U G) = (U A) = yawRadians / 2

LDA U                  \ Set (A G) = (U G) = yawRadians / 2

STA H                  \ Set (H G) = (A G) = yawRadians / 2

\ So we now have:
\
\   (H G) = (A G) = (U G) = yawRadians / 2
\
\ This is the angle vector that we now project onto the
\ x- and z-axes of the world 3D coordinate system

LDX #1                 \ Set X = 0 and secondAxis = 1, so we project sin(H G)
STX secondAxis         \ into sinYawAngle and cos(H G) into cosYawAngle
LDX #0

BIT J                  \ If bit 6 of J is clear, then playerYawAngle is in one
BVC rotm1              \ of these ranges:
\
\   * 0 to 63 (%00000000 to %00111111)
\
\   * -128 to -65 (%10000000 to %10111111)
\
\ The degree system in Revs looks like this:
\
\            0
\      -32   |   +32         Overhead view of car
\         \  |  /
\          \ | /             0 = looking straight ahead
\           \|/              +64 = looking sharp right
\   -64 -----+----- +64      -64 = looking sharp left
\           /|\
\          / | \
\         /  |  \
\      -96   |   +96
\           128
\
\ So playerYawAngle is in the top-right or bottom-left
\ quarter in the above diagram
\
\ In both cases we jump to rotm1 to set sinYawAngle and
\ cosYawAngle

\ If we get here then bit 6 of J is set, so
\ playerYawAngle is in one of these ranges:
\
\   * 64 to 127 (%01000000 to %01111111)
\
\   * -64 to -1 (%11000000 to %11111111)
\
\ So playerYawAngle is in the bottom-right or top-left
\ quarter in the above diagram
\
\ In both cases we set the variables the other way
\ round, as the triangle we draw to calculate the angle
\ is the opposite way round (i.e. it's reflected in the
\ x-axis or y-axis)

INX                    \ Set X = 1 and secondAxis = 0, so we project sin(H G)
DEC secondAxis         \ into cosYawAngle and cos(H G) into sinYawAngle

\ We now enter a loop that sets sinYawAngle + X to
\ sin(H G) on the first iteration, and sets
\ sinYawAngle + secondAxis to cos(H G) on the second
\ iteration
\
\ The commentary is for the sin(H G) iteration, see the
\ end of the loop for details of how the second
\ iteration calculates cos(H G) instead

.rotm1

\ If we get here, then we are set up to calculate the
\ following:
\
\   * If playerYawAngle is top-right or bottom-left:
\
\     sinYawAngle = sin(playerYawAngle)
\     cosYawAngle = cos(playerYawAngle)
\
\   * If playerYawAngle is bottom-right or top-left:
\
\     sinYawAngle = cos(playerYawAngle)
\     cosYawAngle = sin(playerYawAngle)
\
\ In each case, the calculation gives us the correct
\ coordinate, as the second set of results uses angles
\ that are "reflected" in the x-axis or y-axis by the
\ capping process in the GetAngleInRadians routine

CMP #122               \ If A < 122, i.e. U < 122 and H < 122, jump to rotm2
BCC rotm2              \ to calculate sin(H G) for smaller angles

BCS rotm3              \ Jump to rotm3 to calculate sin(H G) for larger angles
\ (this BCS is effectively a JMP as we just passed
\ through a BCS)

LDA G                  \ It doesn't look like this code is ever reached, so
CMP #240               \ presumably it's left over from development
BCS rotm3
```