# Track geometry: GetSegmentAngles (Part 1 of 3)

```       Name: GetSegmentAngles (Part 1 of 3)                          [Show more]
Type: Subroutine
Category: Track geometry
Summary: Get the yaw and pitch angles for the inner or outer track segments
Deep dive: Data structures for the track calculations
The track verges
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* GetTrackAndMarkers calls GetSegmentAngles

This routine works through track segments, starting from distant segments and
working backwards towards the player, calculating the angles and verge data
for each segment as we go, up to a maximum of 16 segments (which is the
capacity of the track segment list).

Arguments:

A                    The index of the first segment to update in the track
segment list, starting at 6 for the first entry in list
of right segments, and 46 for the first entry in the
list of left segments

X                    The offset from xSegmentCoordILo of the segment's 3D
coordinates, i.e. the segment number * 3, with:

* X for inner track segment coordinates

* X + 120 for outer track segment coordinates

segmentOffset        The offset to use for this segment:

* 0 when our car is facing in the same direction

* 120 when our car is facing the opposite direction

segmentDirection     The relative direction of our car:

* 0 when our car is facing in the same direction

* 1 when our car is facing the opposite direction

Returns:

xVergeRight          Updated yaw angles for the entries in the track segment
list (i.e. indexes 6 to 21) for the right verge

yVergeLeft           Updated pitch angles for the entries in the track
segment list (i.e. indexes 6 to 21) for the left verge

edgeDistance         The distance between the player's car and the nearest
track edge

edgeSegmentNumber    The number of the segment within the track segment list
that is closest to the player's car

edgeSegmentPointer   The index of the segment within track verge buffer that
is closest to the player's car

edgeYawAngle         The yaw angle of the segment that is closest to the
player's car

xVergeRight          Entries in the second part of the track segment list for
the coordinates of the outside of the right track verge
(i.e. indexes 22 to 37, which correspond to the yaw
angles in the track segment list in indexes 6 to 21)

xVergeLeft           Entries in the second part of the track segment list for
the coordinates of the outside of the left track verge
(i.e. indexes 22 to 37, which correspond to the yaw
angles in the track segment list in indexes 6 to 21)

yVergeRight          Pitch angles for the entries in the track segment
list (i.e. indexes 6 to 21) for the right verge

yVergeLeft           Pitch angles for the entries in the track segment
list (i.e. indexes 6 to 21) for the left verge

xMarker              Distance in the x-axis between the track edge and the
corner marker for this segment (if there is one)

vergeDataRight       Data (such as colour) for this segment's right verge

vergeDataLeft        Data (such as colour) for this segment's left verge

.GetSegmentAngles

STA segmentListPointer \ Set segmentListPointer to the index passed in A

LDA #0                 \ Set segmentCounter = 0, to use to count visible
STA segmentCounter     \ segments over the course of the following routine

\ We now run the rest of the routine for each segment
\ in turn, looping back to here while segments are
\ visible

.gseg1

JSR GetSegmentYawAngle \ Calculate the yaw angle and distance between the
\ player's car and the track segment specified in X, and
\ store the results in the track segment list at the
\ segment list pointer
\
\ Also set (A K) = (L K) = the distance between the car
\ and the track segment

\ We now check to see if this is the closest track
\ segment we've come across in this iteration of the
\ main loop, and if it is, we set a bunch of variables
\ with the details of the track edge

CMP edgeDistanceHi     \ If A < edgeDistanceHi, then we know that (A K) and
BCC gseg2              \ therefore (L K) < (edgeDistanceHi edgeDistanceLo),
\ so jump to gseg2 to set (L K) as the new minimum
\ distance to the verge

BNE gseg3              \ If A <> edgeDistanceHi, i.e. A > edgeDistanceHi,
\ then (L K) > (edgeDistanceHi edgeDistanceLo), so
\ jump to gseg3 as (L K) is not a new minimum verge
\ distance

\ We now compare the high bytes

LDA edgeDistanceLo     \ If edgeDistanceLo < K, then we know that
BCC gseg3              \ gseg3 as (L K) is not a new minimum verge distance

.gseg2

\ If we get here then we know that
\ (L K) <= (edgeDistanceHi edgeDistanceLo), so we now
\ set (L K) as the new minimum distance to the verge,
\ and set a number of variables so we can refer to this
\ nearest track edge in places like the crash routine

LDA L                  \ Set (edgeDistanceHi edgeDistanceLo) = (L K)
STA edgeDistanceHi
LDA K
STA edgeDistanceLo

LDA segmentCounter     \ Set edgeSegmentNumber = segmentCounter
STA edgeSegmentNumber  \
\ So edgeSegmentNumber contains the number of the
\ segment within the track segment list that is closest
\ to the player's car

LDY segmentListPointer \ Set edgeSegmentPointer = segmentListPointer
STY edgeSegmentPointer \
\ So edgeSegmentPointer contains the index of the
\ segment within the track verge buffer (i.e. from
\ xVergeRight) that is closest to the player's car

LDA xVergeRightHi,Y    \ Set edgeYawAngle = the segment's entry in
STA edgeYawAngle       \ xVergeRightHi
\
\ So edgeYawAngle contains the yaw angle of the segment
\ that is closest to the player's car, from the point of
\ view of the car

.gseg3

JSR GetObjPitchAngle-2 \ Calculate the segment's pitch angle, from the
\ point of view of the player, returning it in A and LL
\
\ If the segment is not visible on-screen, the C flag is
\ set, otherwise it will be clear

BCS gseg4              \ If the segment is not visible on-screen, jump to gseg4

BPL gseg10             \ If the pitch angle is positive, jump to gseg10
```