Skip to navigation


3D objects: GetObjYawAngle (Part 1 of 4)

Name: GetObjYawAngle (Part 1 of 4) [Show more] Type: Subroutine Category: 3D objects Summary: Calculate an object's yaw angle Deep dive: Pitch and yaw angles
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * BuildRoadSign calls GetObjYawAngle * GetObjectAngles calls via GetObjYawAngle-2 * GetSectionAngles (Part 3 of 3) calls via GetObjYawAngle-2 * GetSegmentYawAngle calls via GetObjYawAngle-2

Arguments: X The offset of the variable to use for the object's 3D coordinates * &F4 = xHelmetCoord * &FA = xCoord1 * &FD = xCoord2 Y The offset of the second variable to use: * 0 = xPlayerCoord * 6 = xRoadSignCoord
Returns: (JJ II) The yaw angle of the object (J I) max(|x-delta|, |z-delta|) (H G) min(|x-delta|, |z-delta|) M The smaller yaw angle of the object, where 0 to 255 represents 0 to 45 degrees X X is preserved
Other entry points: GetObjYawAngle-2 Use xPlayerCoord (Y = 0)
LDY #0 \ Use xPlayerCoord for the second variable when calling \ the routine via GetObjYawAngle-2 .GetObjYawAngle \ The vectors used in this routine are configured by the \ values of X and Y, but for the purposes of simplicity, \ the comments will assume the following: \ \ * X = &FD, xCoord2 \ \ * Y = 0, xPlayerCoord LDA xSegmentCoordILo,X \ Set (VV PP) = xCoord2 - xPlayerCoord SEC \ SBC xPlayerCoordHi,Y \ starting with the low bytes STA PP LDA xSegmentCoordIHi,X \ And then the high bytes SBC xPlayerCoordTop,Y STA VV \ Let's call this difference in x-coordinates x-delta, \ so: \ \ (VV PP) = x-delta BPL rotn1 \ If (VV PP) is positive, jump to rotn1 to skip the \ following LDA #0 \ Set (VV PP) = 0 - (VV PP) SEC \ SBC PP \ starting with the low bytes STA PP LDA #0 \ And then the high bytes SBC VV \ So (VV PP) is now positive, in other words: \ \ (VV PP) = |x-delta| .rotn1 STA SS \ Set (SS PP) = (VV PP) \ = |x-delta| LDA zSegmentCoordILo,X \ Set (GG RR) = zCoord2 - zPlayerCoord SEC \ SBC zPlayerCoordHi,Y \ starting with the low bytes STA RR LDA zSegmentCoordIHi,X \ And then the high bytes SBC zPlayerCoordTop,Y STA GG \ Let's call this difference in z-coordinates z-delta, \ so: \ \ (GG RR) = z-delta BPL rotn2 \ If (GG RR) is positive, jump to rotn2 to skip the \ following LDA #0 \ Set (GG RR) = 0 - (GG RR) SEC \ SBC RR \ starting with the low bytes STA RR LDA #0 \ And then the high bytes SBC GG \ So (GG RR) is now positive, in other words: \ \ (GG RR) = |z-delta| .rotn2 STA UU \ Set (UU RR) = (GG RR) \ = |z-delta| \ At this point we have the following: \ \ (SS PP) = |x-delta| \ \ (UU RR) = |z-delta| \ \ We now compare these two 16-bit values, starting with \ the high bytes, and then the low bytes (if the high \ bytes are the same) CMP SS \ If UU < SS, then (UU RR) < (SS PP), so jump to rotn3 BCC rotn3 BNE rotn4 \ If UU <> SS, i.e. UU > SS, then (UU RR) > (SS PP), so \ jump to rotn4 with the C flag clear \ The high bytes are equal, so now we compare the low \ bytes LDA RR \ If RR >= PP, then (UU RR) >= (SS PP), so jump to rotn4 CMP PP \ with the C flag set BCS rotn4 \ Otherwise (UU RR) < (SS PP), so fall through into \ rotn3 .rotn3 \ If we get here then (UU RR) < (SS PP), so: \ \ |z-delta| < |x-delta| LDA UU \ Set (H G) = (UU RR) STA H \ = |z-delta| LDA RR \ STA G \ and (H G) contains the smaller value LDA PP \ Set (J I) = (SS PP) STA I \ = |x-delta| LDA SS \ STA J \ and (J I) contains the larger value JMP rotn6 \ Jump to rotn6 .rotn4 \ If we get here then (UU RR) >= (SS PP), so: \ \ |z-delta| >= |x-delta| PHP \ Store the status flags on the stack, and in particular \ the Z flag, which will be set if the two match, \ i.e. if |z-delta| = |x-delta| \ \ In other words, a BEQ would branch with these flags LDA SS \ Set (H G) = (SS PP) STA H \ = |x-delta| LDA PP \ STA G \ and (H G) contains the smaller value LDA RR \ Set (J I) = (UU RR) STA I \ = |z-delta| LDA UU \ STA J \ and (J I) contains the larger value PLP \ Retrieve the status flags we stored above BEQ rotn9 \ If (UU RR) = (SS PP), jump to rotn9 JMP rotn14 \ Jump to rotn14