Skip to navigation

Drawing polygons: GetPolygonLines (Part 5 of 6)

Name: GetPolygonLines (Part 5 of 6) [Show more] Type: Subroutine Category: Drawing polygons Summary: Loop through all the edges in the polygon and call the correct routines to process one-byte, two-byte or horizontal edges
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
.gpol9 LDA #0 \ Set yPolygonTop = 0 to record the y-coordinate of the STA yPolygonTop \ top of the polygon, where higher y-coordinates are up \ the screen (so this sets the top of the polygon to the \ bottom of the screen, so we can bump it up as we work \ through the polygon) STA xMaxHorizontal \ Set xMaxHorizontal = 0 so we can use it to keep track \ of the maximum x-coordinates of any polygon edges that \ are horizontal STA horizontalEdges \ Set horizontalEdges = 0 so we can use it to keep track \ of how many polygon edges are horizontal LDA #255 \ Set yPolygonBottom = 255 to record the y-coordinate of STA yPolygonBottom \ the bottom of the polygon, where higher y-coordinates \ are up the screen (so this sets the bottom of the \ polygon to the top of the screen, so we can move it \ down as we work through the polygon) STA xMinHorizontal \ Set xMinHorizontal = 255 so we can use it to keep \ track of the minimum x-coordinates of any polygon \ edges that are horizontal STA drawPolygon \ Set drawPolygon to a non-zero value, so by default the \ polygon will not be drawn, though we will set this to \ zero later if the polygon should be drawn LDY #0 \ We now loop through all the edges of the polygon, so \ set a loop counter in Y to work through all the edges \ of the polygon (three for a triangle, four for a \ quadrilateral) .gpol10 STY polygonEdge \ Store the polygon edge number that we are about to \ process in polygonEdge, so we can retrieve it at the \ end of the loop LDA (drawViewAngles),Y \ Set X to the offset within the drawing tables of the TAX \ Y-th point in the polygon INY \ Set Y to the offset within the drawing tables of the LDA (drawViewAngles),Y \ Y+1-st point in the polygon TAY \ So Y and X are the offsets within the drawing tables \ of the start and end points for the polygon edge that \ we are processing LDA #HI(xPolygonLeft) \ Set xPolygonAddrHi to the high byte of the address of STA xPolygonAddrHi \ the xPolygonLeft table, so this value can be used to \ modify the instructions for storing the polygon line \ x-coordinates as we process them \ \ The default is therefore to store the x-coordinate of \ the left end of the polygon line at xPolygonLeft LDA drawViewPitchLo,Y \ Set (A yEdgeDeltaLo) to the following: SEC \ SBC drawViewPitchLo,X \ drawViewPitch(Hi Lo) for point #Y STA yEdgeDeltaLo \ - drawViewPitch(Hi Lo) for point #X LDA drawViewPitchHi,Y \ SBC drawViewPitchHi,X \ So (A yEdgeDeltaLo) contains the difference in pitch \ angle between the two points, or the delta along the \ y-axis BPL gpol11 \ If the result in (A yEdgeDeltaLo) is positive then \ point #Y is higher than point #X and (A yEdgeDeltaLo) \ already has the correct sign for the absolute value, \ so jump to gpol11 to skip the following \ If we get here then point #X is higher than point #Y, \ so we swap them around STA yEdgeDeltaHi \ Set yEdgeDelta(Hi Lo) = (A yEdgeDeltaLo) INC xPolygonAddrHi \ Increment xPolygonAddrHi to HI(xPolygonRight), so when \ we modify the instructions for storing the polygon \ line x-coordinates, they are stored in the table for \ the right end of the polygon line at xPolygonRight STX T \ Swap X and Y around, so point #Y is now higher than STY U \ point #X LDX U LDY T LDA #0 \ Set (A yEdgeDeltaLo) = -yEdgeDelta(Hi Lo) SEC \ SBC yEdgeDeltaLo \ So yEdgeDelta(Hi Lo) is now positive STA yEdgeDeltaLo LDA #0 SBC yEdgeDeltaHi .gpol11 STA yEdgeDeltaHi \ Set yEdgeDelta(Hi Lo) = (A yEdgeDeltaLo) \ \ So point #Y is higher than point #X, and we have a \ positive value in yEdgeDelta(Hi Lo) that contains the \ y-axis delta between the two points \ \ Also, xPolygonAddrHi points to the correct table for \ storing the polygon line (left or right) BIT xPolygonPointScale \ If bit 6 of xPolygonPointScale is clear then the pixel BVC gpol13 \ x-coordinates of all the polygon points fit into \ single-byte numbers, so jump to gpol13 to process the \ edge accordingly LDA xPolygonPointHi,Y \ If both of the high bytes for point #X and point #Y ORA xPolygonPointHi,X \ are zero then the x-coordinates for these particular BEQ gpol13 \ points happen to fit into single-byte numbers, so \ jump to gpol13 to process the edge accordingly LDA yEdgeDeltaHi \ If yEdgeDeltaHi is non-zero then the y-axis delta is BNE gpol12 \ non-zero, so jump to part 6 via gpol12 to process the \ edge accordingly LDA yEdgeDeltaLo \ If yEdgeDeltaLo = 0 then we know yEdgeDelta(Hi Lo) BEQ gpol15 \ must be zero as we passed through the BNE above, so \ the polygon edge is horizontal and we jump to gpol15 \ to move on to the next polygon edge .gpol12 JMP gpol22 \ If we get here then: \ \ * The x-coordinates for points #X and #Y are both \ two-byte numbers \ \ * The y-axis delta in yEdgeDelta(Hi Lo) is non-zero \ and positive \ \ So we jump to part 6 to process this edge accordingly .gpol13 \ If we get here then the x-coordinates for points #X \ and #Y fit into single-byte numbers LDA yEdgeDeltaHi \ If yEdgeDeltaHi is zero then the y-axis delta also BEQ gpol14 \ fits into a single-byte number, so jump to gpol14 LDA #0 \ Zero the high bytes for both points' x-coordinates, STA xPolygonPointHi,Y \ because we are about to process the edge using STA xPolygonPointHi,X \ two-byte calculations, and the high bytes don't get \ written when the x-coordinates of all the polygon \ points fit into single-byte numbers \ \ So this just ensures that the high bytes are correctly \ set up so we can use the value of xPolygonPoint(Hi Lo) \ in the calculations and get the correct x-coordinate \ values JMP gpol22 \ If we get here then: \ \ * The x-coordinates for points #X and #Y are both \ single-byte numbers \ \ * The x-coordinates for points #X and #Y have had \ their high bytes zeroed so they can be used as \ two-byte numbers \ \ * The y-axis delta in yEdgeDelta(Hi Lo) is a \ two-byte number that is non-zero and positive \ \ So we jump to part 6 to process this edge accordingly .gpol14 \ If we get here then: \ \ * The x-coordinates for points #X and #Y are both \ single-byte numbers \ \ * The y-axis delta in yEdgeDelta(Hi Lo) is a \ single-byte number and is therefore equal to \ yEdgeDeltaLo LDA yEdgeDeltaLo \ If yEdgeDeltaLo = 0 then yEdgeDelta(Hi Lo) = 0, so BEQ gpol19 \ jump to gpol19 to process this \ We now set up the start and end points so that the \ edge is either horizontal or slopes downwards when \ moving from the start to the end, as that's what the \ TracePolygonEdge routine expects \ \ We know that point #Y is higher than point #X as we \ set that up above, so we trace along the line from \ the start at point #Y to the end at point #X LDA drawViewPitchHi,Y \ Set yEdgeStart(Hi Lo) = drawViewPitch(Hi Lo) STA yEdgeStartHi \ LDA drawViewPitchLo,Y \ So this sets the y-coordinate of the start point in STA yEdgeStartLo \ point #Y (the lower point) LDA drawViewPitchHi,X \ Set yEdgeEnd(Hi Lo) = drawViewPitch(Hi Lo) STA yEdgeEndHi \ LDA drawViewPitchLo,X \ So this sets the y-coordinate of the end point in STA yEdgeEndLo \ point #X (the higher point) LDA xPolygonPointLo,Y \ Set xEdgeStart(Hi Lo) = (0 xPolygonPointLo) STA xEdgeStartLo \ \ So this sets the x-coordinate of the start point in \ point #Y (the lower point), starting with the low \ bytes LDA xPolygonPointLo,X \ Set xEdgeEnd(Hi Lo) = (0 xPolygonPointLo) STA xEdgeEndLo \ \ So this sets the x-coordinate of the start point in \ point #Y (the lower point), starting with the low \ bytes LDA #0 \ Zero the high bytes of xEdgeStart(Hi Lo) and STA xEdgeStartHi \ xEdgeEnd(Hi Lo) STA xEdgeEndHi JSR TracePolygonEdge \ Trace the polygon edge, populating the xPolygonRight \ or xPolygonLeft table with the x-coordinate of the \ edge for each y-coordinate .gpol15 \ We now move on to the next edge in the polygon LDY polygonEdge \ Set Y to the number of the polygon edge that we have \ been processing INY \ Increment Y to move on to the next edge in the polygon CPY polygonEdgeCount \ If we have processed all the edges in the polygon then BEQ gpol16 \ jump to gpol16 to keep going JMP gpol10 \ Otherwise loop back to gpol10 to process the next edge \ in the polygon .gpol16 \ We have processed all the edges in the polygon, so now \ we work out whether the polygon is visible in the \ current screen buffer LDA horizontalEdges \ If horizontalEdges does not match polygonEdgeCount CMP polygonEdgeCount \ then not every edge in the polygon was horizontal, so BNE gpol17 \ jump to gpol17 to skip the following \ If we get here then every edge in the polygon is \ horizontal, so the entire polygon appears within a \ single horizontal line LDA drawViewPitchHi,X \ If the high byte of the view-relative pitch angle for BNE gpol17 \ point #X is non-zero then point #X is definitely not \ on-screen, and so neither is the horizontal line, so \ jump to gpol17 to skip the following LDY drawViewPitchLo,X \ Set Y to the low byte of the view-relative pitch angle \ for point #X (and therefore the pitch angle for the \ horizontal line) CPY minPitchAngle \ If Y < minPitchAngle then the line is not within the BCC gpol17 \ screen buffer as the pitch angle is below the minimum \ value in the buffer, so jump to gpol17 to skip the \ following CPY maxPitchAngle \ If Y >= maxPitchAngle hen the line is not within the BCS gpol17 \ screen buffer as the pitch angle is above the maximum \ value in the buffer, so jump to gpol17 to skip the \ following \ If we get here then the polygon is a single horizontal \ line and it appears within the screen buffer, so we \ configure the result to return a single polygon line \ with the y-coordinate of single horizontal line, and \ with the maximum and minimum x-coordinates that we \ have been calculating in xMinHorizontal and \ xMaxHorizontal STY yPolygonBottom \ Set both the top and bottom polygon y-coordinates to STY yPolygonTop \ the low byte of the view-relative pitch angle for \ point #X LDA xMinHorizontal \ Set the left edge of the polygon line to the STA xPolygonLeft,Y \ x-coordinate in xMinHorizontal LDA xMaxHorizontal \ Set the right edge of the polygon line to the STA xPolygonRight,Y \ x-coordinate in xMaxHorizontal LDA #0 \ Set drawPolygon = 0 so the polygon gets drawn STA drawPolygon .gpol17 LDA drawPolygon \ If drawPolygon is non-zero then the polygon should not BNE gpol18 \ be drawn, so jump to gpol18 to return from the \ subroutine with the C flag set LDA yPolygonTop \ If yPolygonTop < yPolygonBottom then there are no CMP yPolygonBottom \ visible lines to draw in the polygon, so jump to BCC gpol18 \ gpol18 to return from the subroutine with the C flag \ set CLC \ Clear the C flag to indicate that the polygon is \ visible in the current screen buffer and should be \ drawn RTS \ Return from the subroutine .gpol18 SEC \ Set the C flag to indicate that the polygon is not \ visible in the current screen buffer and should not be \ drawn RTS \ Return from the subroutine .gpol19 \ If we get here then yEdgeDelta(Hi Lo) = 0, so this \ polygon edge is horizontal LDA xPolygonPointLo,X \ Set A = xPolygonPointLo for point #X CMP xMaxHorizontal \ Set xMaxHorizontal = max(xMaxHorizontal, A) BCC gpol20 \ STA xMaxHorizontal \ So xMaxHorizontal keeps track of the maximum \ x-coordinate of all the horizontal polygon edges .gpol20 CMP xMinHorizontal \ Set xMinHorizontal = min(xMinHorizontal, A) BCS gpol21 \ STA xMinHorizontal \ So xMinHorizontal keeps track of the minimum \ x-coordinate of all the horizontal polygon edges .gpol21 INC horizontalEdges \ Increment horizontalEdges so we keep a count of all \ the horizontal polygon edges JMP gpol15 \ Jump to gpol15 to move on to the next polygon edge