Skip to navigation

Revs on the BBC Micro

3D objects: GetObjYawAngle (Part 2 of 4)

Name: GetObjYawAngle (Part 2 of 4) [Show more] Type: Subroutine Category: 3D objects Summary: Calculate yaw angle for when |x-delta| > |z-delta| Deep dive: Pitch and yaw angles
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
.rotn5 \ This part is called from below, if we want to scale \ the division ASL RR \ Set (UU RR) = (UU RR) << 1 ROL UU .rotn6 \ If we get here, then: \ \ * (J I) = (A PP) = |x-delta| \ \ * VV is the high byte of x-delta \ \ * (H G) = (UU RR) = |z-delta| \ \ * GG is the high byte of z-delta \ \ * |x-delta| > |z-delta| \ \ We now do the following division so we can use \ trigonometry to calculate the yaw angle: \ \ |z-delta| / |x-delta| \ \ To get started, we shift both 16-bit values to the \ left as far as possible, which we can do without \ affecting the result as we are going to divide the two \ values, so any mutual shifts will cancel each other \ out in the division \ \ Once that's done, we can drop the low bytes and just \ divide the high bytes, which retains as much accuracy \ as possible while avoiding the need for full 16-bit \ division \ \ So we keep shifting left until we get a 1 in bit 7 of \ (A PP), as that's the larger of the two values ASL PP \ Set (A PP) = (A PP) << 1 ROL A BCC rotn5 \ If we just shifted a 0 out of the high byte of (A PP), \ then we can keep shifting, so loop back to rotn6 to \ keep shifting both values ROR A \ We just shifted a 1 out of bit 7 of A, so reverse the \ shift so A contains the correct high byte (we don't \ care about the low byte any more) \ So by this point, (A PP) and (UU RR) have both been \ scaled by the same number of shifts STA V \ Set V = A, the high byte of the scaled |x-delta| LDA RR \ Set T = RR, the low byte of the scaled |z-delta|, to STA T \ use for rounding the result in Divide8x8 LDA UU \ Set A = UU, the high byte of the scaled |z-delta| CMP V \ If A = V then the high bytes of the scaled values BEQ rotn9 \ match, so jump to rotn9, which deals with the case \ when the xVector and zVector values are equal \ We have scaled both values, so now for the division of \ the high bytes JSR Divide8x8 \ Set T = 256 * A / V \ = 256 * |z-delta| / |x-delta| \ \ using the lower byte of the |z-delta| numerator for \ rounding LDA #0 \ Set II = 0 to use as the low byte for the final yaw STA II \ angle LDY T \ Set A = arctanY(T) LDA arctanY,Y \ = arctanY(|z-delta| / |x-delta|) \ \ So this is the yaw angle of the object STA M \ Store the yaw angle in M, to return from the \ subroutine LSR A \ Set (JJ II) = (A 0) >> 3 ROR II \ = A * 256 / 8 LSR A \ = A * 32 ROR II \ = arctanY(|z-delta| / |x-delta|) * 32 LSR A ROR II STA JJ LDA VV \ If VV and GG have different signs, then so do x-delta EOR GG \ and z-delta, so jump to rotn7 BMI rotn7 LDA #0 \ Negate (JJ II) SEC \ SBC II \ starting with the low bytes STA II LDA #0 \ And then the high bytes SBC JJ STA JJ .rotn7 LDA #64 \ Set A = 64, to add to the high byte below BIT VV \ If x-delta is positive, jump to rotn8 to skip the BPL rotn8 \ following instruction \ If we get here then x-delta is negative LDA #&C0 \ Set A = -64, to add to the high byte below .rotn8 CLC \ Set (JJ II) = (JJ II) + (A 0) ADC JJ \ STA JJ \ which is one of the following: \ \ (JJ II) = (JJ II) + 64 * 256 \ \ (JJ II) = (JJ II) - 64 * 256 \ \ depending on the sign of x-delta RTS \ Return from the subroutine