Skip to navigation

Lander on the Acorn Archimedes

3D objects: DrawObject (Part 1 of 5)

Name: DrawObject (Part 1 of 5) [Show more] Type: Subroutine Category: 3D objects Summary: Draw a 3D object and its shadow Deep dive: Drawing 3D objects Object blueprints Flying by mouse
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawObjects (Part 2 of 3) calls DrawObject * MoveAndDrawParticles (Part 3 of 4) calls DrawObject * MoveAndDrawPlayer (Part 3 of 5) calls DrawObject

Arguments: (R0, R1, R2) The 3D coordinate (x, y, z) of the object relative to the camera R3 The address of the object's rotation matrix
.DrawObject STMFD R13!, {R6-R12, R14} \ Store the registers that we want to use on \ the stack so they can be preserved LDR R12, graphicsBufferEndAddr \ Set R12 to the address of the table that \ contains the end addresses of the graphics \ buffers, so when we draw the objects, we \ can add them as drawing commands onto the \ ends of the relevant graphics buffers \ \ In other words, R12 = graphicsBuffersEnd \ throughout the following ADD R4, R11, #xObject \ Set R4 to the address of xObject STMIA R4, {R0-R2} \ Store (R0, R1, R2) in the first three \ words of xObject, so we have: \ \ * xObject = x-coordinate of the object \ relative to the camera \ \ * yObject = y-coordinate of the object \ relative to the camera \ \ * zObject = z-coordinate of the object \ relative to the camera \ We now scale up the coordinate (x, y, z) \ in (R0, R1, R2) as high as it can go while \ still staying within 32-bit coordinates MOVS R4, R0 \ Set R4 = |R0| MVNMI R4, R4 \ = |x| \ \ If R0 is negative then R4 is actually set \ ~x, which is -(x+1), but it's close enough MOVS R5, R1 \ Set R5 = |R1| MVNMI R5, R5 \ = |y| \ \ If R1 is negative then R5 is actually set \ ~y, which is -(y+1), but it's close enough ORR R4, R4, R5 \ Set R4 = |R0| OR |R1| OR R2 ORR R4, R4, R2 \ = |x| OR |y| OR z ORRS R4, R4, #1 \ \ And round it up so it is non-zero \ \ So this sets R4 to a number that is \ greater than |x|, |y| and z, so R4 is \ therefore an upper bound on the values of \ all three coordinates MOVPL R4, R4, LSL #1 \ If R4 is positive then we know bit 7 is \ clear, so shift the sign bit off the end \ so we don't include it in the scale factor \ calculation below \ We now work out how many times we can \ scale up R4 so that it is as large as \ possible but still fits within a 32-bit \ word MOV R5, #0 \ Set R5 = 0 to use as the scale factor in \ the following loop STRB R5, [R11, #crashedFlag] \ Set crashedFlag = 0 to indicate that the \ object has not crashed (though we will \ change this later if we find that it has) .dobj1 MOVS R4, R4, LSL #1 \ Shift R4 to the left until the top bit is ADDPL R5, R5, #1 \ set, incrementing R5 for each shift so R5 BPL dobj1 \ contains the scale factor we have applied \ to R4 \ \ So this scales R4 as high as possible \ while still staying within 32 bits, with \ the scale factor given in R5 MOV R0, R0, LSL R5 \ We now scale up the coordinate (x, y, z) MOV R1, R1, LSL R5 \ in (R0, R1, R2) by the scale factor in R5, MOV R2, R2, LSL R5 \ as we know the result will stay within \ 32-bit words ADD R4, R11, #xObjectScaled \ Store (R0, R1, R2) in xObjectScaled, STMIA R4, {R0-R2} \ zObjectScaled and zObjectScaled ADD R4, R11, #rotationMatrix \ If R3 does not already point to the CMP R3, R4 \ rotation matrix at rotationMatrix, copy LDMNEIA R3!, {R0-R2} \ the nine-word matrix from the address in STMNEIA R4!, {R0-R2} \ R3 into rotationMatrix, so rotationMatrix LDMNEIA R3!, {R0-R2} \ now contains the object's rotation matrix, STMNEIA R4!, {R0-R2} \ which is made up of the three orientation LDMNEIA R3!, {R0-R2} \ vectors in: STMNEIA R4!, {R0-R2} \ \ (xNoseV, xRoofV, xSideV) \ (yNoseV, yRoofV, ySideV) \ (zNoseV, zRoofV, zSideV) \ So by this point we have: \ \ * The object's coordinate in: \ \ (xObject, yObject, zObject) \ \ * The scaled-up coordinate in: \ \ (xObjectScaled, yObjectScaled, \ zObjectScaled) \ \ * The object's rotation matrix at \ rotationMatrix, which is made up of \ the orientation vectors as follows: \ \ (xNoseV, xRoofV, xSideV) \ (yNoseV, yRoofV, ySideV) \ (zNoseV, zRoofV, zSideV) \ \ * crashedFlag = 0 \ \ * R12 = graphicsBuffersEnd \ \ We are now ready to move on to processing \ the object's vertices and faces