.bcar8 LDA #4 \ Set A = 4, to use as the object type for the car (we \ start with the object type of the standard car, and \ change this later if required) JSR GetObjectAngles-2 \ Calculate the object's yaw and pitch angles, using the \ coordinates in xCoord2, and set the object's \ visibility, scale and type LDX thisDriver \ Set X = thisDriver (driver number of car we are \ driving) LDA objectDistanceHi \ Set A to the high byte of the distance of the object CMP #3 \ If A >= 3, then the car is not close enough to be the BCS bcar11 \ four-object car, so jump to bcar11 to check whether it \ should be built as a distant car object \ If we get here then A <= 2, so the car is close enough \ to consider building as a four-object car LDA thisPosition \ If the car we are building is not the car just ahead CMP positionAhead \ of us in the race, then it can't be the four-object BNE bcar10 \ car, so jump to bcar10 to return from the subroutine \ with the car built as a standard car LDA objectStatus,X \ If bit 7 of the car's object status byte is set, then BMI bcar9 \ the car is not visible, so jump to bcar9 to skip the \ following instruction (which leaves the car object as \ a standard car, but still builds the other three car \ objects) \ If we get here then the car we are building is the \ nearest car in front of us, it's close and it is \ visible, so we draw this car as the four-object car DEC objectStatus,X \ The object type is stored in bits 0-3 of objectStatus, \ so this decrements the car's object type from 4 (the \ standard car) to 3 (the rear wing in the four-object \ car) .bcar9 LDY vectorNumber \ Set Y to the segment vector number that we stored \ above JSR GetSegmentVector \ Fetch the inner segment vector for the part of the \ track that the car is on: \ \ [ (SS T) ] [ xTrackSegmentI ] \ [ (TT U) ] = [ yTrackSegmentI ] \ [ (UU V) ] [ yTrackSegmentI ] \ \ So this contains the direction of the track where the \ car is JSR HalveCoordinate \ Halve the coordinate in (SS T), (TT U) and (UU V) LDY #&FD \ Set Y = &FD so the call to AddVectors uses xCoord2 LDX #&FA \ Set X = &FA so the call to AddVectors uses xCoord1 JSR AddVectors \ Set: \ \ [ (SS T) ] \ xCoord1 = xCoord2 + [ (TT U) ] / 2 \ [ (UU V) ] \ \ So xCoord1 contains the 3D coordinates of the front \ tyres of the four-object car JSR HalveCoordinate \ Halve the coordinate in (SS T), (TT U) and (UU V) LDX #&F4 \ Set X = &F4 so the call to AddVectors uses \ xHelmetCoord JSR AddVectors \ Set: \ \ [ (SS T) ] \ xHelmetCoord = xCoord2 + [ (TT U) ] / 4 \ [ (UU V) ] \ \ So xHelmetCoord contains the 3D coordinates of the \ helmet and body of the four-object car JSR HalveCoordinate \ Halve the coordinate in (SS T), (TT U) and (UU V) LDX #&FD \ Set X = &FD so the call to AddVectors uses xCoord2 JSR AddVectors \ Set: \ \ [ (SS T) ] \ xCoord2 = xCoord2 + [ (TT U) ] / 8 \ [ (UU V) ] \ \ So xCoord2 contains the 3D coordinates of the rear \ tyres of the four-object car \ Now that we have the 3D coordinates of the extra three \ parts of the four-object car, we can calculate the \ object's yaw and pitch angles, and store the details \ in objects 20, 21 and 22 (for the rear tyres, \ body/helmet and front tyres respectively) LDA #20 \ Set objectNumber = 20, to use as then object number STA objectNumber \ for the rear tyres in the four-object car LDA #2 \ Set A = 2, to use as the object type for the rear \ tyres in the four-object car JSR GetObjectAngles-2 \ Calculate the object's yaw and pitch angles, using the \ coordinates of the rear tyres in xCoord2, and set the \ object's visibility, scale and type LDA #21 \ Set objectNumber = 21, to use as then object number STA objectNumber \ for the body and helmet in the four-object car LDA #1 \ Set A = 1, to use as the object type for the body and \ helmet in the four-object car LDX #&F4 \ Set X = &F4 so the call to GetObjectAngles uses \ xHelmetCoord JSR GetObjectAngles \ Calculate the object's yaw and pitch angles, using the \ coordinates of the body and helmet in xHelmetCoord, \ and set the object's visibility, scale and type LDA #22 \ Set objectNumber = 22, to use as then object number STA objectNumber \ for the front tyres in the four-object car LDA #0 \ Set A = 0, to use as the object type for the rear \ tyres in the four-object car LDX #&FA \ Set X = &FA so the call to GetObjectAngles uses \ xCoord1 JSR GetObjectAngles \ Calculate the object's yaw and pitch angles, using the \ coordinates of the front tyres using xCoord1, and set \ the object's visibility, scale and type .bcar10 LDX thisDriver \ Set X to the driver number that we stored at the start \ of the BuildVisibleCar routine RTS \ Return from the subroutine .bcar11 \ We jump here when objectDistanceHi >= 3, so we now \ need to check whether the car is far enough away for \ us to change it to a distant car object \ \ We jump here with A set to objectDistanceHi CMP #5 \ If A < 5, i.e. objectDistanceHi = 4, then the car is BCC bcar10 \ close enough to stay as a standard car object, so jump \ to bcar10 to return from the subroutine LDA objectStatus,X \ If bit 7 of the car's object status byte is set, then BMI bcar10 \ the car is not visible, so jump to bcar10 to return \ from the subroutine \ If we get here then objectDistanceHi >= 5 and the car \ is visible, so the car is far enough away to be a \ distant car object INC objectStatus,X \ The object type is stored in bits 0-3 of objectStatus, \ so this increments the car's object type from 4 (the \ standard car) to 5 (the distant car) RTS \ Return from the subroutineName: BuildCarObjects (Part 3 of 3) [Show more] Type: Subroutine Category: 3D objects Summary: Calculate the screen coordinates of all the objects in the specified car Deep dive: Drawing a 3D car from 2D partsContext: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
Now that we have the car's 3D coordinates in xCoord2, we calculate the car's yaw and pitch angles, and use them to create either one car object, or four car objects if this is the four-object car. If this is the four-object car (i.e. the car is directly in front of us, is close enough and is visible), then we calculate the coordinates for the three extra objects as follows: [ xCoord2 ] [ xTrackSegmentI ] Front tyres = [ yCoord2 ] + [ yTrackSegmentI ] / 2 [ zCoord2 ] [ zTrackSegmentI ] [ xCoord2 ] [ xTrackSegmentI ] Body and helmet = [ yCoord2 ] + [ yTrackSegmentI ] / 4 [ zCoord2 ] [ zTrackSegmentI ] [ xCoord2 ] [ xTrackSegmentI ] Rear tyres = [ yCoord2 ] + [ yTrackSegmentI ] / 8 [ zCoord2 ] [ zTrackSegmentI ]
[X]
Subroutine AddVectors (category: Maths (Geometry))
Add two three-axis vectors together
[X]
Subroutine GetObjectAngles (category: 3D objects)
Calculate the object's yaw and pitch angles, and set the object's visibility, scale and type
[X]
Entry point GetObjectAngles-2 in subroutine GetObjectAngles (category: 3D objects)
Use xCoord2 for the object's 3D coordinates in the call to GetObjYawAngle
[X]
Subroutine GetSegmentVector (category: Track geometry)
Fetch a segment vector from the track data file
[X]
Subroutine HalveCoordinate (category: Maths (Geometry))
Halve a coordinate with three 16-bit axes
[X]
Label bcar10 is local to this routine
[X]
Label bcar11 is local to this routine
[X]
Label bcar9 is local to this routine
[X]
Variable objectDistanceHi in workspace Zero page
The high byte of the distance to the current object
[X]
Variable objectNumber in workspace Zero page
The object number of the four-part car we are drawing
[X]
Variable objectStatus in workspace Stack variables
Various status flags for each object
[X]
Variable positionAhead in workspace Zero page
The number of the position ahead of the current player's position
[X]
Variable thisDriver in workspace Zero page
The number of the car we are currently drawing
[X]
Variable thisPosition in workspace Zero page
The position of the car that we are analysing in the MoveAndDrawCars routine
[X]
Variable vectorNumber in workspace Zero page
The segment vector number when building car objects in the BuildCarObjects routine