; Moving cube geometry shares the existing 320x240 logical game canvas. include src_graphics/dice_anchors.inc .data cubeCorners3D dd -32768,-32768,-32768, 32768,-32768,-32768 dd 32768,32768,-32768, -32768,32768,-32768 dd -32768,-32768,32768, 32768,-32768,32768 dd 32768,32768,32768, -32768,32768,32768 cubeFaces3D db 0,1,2,3, 4,7,6,5, 0,3,7,4 db 1,5,6,2, 0,4,5,1, 3,2,6,7 cubeTop3D dd 3,1,1,1,1,3 cubeRight3D dd 2,3,2,2,3,2 cubeColors3D dd 00FAF1DFh,00C9C1B0h,00D1C5AEh dd 00DFD3BDh,00FFF9EAh,00B5AA98h cubePips3D dd 32768,32768, 16384,16384, 49152,49152 dd 49152,16384, 16384,49152, 16384,32768, 49152,32768 cubeX3D dd 0 cubeY3D dd 0 cubeScale3D dd 36 cubeSinX3D dd 0 cubeCosX3D dd 65536 cubeSinY3D dd 0 cubeCosY3D dd 65536 cubeSinZ3D dd 0 cubeCosZ3D dd 65536 cubeVertices3D dd 16 dup(0) cubeFaceValues3D dd 6 dup(0) cubeQuad3D dd 8 dup(0) cubeContactShadow3D dd 0 .code ; Fill clockwise triangles. Edges are incremented per pixel, avoiding divisions. DrawTriangle3D PROC uses ebx esi edi x1:DWORD,y1:DWORD,x2:DWORD,y2:DWORD,x3:DWORD,y3:DWORD,tint:DWORD local lowX:DWORD,highX:DWORD,lowY:DWORD,highY:DWORD local dx0:DWORD,dy0:DWORD,dx1:DWORD,dy1:DWORD,dx2:DWORD,dy2:DWORD local row0:DWORD,row1:DWORD,row2:DWORD,e0:DWORD,e1:DWORD,e2:DWORD local py:DWORD,px:DWORD mov eax, x2 sub eax, x1 mov dx0, eax mov edx, y2 sub edx, y1 mov dy0, edx mov ebx, x3 sub ebx, x1 imul ebx, edx mov ecx, y3 sub ecx, y1 imul eax, ecx sub eax, ebx cmp eax, 0 jle triangle_done mov eax, x3 sub eax, x2 mov dx1, eax mov eax, y3 sub eax, y2 mov dy1, eax mov eax, x1 sub eax, x3 mov dx2, eax mov eax, y1 sub eax, y3 mov dy2, eax mov eax, x1 mov ebx, eax cmp eax, x2 jle @F mov eax, x2 @@: cmp eax, x3 jle @F mov eax, x3 @@: cmp eax, 0 jge @F xor eax, eax @@: mov lowX, eax cmp ebx, x2 jge @F mov ebx, x2 @@: cmp ebx, x3 jge @F mov ebx, x3 @@: cmp ebx, 319 jle @F mov ebx, 319 @@: mov highX, ebx mov eax, y1 mov ebx, eax cmp eax, y2 jle @F mov eax, y2 @@: cmp eax, y3 jle @F mov eax, y3 @@: cmp eax, 0 jge @F xor eax, eax @@: mov lowY, eax cmp ebx, y2 jge @F mov ebx, y2 @@: cmp ebx, y3 jge @F mov ebx, y3 @@: cmp ebx, 239 jle @F mov ebx, 239 @@: mov highY, ebx mov eax, lowY sub eax, y1 imul eax, dx0 mov edx, lowX sub edx, x1 imul edx, dy0 sub eax, edx mov row0, eax mov eax, lowY sub eax, y2 imul eax, dx1 mov edx, lowX sub edx, x2 imul edx, dy1 sub eax, edx mov row1, eax mov eax, lowY sub eax, y3 imul eax, dx2 mov edx, lowX sub edx, x3 imul edx, dy2 sub eax, edx mov row2, eax mov eax, lowY mov py, eax triangle_row: mov eax, py cmp eax, highY jg triangle_done mov eax, row0 mov e0, eax mov eax, row1 mov e1, eax mov eax, row2 mov e2, eax mov eax, lowX mov px, eax triangle_pixel: mov eax, px cmp eax, highX jg triangle_next_row mov eax, e0 or eax, e1 or eax, e2 js triangle_next_pixel mov edi, py imul edi, SCREEN_W * 2 mov eax, px shl eax, 1 add edi, eax mov eax, tint mov screenBuffer[edi*4], eax mov screenBuffer[edi*4+4], eax mov screenBuffer[edi*4+SCREEN_W*4], eax mov screenBuffer[edi*4+SCREEN_W*4+4], eax triangle_next_pixel: mov eax, dy0 sub e0, eax mov eax, dy1 sub e1, eax mov eax, dy2 sub e2, eax inc px jmp triangle_pixel triangle_next_row: mov eax, dx0 add row0, eax mov eax, dx1 add row1, eax mov eax, dx2 add row2, eax inc py jmp triangle_row triangle_done: ret DrawTriangle3D ENDP ; Local 16.16 coordinates -> yaw, pitch, roll -> screen coordinates. ProjectCubePoint3D PROC uses ebx esi edi nx:DWORD,ny:DWORD,nz:DWORD local rx:DWORD,ry:DWORD,rz:DWORD mov eax, nx imul cubeCosY3D shrd eax, edx, 16 mov ebx, eax mov eax, nz imul cubeSinY3D shrd eax, edx, 16 add eax, ebx mov rx, eax mov eax, nz imul cubeCosY3D shrd eax, edx, 16 mov ebx, eax mov eax, nx imul cubeSinY3D shrd eax, edx, 16 sub ebx, eax mov rz, ebx mov eax, ny imul cubeCosX3D shrd eax, edx, 16 mov ebx, eax mov eax, rz imul cubeSinX3D shrd eax, edx, 16 sub ebx, eax mov ry, ebx mov eax, rx imul cubeCosZ3D shrd eax, edx, 16 mov ebx, eax mov eax, ry imul cubeSinZ3D shrd eax, edx, 16 sub ebx, eax imul ebx, cubeScale3D sar ebx, 16 add ebx, cubeX3D mov eax, rx imul cubeSinZ3D shrd eax, edx, 16 mov esi, eax mov eax, ry imul cubeCosZ3D shrd eax, edx, 16 add eax, esi imul eax, cubeScale3D sar eax, 16 add eax, cubeY3D mov edx, eax mov eax, ebx ret ProjectCubePoint3D ENDP DrawCubePip3D PROC uses ebx esi u:DWORD,v:DWORD,pipRadius:DWORD mov eax, cubeQuad3D[8] sub eax, cubeQuad3D imul u shrd eax, edx, 16 mov ebx, eax mov eax, cubeQuad3D[24] sub eax, cubeQuad3D imul v shrd eax, edx, 16 add ebx, eax add ebx, cubeQuad3D mov eax, cubeQuad3D[12] sub eax, cubeQuad3D[4] imul u shrd eax, edx, 16 mov esi, eax mov eax, cubeQuad3D[28] sub eax, cubeQuad3D[4] imul v shrd eax, edx, 16 add esi, eax add esi, cubeQuad3D[4] invoke DrawCircle, ebx, esi, pipRadius, 00A31D25h ret DrawCubePip3D ENDP DrawTumblingDie3D PROC uses ebx esi edi centerX:DWORD,centerY:DWORD,pitch:DWORD,yaw:DWORD,roll:DWORD,value:DWORD local face:DWORD,pip:DWORD,pipRadius:DWORD,area:DWORD mov eax, centerX mov cubeX3D, eax mov eax, centerY mov cubeY3D, eax mov eax, pitch and eax, 511 mov edx, tableSin[eax*4] mov cubeSinX3D, edx mov edx, tableCos[eax*4] mov cubeCosX3D, edx mov eax, yaw and eax, 511 mov edx, tableSin[eax*4] mov cubeSinY3D, edx mov edx, tableCos[eax*4] mov cubeCosY3D, edx mov eax, roll and eax, 511 mov edx, tableSin[eax*4] mov cubeSinZ3D, edx mov edx, tableCos[eax*4] mov cubeCosZ3D, edx mov eax, value mov cubeFaceValues3D[16], eax mov edx, 7 sub edx, eax mov cubeFaceValues3D[20], edx dec eax mov edx, cubeRight3D[eax*4] mov cubeFaceValues3D[12], edx mov ecx, 7 sub ecx, edx mov cubeFaceValues3D[8], ecx mov edx, cubeTop3D[eax*4] mov cubeFaceValues3D, edx mov ecx, 7 sub ecx, edx mov cubeFaceValues3D[4], ecx xor esi, esi cube_project_loop: imul edi, esi, 12 invoke ProjectCubePoint3D, cubeCorners3D[edi], cubeCorners3D[edi+4], cubeCorners3D[edi+8] mov cubeVertices3D[esi*8], eax mov cubeVertices3D[esi*8+4], edx inc esi cmp esi, 8 jb cube_project_loop ; A resting cube touches the cloth along its projected bottom face. ; Reverse the underside winding; the normal face pass culls it. cmp cubeContactShadow3D,0 je cube_no_contact_shadow mov eax,cubeVertices3D[28] inc eax mov ebx,cubeVertices3D[60] inc ebx mov edi,cubeVertices3D[52] inc edi invoke DrawTriangle3D,cubeVertices3D[24],eax,cubeVertices3D[56],ebx,cubeVertices3D[48],edi,00153122h mov eax,cubeVertices3D[28] inc eax mov ebx,cubeVertices3D[52] inc ebx mov edi,cubeVertices3D[20] inc edi invoke DrawTriangle3D,cubeVertices3D[24],eax,cubeVertices3D[48],ebx,cubeVertices3D[16],edi,00153122h cube_no_contact_shadow: mov face, 0 cube_face_loop: mov esi, face xor edi, edi cube_load_quad: movzx eax, cubeFaces3D[esi*4+edi] mov ebx, cubeVertices3D[eax*8] mov cubeQuad3D[edi*8], ebx mov ebx, cubeVertices3D[eax*8+4] mov cubeQuad3D[edi*8+4], ebx inc edi cmp edi, 4 jb cube_load_quad mov eax, cubeQuad3D[8] sub eax, cubeQuad3D mov edx, cubeQuad3D[28] sub edx, cubeQuad3D[4] imul eax, edx mov ebx, cubeQuad3D[24] sub ebx, cubeQuad3D mov edx, cubeQuad3D[12] sub edx, cubeQuad3D[4] imul ebx, edx sub eax, ebx mov area, eax cmp eax, 0 jle cube_next_face mov ebx, cubeColors3D[esi*4] invoke DrawTriangle3D, cubeQuad3D, cubeQuad3D[4], cubeQuad3D[8], cubeQuad3D[12], cubeQuad3D[16], cubeQuad3D[20], ebx invoke DrawTriangle3D, cubeQuad3D, cubeQuad3D[4], cubeQuad3D[16], cubeQuad3D[20], cubeQuad3D[24], cubeQuad3D[28], ebx cmp area, 70 jl cube_next_face mov pipRadius, 1 cmp area, 450 jl @F mov pipRadius, 2 @@: mov ebx, cubeFaceValues3D[esi*4] test ebx, 1 jz cube_corner_pips invoke DrawCubePip3D, 32768, 32768, pipRadius cube_corner_pips: cmp ebx, 2 jl cube_next_face invoke DrawCubePip3D, 16384, 16384, pipRadius invoke DrawCubePip3D, 49152, 49152, pipRadius cmp ebx, 4 jl cube_next_face invoke DrawCubePip3D, 49152, 16384, pipRadius invoke DrawCubePip3D, 16384, 49152, pipRadius cmp ebx, 6 jl cube_next_face invoke DrawCubePip3D, 16384, 32768, pipRadius invoke DrawCubePip3D, 49152, 32768, pipRadius cube_next_face: inc face cmp face, 6 jb cube_face_loop ret DrawTumblingDie3D ENDP RenderDiceThrow3D PROC uses ebx esi edi local t:DWORD,ground:DWORD,lift:DWORD,pitch:DWORD,yaw:DWORD,roll:DWORD local cx1:DWORD,cx2:DWORD,cy:DWORD,cy2:DWORD,oldScale:DWORD,shadowAlpha:DWORD ; Held dice are painted into the cupped palm: no second pair over skin. cmp diceArtReady3D,1 jne throw_begin cmp dice3d_state,0 je throw_done cmp dice3d_state,1 jne throw_begin cmp dice3d_timer,240 jb throw_done throw_begin: mov eax,cubeScale3D mov oldScale,eax mov t,0 cmp dice3d_state,2 jne @F mov t,1600 @@: cmp dice3d_state, 1 jne throw_pose mov eax, dice3d_timer sub eax,240 jns @F xor eax,eax @@: cmp eax,1360 jbe @F mov eax,1360 @@: imul eax,1600 xor edx,edx mov ecx,1360 div ecx mov t, eax throw_pose: mov cubeScale3D,12 mov eax,t imul eax, DICE_RELEASE_Y1-146 xor edx, edx mov ecx, 1600 div ecx mov ebx, DICE_RELEASE_Y1 sub ebx, eax mov ground, ebx mov lift, 0 mov eax, t cmp eax, 500 jae throw_bounce2 mov edx, 500 sub edx, eax imul eax, edx imul eax, 160 xor edx, edx mov ecx, 250000 div ecx mov lift, eax jmp throw_position throw_bounce2: cmp eax, 950 jae throw_bounce3 sub eax, 500 mov edx, 450 sub edx, eax imul eax, edx imul eax, 56 xor edx, edx mov ecx, 202500 div ecx mov lift, eax jmp throw_position throw_bounce3: cmp eax, 1300 jae throw_position sub eax, 950 mov edx, 350 sub edx, eax imul eax, edx imul eax, 24 xor edx, edx mov ecx, 122500 div ecx mov lift, eax throw_position: mov eax, ground sub eax, lift mov cy, eax mov eax, t imul eax, DICE_RELEASE_X1-134 xor edx, edx mov ecx, 1600 div ecx mov ebx, DICE_RELEASE_X1 sub ebx, eax mov cx1, ebx mov eax,t imul eax,DICE_RELEASE_X2-186 xor edx,edx mov ecx,1600 div ecx mov ebx,DICE_RELEASE_X2 sub ebx,eax mov cx2,ebx mov eax, 1600 sub eax, t imul eax,eax imul eax,1024 xor edx, edx mov ecx,2560000 div ecx mov esi,1024 sub esi,eax mov roll,esi mov eax,esi add eax,70 mov pitch,eax mov eax,esi shr eax,1 add eax,44 mov yaw,eax mov cubeContactShadow3D,0 cmp t,1600 jne @F mov cubeContactShadow3D,1 @@: mov eax,t imul eax,DICE_RELEASE_Y1-DICE_RELEASE_Y2 xor edx,edx mov ecx,1600 div ecx add eax,cy sub eax,DICE_RELEASE_Y1-DICE_RELEASE_Y2 mov cy2,eax cmp dice3d_state,0 je throw_cubes cmp dice3d_state,1 jne throw_shadows cmp dice3d_timer,240 jb throw_cubes throw_shadows: cmp diceShadowPass3D,0 je throw_cubes mov eax,85 sub eax,lift mov shadowAlpha,eax mov eax,cx1 shl eax,1 mov edx,cubeScale3D shr edx,2 add edx,ground shl edx,1 invoke DrawCoinShadow3D,eax,edx,cubeScale3D,6,shadowAlpha mov eax,cx2 shl eax,1 mov edx,cubeScale3D shr edx,2 add edx,ground shl edx,1 invoke DrawCoinShadow3D,eax,edx,cubeScale3D,6,shadowAlpha throw_cubes: cmp diceShadowPass3D,0 jne throw_restore invoke DrawTumblingDie3D, cx1, cy, pitch, yaw, roll, dice3d_val1 mov eax,roll neg eax invoke DrawTumblingDie3D, cx2, cy2, pitch, yaw, eax, dice3d_val2 throw_restore: mov eax,oldScale mov cubeScale3D,eax mov cubeContactShadow3D,0 throw_done: ret RenderDiceThrow3D ENDP