.DrawObject JSR GetObjectAngles \ Calculate the angles and distances of the vector from \ the viewer to object #Y and put them into the \ following variables: \ \ * Set objectViewYaw(Hi Lo) to the yaw angle of the \ viewer's gaze towards the object, relative to the \ screen \ \ * Set objectGazeYaw(Hi Lo) to the difference in yaw \ angles between the viewer's gaze towards the \ object and the object's gaze to wherever it is \ looking (so that's the object's gaze relative to \ the viewer's gaze) \ \ * Set hypotenuse(Hi Lo) to the length of the 3D \ vector from the viewer to the object when \ projected down onto the ground plane \ \ * Set objectAdjacent(Hi Lo) to the length of the \ adjacent side in the vertical right-angled \ triangle with the projected vector along the \ bottom and the vector from the viewer to the \ object as the hypotenuse \ \ * Set objectOpposite(Hi Lo) to the length of the \ opposite side in the vertical right-angled \ triangle with the projected vector along the \ bottom and the vector from the viewer to the \ object as the hypotenuse \ \ Note that hypotenuse(Hi Lo) and objectAdjacent(Hi Lo) \ are the same value, as the hypotenuse of the ground \ plane triangle is the same as the adjacent side of the \ vertical triangle \ \ This also sets objectToAnalyse to the number of the \ object that we are drawing LDA hypotenuseHi \ If hypotenuseHi (i.e. objectAdjacentHi) is greater or CMP #15 \ equal to 15 then the object is a fair distance away ROR blendPolygonEdges \ from the viewer along the z-axis, so set bit 7 of \ blendPolygonEdges so we draw the polygon edges in the \ same colour as the polygon body (i.e. the fill \ colour), so the edges blend into the body \ \ We do this for distant objects because distinct edge \ colours can make those object look messy JSR GetObjPointAngles \ Calculate the view-relative pitch and yaw angles of \ all the points in the object and put them into the \ drawing tables at: \ \ drawViewYaw(Hi Lo) \ \ drawViewPitch(Hi Lo) \ \ We can use these as screen x- and y-coordinates, using \ the same screen projection that is used in Revs LDA #%01000000 \ Clear bit 7 and set bit 6 of polygonType so the call STA polygonType \ to DrawPolygon below draws the correct type of polygon \ for being part of an object LDA #0 \ Set drawingPhaseCount = 0, so the default is to draw STA drawingPhaseCount \ the object in one phase (we may change this later if \ the object needs to be drawn in two phases) STA drawingPhase \ Clear bit 7 of drawingPhase so for objects that need \ two drawing phases, we start by drawing the first \ phase (as the current phase is determined by bit 7) LDX objTypeToAnalyse \ Set X to the number of the object we are drawing LDA objPolygonPhases,X \ Set A to the phase data for the object we are drawing, \ which helps determine the number of drawing phases BEQ drob4 \ If A = 0 then this object only has one drawing phase, \ so jump to drob4 to move on to drawing the object \ (this applies to the tree, the boulder, the Sentinel's \ tower and the 3D text blocks) \ If we get here then bit 1 of A must be set, as the \ only values used in the objPolygonPhases table are \ %00, %10 and %11 LSR A \ If bit 0 of A is set then this object might need two BCS drob1 \ drawing phases, so jump to drob1 to work out how many \ phases are required by checking the relative altitude \ of the object (this applies to the robot, the sentry \ and the Sentinel) \ If we get here then bit 0 of A is clear and bit 1 is \ set, so we need to work out how many phases are \ required by checking whether or not the object is \ facing the viewer as given in the object's yaw angle \ (this applies to the meanie only) LDA objectGazeYawHi \ Set A to the object's gaze yaw angle + 192, to turn it ADC #192 \ anticlockwise (left) through 90 degrees for the phase \ calculation (the addition works because the C flag is \ clear, as we just passed through a BCS) JMP drob3 \ Jump to drob3 to set drawingPhaseCount to 0 or 2, \ depending on the direction in which the meanie is now \ facing: \ \ * 0 = one phase if the meanie's gaze yaw angle is \ positive after the rotation, which means it must \ be facing towards the viewer (so we leave \ drawingPhaseCount = 0) \ \ * 2 = two phases if the meanie's gaze yaw angle is \ negative after the rotation, which means it must \ be facing away from the viewer (so we set the \ drawingPhaseCount = 2) .drob1 \ If we get here then we are drawing a robot, a sentry \ or the Sentinel, so we need to work out how many \ drawing phases are required LDA objectOppositeHi \ If objectOpposite(Hi Lo) has a non-zero high byte, BNE drob2 \ then jump to drob2 to: \ \ * Draw the object in two phases if objectOppositeHi \ is positive (i.e. the object is reasonably far \ above the viewer) \ \ * Draw the object in one phase if objectOppositeHi \ is negative (i.e. the object is below the viewer) LDA objectOppositeLo \ If objectOpposite(Hi Lo) = 0 then the object is at the BEQ drob4 \ same height as the viewer, so jump to drob4 to draw \ the object in one phase (by leaving drawingPhaseCount \ set to 0) \ If we get here then objectOppositeHi is zero but \ objectOppositeLo is non-zero, so the object is only a \ little bit above the viewer and we draw the object in \ two phases (so now we set drawingPhaseCount = 2) LSR A \ Clear bit 7 of A, so the following EOR instruction \ will set bit 7, so we pass through the BPL instruction \ and set drawingPhaseCount = 2 before falling through \ into drob4 to do the actual drawing .drob2 EOR #%10000000 \ Flip bit 7 of A, which will contain objectOppositeHi \ if we jumped here from the BNE above .drob3 BPL drob4 \ If we jumped here because we are drawing a meanie, \ then this jumps to drob4 if the updated object's gaze \ yaw angle is positive \ \ If we fell through from drob2, then this jumps to \ drob4 if bit 7 of objectOppositeHi is set, i.e. if \ objectOpposite(Hi Lo) is negative \ If we get here then one of these is true: \ \ * We are drawing a meanie and it is facing away from \ the viewer \ \ * We are drawing a robot, a sentry or the Sentinel \ and one of these is true: \ \ * objectOpposite(Hi Lo) is positive and \ objectOppositeHi > 0 (so the object is \ reasonably far above the viewer) \ \ * objectOppositeHi is zero and objectOppositeLo is \ non-zero (so the object is a little bit above \ the viewer) \ \ In other words we are drawing a robot, a sentry or \ the Sentinel and the object is above the viewer LDA #2 \ Set drawingPhaseCount = 2 so we draw the object in two STA drawingPhaseCount \ phases .drob4 LDX objTypeToAnalyse \ Set X to the number of the object we are drawing LDA objPolygonRange+1,X \ Set objectLastPolygon to entry X + 1 from the STA objectLastPolygon \ table at objPolygonRange, so this now contains the \ number of the first polygon for the next object, \ object #X + 1, which is one greater than the last \ polygon number for object #X, as the lists of \ object polygons are sequential (so object #0's \ polygons are first in the object data tables, then \ object #1's polygons, and so on) LDY objPolygonRange,X \ Set Y to entry X from the table at objPolygonRange, so \ so this now contains the number of the first polygon \ for object #X \ \ This means that in the following loop, we start the \ drawing process with the first polygon for object #X .drob5 STY polygonNumber \ Set polygonNumber to Y, so we start from the first \ polygon and work through them in order LDA objPolygonData,Y \ Set A to the polygon data byte for the polygon we are \ drawing LDX drawingPhaseCount \ If drawingPhaseCount = 0 then jump to drob6 to skip BEQ drob6 \ the following, as there is only one drawing phase for \ this object EOR drawingPhase \ If bit 7 of the polygon data byte does not match bit 7 BMI drob7 \ of drawingPhase, then we do not draw this polygon in \ this phase, so jump to drob7 to skip drawing the \ polygon and move on to the next one \ If we get here then bit 7 of the polygon data byte \ matches the phase we are currently drawing, so we draw \ the polygon .drob6 AND #%00111100 \ Extract bits 2 to 5 from the polygon data byte to get STA polygonColours \ the polygon's edge and fill colours, and put them into \ polygonColours LDA objPolygonData,Y \ Set A to the polygon data byte for the polygon we are \ drawing AND #%00000011 \ Extract bits 0 to 1 from the polygon data byte to get CLC \ the number of sides in the polygon (where 0 means ADC #3 \ three sides and 1 means four sides) STA polygonEdgeCount \ \ Then add 3 to get the number of sides in the polygon, \ (three for a triangle or four for a quadrilateral) \ and store the result in polygonEdgeCount LDA objPolygonAddrLo,Y \ Set drawViewAngles(1 0) to the address of the list of STA drawViewAngles \ object-relative point numbers for this polygon so the LDA objPolygonAddrHi,Y \ DrawPolygon routine can use the yaw and pitch angles STA drawViewAngles+1 \ that we calculated for the object points in the \ GetObjPointAngles routine JSR DrawPolygon \ Draw the polygon LDY polygonNumber \ Set Y to the polygon number once again, as the call \ to DrawPolygon will have corrupted it .drob7 INY \ Increment the polygon number in Y CPY objectLastPolygon \ If we have not yet reached the end of the list, loop BCC drob5 \ back to drob5 to draw the next polygon, until we have \ processed all the polygons in the object DEC drawingPhaseCount \ Decrement the drawing phase counter BMI drob8 \ If drawingPhaseCount was zero before being decremented \ then there is only one drawing phase, so jump to drob8 \ to finish up BEQ drob8 \ If drawingPhaseCount was 1 before being decremented \ then there are two drawing phases and we have just \ finished drawing the second phase, so jump to drob8 to \ finish up \ If we get here then drawingPhaseCount was 2 before \ being decremented, so this is a two-phase object and \ we have only drawn the first phase, so now we draw the \ second phase LDA #%10000000 \ Set bit 7 of drawingPhase so we now draw the second STA drawingPhase \ phase BMI drob4 \ Jump back to drob4 to draw the second phase for the \ two-phase object .drob8 LDA #LO(polygonPoint) \ Set drawViewAngles(1 0) = polygonPoint STA drawViewAngles \ LDA #HI(polygonPoint) \ This resets drawViewAngles(1 0) so DrawPolygon will STA drawViewAngles+1 \ return to the default behaviour of drawing using point \ data for tile faces rather than object polygons LSR blendPolygonEdges \ Clear bit 7 of blendPolygonEdges so we return to the \ default setting of allowing drawing polygon edges to \ be a different colour to the polygon fill LDY objectToAnalyse \ Set Y to the number of the object we just drew, so it \ is preserved RTS \ Return from the subroutineName: DrawObject [Show more] Type: Subroutine Category: Drawing objects Summary: Draw a 3D objectContext: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawObjectStack calls DrawObject * DrawTileAndObjects calls DrawObject * DrawTitleObject calls DrawObject * DrawUpdatedObject calls DrawObject
Arguments: Y The number of the object to be drawn
Returns: Y Y is preserved
[X]
Subroutine DrawPolygon (category: Drawing polygons)
Draw a polygon
[X]
Subroutine GetObjPointAngles (category: Drawing objects)
Calculate the view-relative pitch and yaw angles of all the points in an object
[X]
Subroutine GetObjectAngles (category: 3D objects)
Calculate the angles and distances of the vector from the viewer to a specific object
[X]
Variable blendPolygonEdges in workspace Main variable workspace
A flag to determine whether polygon edges are drawn in the same colour as the polygon fill, thus blending the edges into the polygon body
[X]
Variable drawViewAngles in workspace Zero page
The address in drawViewAngles(1 0) of the pitch and yaw angles of the tile and polygon points that we are drawing in the landscape view
[X]
Variable drawingPhase in workspace Main variable workspace
The number of the current drawing phase when drawing two-phase objects
[X]
Variable drawingPhaseCount in workspace Zero page
A phase counter for objects that need to be drawn in multiple phases
[X]
Label drob1 is local to this routine
[X]
Label drob2 is local to this routine
[X]
Label drob3 is local to this routine
[X]
Label drob4 is local to this routine
[X]
Label drob5 is local to this routine
[X]
Label drob6 is local to this routine
[X]
Label drob7 is local to this routine
[X]
Label drob8 is local to this routine
[X]
Variable hypotenuseHi in workspace Zero page
The high byte of the hypotenuse of a triangle
[X]
Variable objPolygonAddrHi (category: Drawing objects)
Addresses for the list of polygons and points for each object (high byte)
[X]
Variable objPolygonAddrLo (category: Drawing objects)
Addresses for the list of polygons and points for each object (low byte)
[X]
Variable objPolygonData (category: Drawing objects)
Various data for object polygons (colour, drawing phase)
[X]
Variable objPolygonPhases (category: Drawing objects)
The phase configuration for each object
[X]
Variable objPolygonRange (category: Drawing objects)
The first and last polygon numbers for each object
[X]
Variable objTypeToAnalyse in workspace Zero page
The type of the object being analysed in the GetObjectAngles routine
[X]
Variable objectGazeYawHi in workspace Zero page
The difference in the yaw angle of the viewer's gaze and the yaw angle (i.e. the gaze) of the object being analysed (low byte)
[X]
Variable objectLastPolygon in workspace Zero page
The number of the last polygon in the object being drawn
[X]
Variable objectOppositeHi in workspace Main variable workspace
The height of an object relative to the viewer, expressed as the length of the opposite side in a triangle with the vector from the viewer to the object as the hypotenuse (high byte)
[X]
Variable objectOppositeLo in workspace Main variable workspace
The height of an object relative to the viewer, expressed as the length of the opposite side in a triangle with the vector from the viewer to the object as the hypotenuse (low byte)
[X]
Variable objectToAnalyse in workspace Zero page
The number of the object to analyse in the GetObjectAngles routine
[X]
Variable polygonColours in workspace Zero page
The colours of the polygon that's being drawn in the DrawPolygon routine
[X]
Variable polygonEdgeCount in workspace Zero page
The number of sides in the polygon we are drawing, which is one less than the number of points in the polygon's point list (as the last point in the list is always a repeat of the first point)
[X]
Variable polygonNumber in workspace Zero page
A counter for the polygon number as we work through the polygons in an object when drawing the object
[X]
Variable polygonPoint in workspace Main variable workspace
Up to five coordinates for the points of the polygon being drawn
[X]
Variable polygonType in workspace Zero page
Bits 6 and 7 determine the type of polygon to draw in the DrawPolygon routine (the calling subroutine is in brackets)