Skip to navigation

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 \ \ Let's call this yawRadians / 2, where yawRadians is \ 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