Skip to navigation

Drawing polygons: TracePolygonEdge (Part 3 of 8)

Name: TracePolygonEdge (Part 3 of 8) [Show more] Type: Subroutine Category: Drawing polygons Summary: Trace a polygon edge with a shallow gradient by stepping along the x-axis
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
.tred18 \ If we get here then xEdgeDelta >= yEdgeDeltaLo, so the \ x-axis delta is the biggest and the polygon edge has a \ shallow gradient \ \ We therefore step along the x-axis one pixel at a time \ and cumulatively add the gradient to calculate the \ y-coordinate at each step STA tred24+2 \ Modify the instruction at tred24 to use the address in STY tred24+1 \ (A Y), so it becomes: \ \ STX into address (xPolygonAddrHi yEdgeStartLo) \ \ xPolygonAddrHi is set to the high byte of either \ xPolygonLeft or xPolygonRight, and both of these \ tables start on a page boundary, so this sets the \ address to offset yEdgeStartLo within the table \ specified by xPolygonAddrHi \ \ We will decrement this address when we need to step \ along the y-axis, according to the cumulative value of \ the slope error STX tred22 \ Modify the instruction at tred12 to use the opcode \ specified in X, so we have: \ \ * DEX when xEdgeStartLo - xEdgeEndLo is positive \ \ * INX when xEdgeStartLo - xEdgeEndLo is negative \ \ We store the x-coordinate in X, so this ensures that: \ \ * We step left when required with DEX, for when the \ start point is to the right of the end point \ \ * We step right when required with INX, for when the \ start point is to the left of the end point \ \ We will run this instruction for each step along the \ edge, so we step along the x-axis as we trace the edge LDY #tred24-tred23-2 \ Set Y to the operand required to modify the BCC \ instruction at tred23 to the following: \ \ BCC tred24 CMP #HI(xPolygonLeft) \ If we are tracing a left edge of the polygon, jump to BEQ tred19 \ tred19 \ If we get here then we are tracing a right edge of the \ polygon CPX #&CA \ If we are going to be stepping along the x-axis with a BEQ tred20 \ DEX instruction (opcode &DA), jump to tred20 so we can \ modify the instruction at tred23 to BCC tred25 BNE tred21 \ Otherwise we are going to be stepping along the x-axis \ with an INX instruction, so jump to tred21 to modify \ the instruction at tred23 to BCC tred24 (this BNE is \ effectively a JMP as we just passed through a BEQ) .tred19 \ If we get here then we are tracing a left edge of the \ polygon CPX #&CA \ If we are going to be stepping along the x-axis with a BEQ tred21 \ DEX instruction (opcode &DA), jump to tred21 so we can \ modify the instruction at tred23 to BCC tred24 .tred20 LDY #tred25-tred23-2 \ Set Y to the operand required to modify the BCC \ instruction at tred23 to the following: \ \ BCC tred25 .tred21 STY tred23+1 \ Modify the instruction at tred23 to use the operand \ specified in Y, so we have: \ \ * BCC tred24 when we are tracing a right edge and \ stepping along the x-axis with INX or a left edge \ and stepping along with DEX \ \ * BCC tred25 when we are tracing a right edge and \ stepping along the x-axis with DEX or a left edge \ and stepping along with INX \ \ This ensures that we store the x-coordinate of the \ outermost pixel along the edge for each horizontal \ polygon line (see tred23 below for details) LDY xEdgeDelta \ Set Y = xEdgeDelta + 1 INY \ \ We can use this as a pixel counter when stepping along \ the polygon edge's x-axis delta one pixel at a time, \ as there are xEdgeDelta + 1 pixels along the edge \ (the additional one ensures we include the pixels at \ both ends) LDA xEdgeDelta \ Set A = ~(xEdgeDelta / 2) LSR A \ EOR #&FF \ We use A to keep track of the slope error, though I am \ unsure of why we start with this value CLC \ Clear the C flag so the first addition we do in the \ following loop will work correctly \ We already ensured in part 1 that yEdgeStart(Hi Lo) \ is positive, so the following check only matches \ yEdgeStartHi when it's in the range 1 to 127 LDX yEdgeStartHi \ If 0 < yEdgeStartHi < 128 then the start point is BNE tred31 \ beyond the top of the screen, so jump to part 5 to \ trace the edge from the start until it reaches the \ screen, but without storing the results \ \ When the tracing reaches the top of the screen, part 4 \ will jump into the loop below at tred14 to continue \ the normal tracing process LDX xEdgeStartLo \ Set X to the x-coordinate of the starting point, so we \ can start tracing from the start of the edge JMP tred24 \ Jump into the middle of the loop at tred24 .tred22 DEX \ This instruction is modified above to: \ \ * INX (if we are stepping right along the x-axis) \ \ * DEX (if we are stepping left along the x-axis) \ \ So in either case this steps us along the x-axis by \ one pixel ADC yEdgeDeltaLo \ Add the y-axis delta to the slope error in A, so we \ keep track of the slope error as we move along the \ x-axis .tred23 BCC tred25 \ This instruction is modified above to: \ \ * BCC tred24 when we are tracing a right edge with \ INX or a left edge with DEX \ \ * BCC tred25 when we are tracing a right edge with \ DEX or a left edge with INX \ \ So if the addition didn't overflow then we have not \ moved into a new y-coordinate with this step along the \ x-axis, so jump to tred24 or tred25 so we do not move \ along the y-axis \ \ The difference in the two branches is as follows: \ \ * BCC tred24 stores the coordinate \ \ * BCC tred25 does not store the coordinate \ \ So when we are tracing a right edge with DEX and we \ are moving left along the x-axis, then we only \ update the coordinate when the slope error overflows, \ so we store the x-coordinate for the rightmost pixel \ there is more than one pixel along the x-axis for this \ step (so we store the rightmost pixels from the edge, \ which is what we want) \ \ The same is true when we are tracing a left edge with \ INX and we are moving right along the x-axis, but in \ this case we store the x-coordinate for the leftmost \ pixel for each step (so we store the leftmost pixels \ from this edge, which is what we want) SBC xEdgeDelta \ Set A = A - xEdgeDelta \ \ This updates the slope error in A \ \ This subtraction works as we just passed through a \ BCC, so we know the C flag is set DEC tred24+1 \ Decrement the low byte of the address in the \ instruction below so that it points to the table \ entry for the next y-coordinate down BEQ tred17 \ If we just decremented the low byte of the address to \ zero then we have finished stepping along the y-axis, \ so jump to tred17 in part 2 to finish off .tred24 STX xPolygonRight+&9E \ This instruction is modified above to the following: \ \ STX into address (xPolygonAddrHi yEdgeStartLo) \ \ So this stores the current x-coordinate as we step \ along the edge, storing the coordinate in either the \ xPolygonRight or xPolygonLeft table, and storing the \ coordinate in the offset given by the y-coordinate \ of the current position along the edge we are tracing \ \ The original value of xPolygonRight+&9E is just \ workspace noise and has no meaning, as it is modified \ before we get here .tred25 DEY \ Decrement the pixel counter in Y BNE tred22 \ Loop back to keep tracing the polygon edge until we \ have worked our way through all the pixels along the \ x-axis \ If we get here then we have finished tracing the edge \ and Y = 0, so we can now finish off by setting the \ value of drawPolygon to zero so the polygon gets drawn JMP tred15 \ Jump to tred15 to set drawPolygon and return from the \ subroutine (this BEQ is effectively a JMP as Y is \ always zero)