Skip to navigation

Lander on the Acorn Archimedes

3D objects: DrawObject (Part 3 of 5)

Name: DrawObject (Part 3 of 5) [Show more] Type: Subroutine Category: 3D objects Summary: Calculate the visibility of each of the object's faces Deep dive: Drawing 3D objects Object blueprints
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
LDR R1, [R11, #objectData] \ Set R1 to the address of the blueprint \ for the object that is being drawn LDR R0, [R1, #8] \ Set R0 to the third word of the blueprint, \ which contains the offset from the start \ of the blueprint to the face data ADD R9, R1, R0 \ Set R9 to the address of the face data in \ the blueprint LDR R8, [R1, #4] \ Set R8 to the second word of the \ blueprint, which contains the number of \ faces \ We now iterate through the faces in the \ blueprint, using R8 as a loop counter (as \ we just set it to the number of faces) \ \ As we iterate through the faces we check \ their visibility, and draw the visible \ faces and (if applicable) their shadows \ into the graphics buffers .dobj3 MOV R0, R9 \ Copy the value of R9 into R0, so R0 points \ to the start of the current face data, \ which is where the face's normal vector is \ stored ADD R9, R9, #12 \ Add 12 to R9 so it points to the fourth \ word in the current face data, which is \ where the vertex numbers are stored ADD R1, R11, #xVertex \ Set R1 to the address of xVertex, so we \ store the results of the following \ calculation here BL MultiplyVectorByMatrix \ If this object is a static object, then \ simply copy the normal vector into xVertex \ as follows: \ \ [xVertex] [xNormal] \ [yVertex] = [yNormal] \ [zVertex] [zNormal] \ \ If this is a rotating object, then \ calculate the following, multiplying the \ vector in R0 by the rotation matrix in \ rotationMatrix: \ \ [xVertex] [xNormal] \ [yVertex] = rotationMatrix . [yNormal] \ [zVertex] [zNormal] \ \ So this rotates the normal vector in R0 by \ the object's rotation matrix, so the \ normal has now been rotated into the same \ frame of reference as the object in the 3D \ world, and we can check the orientation of \ that rotated normal to see if the face is \ visible LDR R1, [R11, #yVertex] \ Set R1 to yVertex, the y-coordinate of the \ rotated normal LDRB R14, [R11, #objectFlags] \ If bit 0 of objectFlags is zero then this TST R14, #%00000001 \ object is static and does not rotate, so MVNEQ R3, #0 \ set R1 and R3 to -1 so this face is always MVNEQ R1, #0 \ visible (as R3 is negative) and always \ casts a shadow in objects with shadows \ as (R1 is negative) ADDNE R2, R11, #xObjectScaled \ Otherwise bit 0 of objectFlags is set, so ADDNE R0, R11, #xVertex \ calculate the dot product of the vectors BLNE GetDotProduct \ at xObjectScaled and xVertex, storing the \ result in R3 \ \ The sign of the dot product depends on the \ angle between the two vectors, so R3 is: \ \ * Negative if angle < 90 degrees \ \ * Positive if angle >= 90 degrees \ \ The vector at xObjectScaled is the vector \ from the camera to the object, so we can \ see faces with normals that are less than \ 90 degrees off this vector, as they point \ towards the camera, while hidden faces \ point away from the camera at angles of \ more than 90 degrees \ \ So if R3 is positive, the face is facing \ away from us and is not visible, and if \ it's negative, the opposite is true STMFD R13!, {R8-R9, R11-R12} \ Store the registers that we want to use on \ the stack so they can be retrieved at \ dobj5 after the face has been processed