Skip to navigation

Drawing polygons: GetPolygonLines (Part 6 of 6)

Name: GetPolygonLines (Part 6 of 6) [Show more] Type: Subroutine Category: Drawing polygons Summary: Split polygon edges whose coordinates are stored in two-byte numbers into smaller sections for processing
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
.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 a two-byte number, and it is also positive STX pointX \ Store the number of point #X in pointX so we can \ retrieve it below LDA #0 \ Set scaleFactor = 0 so we can use it to record the STA scaleFactor \ scale factor we apply to the x-axis and y-axis deltas \ below when fitting them into single-byte numbers LDA xPolygonPointLo,Y \ Set (A T) to the following: SEC \ SBC xPolygonPointLo,X \ xPolygonPoint(Hi Lo) for point #Y STA T \ - xPolygonPoint(Hi Lo) for point #X LDA xPolygonPointHi,Y \ SBC xPolygonPointHi,X \ So (A T) contains the difference in the x-axis between \ the two polygon points STA xPointDeltaHi \ Store the high byte in xPointDeltaHi so we can test \ the sign below JSR Absolute16Bit \ Set (U T) = |A T| STA U \ \ So by this point we have: \ \ * The absolute x-axis delta in (U T) \ \ * The positive y-axis delta in yEdgeDelta(Hi Lo) ORA yEdgeDeltaHi \ Set A = U OR yEdgeDeltaHi \ \ So the highest set bit in A matches the position of \ the highest set bit across the two high bytes of the \ two deltas BEQ gpol24 \ If both U and yEdgeDeltaHi are zero then both deltas \ fit into one byte (the low byte), so jump to gpol24 \ If we get here then at least one of the deltas does \ not fit into a single byte, so we now scale both of \ the deltas down \ \ We do this by shifting both deltas to the right, and \ at the same time we shift A to the right, repeating \ the process until there are no more set bits in A, by \ which time we will have shifted the deltas by the \ minimum number of shifts required to zero both high \ bytes \ \ We also record the number of shifts in scaleFactor in \ the form of one set bit for each shift .gpol23 LSR yEdgeDeltaHi \ Shift the y-axis delta in yEdgeDelta(Hi Lo) to the ROR yEdgeDeltaLo \ right by one place to scale it down by half LSR U \ Shift the x-axis delta in (U T) to the right by one ROR T \ place to scale it down by half SEC \ Rotate a set bit into bit 0 of scaleFactor, so we ROL scaleFactor \ build up a sequence of set bits in the bottom part \ of scaleFactor that matches the number of shifts, \ effectively giving us the total cumulative scale \ factor of the shifts (in fact scaleFactor will end \ up being the cumulative scale factor minus 1, but \ that's good enough for our needs) LSR A \ Shift A to the right to move the highest set bit \ towards bit 0 BNE gpol23 \ If there is still a set bit in A then at least one of \ the high bytes in the deltas is non-zero, so loop back \ to perform another shift until both high bytes are \ zero .gpol24 \ By this point we have: \ \ * The scaled absolute x-axis delta in T \ \ * The scaled positive y-axis delta in yEdgeDeltaLo \ \ * The scale factor in scaleFactor \ \ We now ensure that bit 7 is clear in both low bytes, \ to make sure the single-byte values are both positive LDX yEdgeDeltaLo \ If yEdgeDeltaLo = 255 then jump back to gpol23 to CPX #255 \ scale both deltas down by one more shift BEQ gpol23 LDX T \ If T = 255 then jump back to gpol23 to scale both CPX #255 \ deltas down by one more shift BEQ gpol23 LDA U \ Set (A T) = (U T) \ \ This effectively sets (A T) to the two-byte value of \ the x-axis delta, though by this point U will always \ be zero BIT xPointDeltaHi \ We set xPointDeltaHi to the high byte of the original \ x-axis delta subtraction, so this sets the N flag \ according to the sign of that calculation JSR Absolute16Bit \ Set the sign of (A T) to that of the N flag argument, \ so (A T) now has the correct sign of the x-axis delta STA xEdgeDeltaHi \ Set xEdgeDelta(Hi Lo) = (A T) LDA T \ STA xEdgeDeltaLo \ So xEdgeDelta(Hi Lo) contains the signed x-axis delta \ By this point we have: \ \ * The scaled signed x-axis delta across the polygon \ edge in xEdgeDelta(Hi Lo) \ \ * The scaled signed y-axis delta across the polygon \ edge in (0 yEdgeDeltaLo), which also happens to be \ positive \ \ * The scale factor in scaleFactor \ We now trace the polygon edge from the starting point \ in point #Y to the end point in point #X \ \ To kick this process off, we set the coordinates in \ xEdgeEnd and yEdgeEnd to those of point #Y, as these \ variables are used to store the "end of the previous \ part of the edge" and are therefore used as the "start \ of the next part of the edge" in the tracing process LDA xPolygonPointLo,Y \ Set xEdgeEnd(Hi Lo) to the x-coordinate of point #Y, STA xEdgeEndLo \ from the x-coordinate tables we populated in parts 3 LDA xPolygonPointHi,Y \ and 4 STA xEdgeEndHi LDA drawViewPitchHi,Y \ Set yEdgeEnd(Hi Lo) to the y-coordinate of point #Y, STA yEdgeEndHi \ taken from the pitch angles of the points in the LDA drawViewPitchLo,Y \ drawing tables STA yEdgeEndLo LDA scaleFactor \ If scaleFactor is zero then we didn't need to do any BEQ gpol26 \ scaling on the deltas, so jump to gpol26 to skip the \ following and process the polygon edge in one step \ If we get here then we have scaled the deltas down by \ a factor of scaleFactor \ \ Because of the way we fed a set bit into scaleFactor \ for each shift, the scale factor is scaleFactor+1, so \ this is the same as splitting the polygon edge into \ scaleFactor+1 parts, each of which is a step along the \ the edge of the size given in the scaled-down deltas \ \ So we now process each of these small steps in a loop \ that we perform scaleFactor times in the first part \ and one more time at gpol26 \ \ For each step we move the start point to the end point \ from the previous step, and we move the end point \ along the edge by the delta \ \ We set up the "end point from the previous step" to \ point #Y above, so this process starts from point #Y \ and steps toward point #X \ \ Note that we set up the start and end points so 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 in part 5, so we trace along the line from \ the start at point #Y to the end at point #X .gpol25 LDA yEdgeEndLo \ Set the following, in sequence: STA yEdgeStartLo \ SEC \ yEdgeStart(Hi Lo) = yEdgeEnd(Hi Lo) SBC yEdgeDeltaLo \ STA yEdgeEndLo \ yEdgeEnd(Hi Lo) -= yEdgeDelta(Hi Lo) LDA yEdgeEndHi \ STA yEdgeStartHi \ So we step along the y-axis by one more delta SBC #0 STA yEdgeEndHi LDA xEdgeEndLo \ Set the following, in sequence: STA xEdgeStartLo \ SEC \ xEdgeStart(Hi Lo) = xEdgeEnd(Hi Lo) SBC xEdgeDeltaLo \ STA xEdgeEndLo \ xEdgeEnd(Hi Lo) -= xEdgeDelta(Hi Lo) LDA xEdgeEndHi \ STA xEdgeStartHi \ So we step along the x-axis by one more delta SBC xEdgeDeltaHi STA xEdgeEndHi JSR TracePolygonEdge \ Trace the small step of polygon edge that we just made \ along the edge, populating the xPolygonRight or \ xPolygonLeft table with the x-coordinate of the edge \ for each y-coordinate DEC scaleFactor \ Decrement the scale factor in scaleFactor BNE gpol25 \ Loop back to repeat the tracing process scaleFactor \ times \ \ As there are actually scaleFactor+1 steps, we now fall \ into the following to do one more step .gpol26 \ If we get here then we are either tracing the entire \ edge in one step, or we are performing the last step \ in a set of scaled steps \ \ If we are tracing the entire edge in one step, then we \ already set up the coordinates of the "end point from \ the previous step" in xEdgeEnd and yEdgeEnd to that of \ point #Y, so this process starts from point #Y and \ traces the edge to point #X \ \ If we are performing the last step in a set of scaled \ steps, then xEdgeEnd and yEdgeEnd are set to the end \ of the last step to be traced, so this process traces \ the last step towards point #X \ \ In either case, we start by setting the starting point \ for this tracing process to the values in xEdgeEnd and \ yEdgeEnd \ \ Note that we set up the start and end points so 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 in part 5, so we trace along the line from \ the start at point #Y to the end at point #X LDA yEdgeEndLo \ Set yEdgeStart(Hi Lo) = yEdgeEnd(Hi Lo) STA yEdgeStartLo \ LDA yEdgeEndHi \ So this is either the y-coordinate of point #Y or the STA yEdgeStartHi \ end of the last step in a multi-step trace LDA xEdgeEndLo \ Set xEdgeStart(Hi Lo) = xEdgeEnd(Hi Lo) STA xEdgeStartLo \ LDA xEdgeEndHi \ So this is either the x-coordinate of point #Y or the STA xEdgeStartHi \ end of the last step in a multi-step trace LDX pointX \ Set X to the number of point #X, which we stored at \ the start of this part LDA drawViewPitchLo,X \ Set yEdgeEnd(Hi Lo) to the y-coordinate of point #X, STA yEdgeEndLo \ from the x-coordinate tables we populated in parts 3 LDA drawViewPitchHi,X \ and 4 STA yEdgeEndHi LDA xPolygonPointLo,X \ Set xEdgeEnd(Hi Lo) to the x-coordinate of point #X STA xEdgeEndLo \ from the x-coordinate tables we populated in parts 3 LDA xPolygonPointHi,X \ and 4 STA xEdgeEndHi LDA yEdgeStartLo \ Set yEdgeDeltaLo = yEdgeStartLo - yEdgeEndLo SEC \ SBC yEdgeEndLo \ This calculates the y-axis delta along the edge, which STA yEdgeDeltaLo \ we know we can do in one byte by this point JSR TracePolygonEdge \ Trace the polygon edge, populating the xPolygonRight \ or xPolygonLeft table with the x-coordinate of the \ edge for each y-coordinate JMP gpol15 \ Jump back to part 5 to move on to the next polygon \ edge