Skip to navigation

Revs on the BBC Micro

3D objects: GetObjYawAngle (Part 4 of 4)

Name: GetObjYawAngle (Part 4 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
.rotn13 \ This part is called from below, if we want to scale \ the division ASL PP \ Set (SS PP) = (SS PP) << 1 ROL SS .rotn14 \ If we get here, then: \ \ * (H G) = (SS PP) = |x-delta| \ \ * VV is the high byte of x-delta \ \ * (J I) = (A 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: \ \ |x-delta| / |z-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 RR), as that's the larger of the two values ASL RR \ Set (A RR) = (A RR) << 1 ROL A BCC rotn13 \ If we just shifted a 0 out of the high byte of (A RR), \ then we can keep shifting, so loop back to rotn13 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 RR) and (SS PP) have both been \ scaled by the same number of shifts STA V \ Set V = A, the high byte of the scaled |z-delta| LDA PP \ Set T = PP, the low byte of the scaled |x-delta|, to STA T \ use for rounding the result in Divide8x8 LDA SS \ Set A = SS, the high byte of the scaled |x-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 * |x-delta| / |z-delta| \ \ using the lower byte of the |x-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(|x-delta| / |z-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(|x-delta| / |z-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 rotn15 BPL rotn15 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 .rotn15 LDA #0 \ Set A = 0, to add to the high byte below BIT GG \ If z-delta is positive, jump to rotn16 to skip the BPL rotn16 \ following instruction \ If we get here then z-delta is negative LDA #&80 \ Set A = -128, to add to the high byte below .rotn16 CLC \ Set (JJ II) = (JJ II) + (A 0) ADC JJ \ STA JJ \ which is one of the following: \ \ (JJ II) = (JJ II) \ \ (JJ II) = (JJ II) - 128 * 256 \ \ depending on the sign of z-delta RTS \ Return from the subroutine