Skip to navigation

Aviator on the BBC Micro

Visibility: ProcessLinesToShow

Name: ProcessLinesToShow [Show more] Type: Subroutine Category: Visibility Summary: Process the linesToShow list, projecting all the lines onto the screen and moving any that aren't visible to the linesToHide list Deep dive: Visibility checks
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MainLoop (Part 13 of 15) calls ProcessLinesToShow
.ProcessLinesToShow LDA linesToShowEnd \ If the linesToShow list is empty, jump to show5 to BEQ show5 \ clear down the relatedPoints list, as there are no \ visible lines at all LDA #255 \ Set linesToShowPointer = 255, to use as a pointer STA linesToShowPointer \ to the end of the new linesToShow list as we build it \ up in-situ LDA #0 \ Set lineCounter = 0, to use as a line counter as we STA lineCounter \ loop through the linesToShow list .show1 LDX lineCounter \ Set lineId to the ID of the next line in the LDY linesToShow,X \ linesToShow list STY lineId LDX lineStartPointId,Y \ Set GG to the point ID of the line's start point, to STX GG \ pass to the ProjectPoint routine STX L \ Set L to the point ID of the line's start point LDX lineEndPointId,Y \ Set M to the point ID of the line's end point STX M JSR ProjectPoint \ Project the line's end point onto the screen, putting \ the screen coordinates into (xPoint, yPoint) and \ setting the point's status byte accordingly LDA M \ Set GG to the point ID of the line's start point, to STA GG \ pass to the ProjectPoint routine JSR ProjectPoint \ Project the line's start point onto the screen, \ putting the screen coordinates into (xPoint, yPoint) \ and setting the point's status byte accordingly LDX L \ Set startStatus to the status byte of the line's start LDA pointStatus,X \ point STA startStatus LDX M \ Set N to the status byte of the line's end point LDA pointStatus,X STA N AND startStatus \ Set A as follows: AND #%00110000 \ \ * Bit 4 is set in A if bit 4 is set in both points, \ so both the start and end points (in 3D space) \ have |yPoint| * 2 >= |zPoint| \ \ * Bit 5 is set in A if bit 5 is set in both points, \ so both the start and end points (in 3D space) \ have |xPoint| >= |zPoint| \ \ so A is in the form %00xx0000 BEQ show2 \ If both bits 4 and 5 are clear in the above, jump to \ show2 to keep the line in the linesToShow list LSR A \ Shift bits 4 and 5 down into bits 2 and 3 and store LSR A \ the result in T, so: STA T \ \ * Bit 2 is set in T if bit 4 is set in both points \ * Bit 3 is set in T if bit 5 is set in both points \ \ and the rest of the bits will be 0, so T is in the \ form %0000xx00 LDA N \ Set A = end point status EOR startStatus \ EOR start point status EOR #&FF \ EOR %11111111 AND T \ AND T \ \ Because T is in the form %0000xx00, we are only \ interested in the calculation for bits 2 and 3, as all \ other bits will be zeroed by the AND T. Just taking \ bit 2 we get the following (the numbers on the right \ show the calculation in progress): \ \ A = bit 2 of end point \ EOR bit 2 of start point <- 0 if bits are same \ EOR 1 <- 1 if bits are same \ AND bit 2 of T <- 1 if set \ \ So bit 2 of A will be set only when both of the \ following are true: \ \ * Bit 2 is the same in both points \ * Bit 2 of T is set \ \ which expands to the following: \ \ * Bit 2 is the same in both points \ * Bit 4 is set in both points \ \ and means: \ \ * yPoint in both points has the same sign \ * |yPoint| * 2 >= |zPoint| for both points \ \ Similarly, bit 3 of A will be set only when both of \ the following are true: \ \ * Bit 3 is the same in both points \ * Bit 5 is set in both points \ \ which means: \ \ * xPoint in both points has the same sign \ * |xPoint| >= |zPoint| for both points BNE show3 \ If A is non-zero, then this means that at least one of \ the above is true for this line. Let's see what that \ means. If both of the following are true: \ \ * yPoint in both points has the same sign \ * |yPoint| * 2 >= |zPoint| for both points \ \ then: \ \ * The first one means that either both ends of the \ line are above us, or both are below us, so the \ line isn't crossing our field of view from top to \ bottom \ \ * The second one means that both points are above or \ both points are below the 2y = z line (or, more \ accurately, the 2y = z plane). In terms of 3D \ space, this means that for us to look at these \ points from our plane seat, we would need to raise \ or lower our gaze by more than 22.5 degrees \ \ If both of these are true, then the line isn't \ crossing our field of view, and it's too far above or \ below us to be seen... or in other words, it isn't \ visible \ \ The xPoint rules are similar. If both of these are \ true: \ \ * xPoint in both points has the same sign \ * |xPoint| >= |zPoint| for both points \ \ then: \ \ * The first one means that either both ends of the \ line are to the left of us, or both are to the \ right of us, so the line isn't crossing our field \ of view from left to right \ \ * The second one means that both points are to the \ left of or both points are to the right of the \ x = z line (or, more accurately, the x = z plane). \ In terms of 3D space, this means that for us to \ look at these points from our plane seat, we would \ need to look left or right by more than 45 degrees \ \ If both of these are true, then the line isn't \ crossing our field of view, and it's too far to the \ left or right of us to be seen... or in other words, \ it isn't visible \ \ So if A is non-zero, this means that the line is not \ visible so we jump to show3 to add this line to the \ linesToHide list .show2 \ If we get here then we want to keep this line in the \ linesToShow list INC linesToShowPointer \ Increment the linesToShowPointer pointer to point to \ the next free slot in the new list we are creating LDX linesToShowPointer \ Store the line ID at the end of the new list we are LDA lineId \ creating STA linesToShow,X JMP show4 \ Jump to show4 to move on to the next line .show3 LDA lineId \ If the line Id is 0 then it's the horizon, so jump up BEQ show2 \ to show2 add it to the linesToShow list, as we don't \ want to hide the horizon INC linesToHideEnd \ Increment linesToHideEnd to point to the next free \ entry at the end of the linesToHide list LDX linesToHideEnd \ Add the line ID in A to the end of the linesToHide STA linesToHide,X \ list .show4 INC lineCounter \ Increment the loop counter to point to the next line \ in the linesToShow list LDA lineCounter \ Loop back to process the next line from linesToShow CMP linesToShowEnd \ until we have worked our way to the end BCC show1 LDA linesToShowPointer \ Set linesToShowEnd = linesToShowPointer + 1 ADC #0 \ STA linesToShowEnd \ so it points to the index of the first empty entry in \ the newly processed linesToShow list .show5 LDX relatedPoints \ If the relatedPoints list is empty, jump to show7 to BEQ show7 \ return from the subroutine \ Otherwise we now reset the point status bytes for all \ the points mentioned in the relatedPoints list, so \ they are no longer marked as having their coordinates \ and visibility calculated LDA #0 \ Set A = 0 to use for resetting the status bytes .show6 LDY relatedPoints,X \ Zero the status byte for the X-th entry in the list STA pointStatus,Y DEX \ Decrement the loop counter BNE show6 \ Loop back until we have reset all the .show7 RTS \ Return from the subroutine