; Symmetric normal impulses and overlap correction follow the existing billiards ; solver. Four 4-ms substeps prevent tunnelling; angular rocking is separate. include src_graphics\bowling_deck.inc NormalizeBowlingPinAxis3D PROC uses esi pin:DWORD local axisLength:REAL8 mov esi,pin mov eax,bpPinAxisX3D[esi*4] or eax,bpPinAxisY3D[esi*4] jnz bp_axis_length mov bpPinAxisY3D[esi*4],-FP_1 ret bp_axis_length: fild bpPinAxisX3D[esi*4] fmul st,st fild bpPinAxisY3D[esi*4] fmul st,st faddp st(1),st fsqrt fstp axisLength fild bpPinAxisX3D[esi*4] fdiv axisLength fmul roofFloatFP3D fistp bpPinAxisX3D[esi*4] fild bpPinAxisY3D[esi*4] fdiv axisLength fmul roofFloatFP3D fistp bpPinAxisY3D[esi*4] ret NormalizeBowlingPinAxis3D ENDP BowlingPlayHit3D PROC pin:DWORD,vx:DWORD,vy:DWORD invoke BowlingPlayKick3D,pin,vx,vy ret BowlingPlayHit3D ENDP BowlingPlayKick3D PROC uses ebx esi edi pin:DWORD,vx:DWORD,vy:DWORD local energy:DWORD mov esi,pin cmp esi,10 jae bp_kick_done ; Preserve fractional impulses: signed pre-rounding can collapse the basis. fild vx fmul st,st fild vy fmul st,st faddp st(1),st fsqrt fistp energy mov eax,energy cmp eax,128 jb bp_kick_done cmp eax,bpImpactEnergy3D jbe @F mov bpImpactEnergy3D,eax @@: cmp eax,128 jb bp_kick_done mov edx,bpPhysicsTicks3D mov bpPinContactTick3D[esi*4],edx mov ecx,2 cdq idiv ecx cmp eax,2000 jbe @F mov eax,2000 @@: add bpPinTiltV3D[esi*4],eax mov eax,bpPinTiltV3D[esi*4] cmp eax,2400 jle @F mov bpPinTiltV3D[esi*4],2400 @@: cmp bpPinTilt3D[esi*4],64*256 jae bp_kick_done mov eax,vx mov ecx,FP_1 imul ecx idiv energy mov bpPinAxisX3D[esi*4],eax mov eax,vy imul ecx idiv energy mov bpPinAxisY3D[esi*4],eax invoke NormalizeBowlingPinAxis3D,esi mov eax,vx sub eax,vy sar eax,10 mov bpPinSpin3D[esi*4],eax bp_kick_done: ret BowlingPlayKick3D ENDP BowlingPlayContact3D PROC uses ebx esi edi a:DWORD,b:DWORD local deltaX:DWORD,deltaY:DWORD,radius:DWORD,distance:DWORD,nx:DWORD,ny:DWORD local impulse:DWORD,changeA:DWORD,changeB:DWORD,ix:DWORD,iy:DWORD,massSum:DWORD local contactLength:REAL8 mov esi,a mov edi,b mov eax,bpRadius3D[esi*4] add eax,bpRadius3D[edi*4] mov radius,eax shl eax,8 mov ebx,eax mov eax,bpPinX3D[edi*4] sub eax,bpPinX3D[esi*4] cmp eax,ebx jg bp_contact_done neg ebx cmp eax,ebx jl bp_contact_done mov deltaX,eax mov eax,bpPinY3D[edi*4] sub eax,bpPinY3D[esi*4] cmp eax,ebx jl bp_contact_done neg ebx cmp eax,ebx jg bp_contact_done mov deltaY,eax sar eax,8 imul eax,eax mov ebx,deltaX sar ebx,8 imul ebx,ebx add eax,ebx mov ebx,radius imul ebx,ebx cmp eax,ebx jae bp_contact_done fild deltaX fmul st,st fild deltaY fmul st,st faddp st(1),st fsqrt fst contactLength fistp distance cmp distance,0 jne @F mov deltaX,1 mov deltaY,0 mov distance,1 fild distance fstp contactLength @@: mov eax,radius shl eax,8 cmp distance,eax jae bp_contact_done fild deltaX fdiv contactLength fmul roofFloatFP3D fistp nx fild deltaY fdiv contactLength fmul roofFloatFP3D fistp ny mov eax,bpInvMass3D[esi*4] add eax,bpInvMass3D[edi*4] mov massSum,eax mov eax,bpPinVX3D[edi*4] sub eax,bpPinVX3D[esi*4] imul nx shrd eax,edx,16 mov ebx,eax mov eax,bpPinVY3D[edi*4] sub eax,bpPinVY3D[esi*4] imul ny shrd eax,edx,16 add eax,ebx test eax,eax jns bp_contact_separate neg eax mov ecx,FP_1*3/2 imul ecx idiv massSum mov impulse,eax imul bpInvMass3D[esi*4] shrd eax,edx,16 mov changeA,eax mov eax,impulse imul bpInvMass3D[edi*4] shrd eax,edx,16 mov changeB,eax mov eax,changeA imul nx shrd eax,edx,16 sub bpPinVX3D[esi*4],eax neg eax mov ix,eax mov eax,changeA imul ny shrd eax,edx,16 sub bpPinVY3D[esi*4],eax neg eax invoke BowlingPlayKick3D,esi,ix,eax mov eax,changeB imul nx shrd eax,edx,16 add bpPinVX3D[edi*4],eax mov ix,eax mov eax,changeB imul ny shrd eax,edx,16 add bpPinVY3D[edi*4],eax invoke BowlingPlayKick3D,edi,ix,eax bp_contact_separate: mov eax,radius shl eax,8 sub eax,distance jle bp_contact_done imul eax,3 sar eax,2 mov impulse,eax imul bpInvMass3D[esi*4] idiv massSum mov changeA,eax mov eax,impulse imul bpInvMass3D[edi*4] idiv massSum mov changeB,eax mov eax,changeA imul nx shrd eax,edx,16 sub bpPinX3D[esi*4],eax mov eax,changeA imul ny shrd eax,edx,16 sub bpPinY3D[esi*4],eax mov eax,changeB imul nx shrd eax,edx,16 add bpPinX3D[edi*4],eax mov eax,changeB imul ny shrd eax,edx,16 add bpPinY3D[edi*4],eax bp_contact_done: ret BowlingPlayContact3D ENDP BowlingPlayStep3D PROC uses ebx esi edi local substep:DWORD,rack:DWORD mov esi,bpLane3D mov eax,bwRack3D[esi*4] or eax,1024 mov rack,eax mov eax,bpBallX3D mov bpPinX3D[40],eax mov eax,bpBallY3D mov bpPinY3D[40],eax mov eax,bpBallVX3D mov bpPinVX3D[40],eax mov eax,bpBallVY3D mov bpPinVY3D[40],eax mov substep,0 bp_physics_substep: xor esi,esi bp_physics_integrate: bt rack,esi jnc bp_physics_integrate_next mov eax,bpPinVX3D[esi*4] sar eax,2 add bpPinX3D[esi*4],eax mov eax,bpPinVY3D[esi*4] sar eax,2 add bpPinY3D[esi*4],eax cmp esi,10 jne bp_physics_integrate_next cmp bpPinY3D[40],FP_1*28/10 jge @F mov bpPinVX3D[40],0 mov bpPinVY3D[40],0 @@: mov eax,bpPinX3D[40] cdq xor eax,edx sub eax,edx cmp eax,FP_1*74/100 jbe bp_physics_integrate_next mov bpGutter3D,1 mov eax,FP_1*87/100 cmp bpPinX3D[40],0 jge @F neg eax @@: mov bpPinX3D[40],eax mov bpPinVX3D[40],0 bp_physics_integrate_next: inc esi cmp esi,BP_BODY_COUNT jb bp_physics_integrate xor esi,esi bp_physics_pair_a: bt rack,esi jnc bp_physics_pair_next_a lea edi,[esi+1] bp_physics_pair_b: bt rack,edi jnc bp_physics_pair_next_b cmp edi,10 jne @F cmp bpGutter3D,0 jne bp_physics_pair_next_b @@: invoke BowlingPlayContact3D,esi,edi bp_physics_pair_next_b: inc edi cmp edi,BP_BODY_COUNT jb bp_physics_pair_b bp_physics_pair_next_a: inc esi cmp esi,10 jb bp_physics_pair_a xor esi,esi bp_physics_substep_limits: bt rack,esi jnc @F invoke BowlingPlayTether3D,esi invoke BowlingPlayDeckBounds3D,esi @@: inc esi cmp esi,10 jb bp_physics_substep_limits inc substep cmp substep,4 jb bp_physics_substep xor esi,esi bp_physics_pin: bt rack,esi jnc bp_physics_pin_next mov ecx,246 mov eax,bpPhysicsTicks3D sub eax,bpPinContactTick3D[esi*4] cmp eax,10 jb @F bt bpHitMask3D,esi jnc @F mov ecx,224 @@: mov eax,bpPinVX3D[esi*4] imul eax,ecx sar eax,8 mov bpPinVX3D[esi*4],eax mov eax,bpPinVY3D[esi*4] imul eax,ecx sar eax,8 mov bpPinVY3D[esi*4],eax mov eax,bpPinTilt3D[esi*4] cmp eax,24*256 jae bp_physics_topple mov edx,eax sar edx,6 sub bpPinTiltV3D[esi*4],edx jmp bp_physics_tilt bp_physics_topple: add bpPinTiltV3D[esi*4],160 bp_physics_tilt: mov edx,bpPinTiltV3D[esi*4] imul edx,245 sar edx,8 mov bpPinTiltV3D[esi*4],edx add eax,edx test eax,eax jns @F xor eax,eax mov bpPinTiltV3D[esi*4],0 @@: cmp eax,128*256 jbe @F mov eax,128*256 mov edx,bpPinTiltV3D[esi*4] neg edx sar edx,2 cmp edx,-80 jl bp_physics_bounce xor edx,edx bp_physics_bounce: mov bpPinTiltV3D[esi*4],edx @@: mov bpPinTilt3D[esi*4],eax cmp eax,64*256 jb bp_physics_pin_next bts bpHitMask3D,esi mov bpRadius3D[esi*4],48 ; Slow rolling yaw, independent of the fall's vertical angle. mov ecx,bpPinSpin3D[esi*4] and ecx,511 mov eax,bpPinAxisX3D[esi*4] imul tableCos[ecx*4] shrd eax,edx,16 mov ebx,eax mov eax,bpPinAxisY3D[esi*4] imul tableSin[ecx*4] shrd eax,edx,16 sub ebx,eax mov eax,bpPinAxisX3D[esi*4] imul tableSin[ecx*4] shrd eax,edx,16 mov edi,eax mov eax,bpPinAxisY3D[esi*4] imul tableCos[ecx*4] shrd eax,edx,16 add eax,edi mov bpPinAxisY3D[esi*4],eax mov bpPinAxisX3D[esi*4],ebx invoke NormalizeBowlingPinAxis3D,esi mov eax,bpPinSpin3D[esi*4] imul eax,230 test eax,eax jns @F add eax,255 @@: sar eax,8 mov bpPinSpin3D[esi*4],eax bp_physics_pin_next: bt rack,esi jnc @F invoke BowlingPlayTether3D,esi invoke BowlingPlayDeckBounds3D,esi @@: inc esi cmp esi,10 jb bp_physics_pin mov eax,bpPinX3D[40] mov bpBallX3D,eax mov eax,bpPinY3D[40] mov bpBallY3D,eax mov eax,bpPinVX3D[40] mov bpBallVX3D,eax mov eax,bpPinVY3D[40] mov bpBallVY3D,eax inc bpPhysicsTicks3D cmp bpBallY3D,3*FP_1 jge @F inc bpEndTicks3D @@: ret BowlingPlayStep3D ENDP BowlingPlayReady3D PROC uses esi cmp bpPhysicsTicks3D,900 jae bp_physics_ready cmp bpEndTicks3D,100 jb bp_physics_not_ready xor esi,esi bp_physics_quiet: mov eax,bpPinVX3D[esi*4] cdq xor eax,edx sub eax,edx cmp eax,96 ja bp_physics_not_ready mov eax,bpPinTilt3D[esi*4] cmp eax,128*256 jae @F cmp eax,24*256 jae bp_physics_not_ready mov eax,bpPinTiltV3D[esi*4] cdq xor eax,edx sub eax,edx cmp eax,32 ja bp_physics_not_ready @@: mov eax,bpPinVY3D[esi*4] cdq xor eax,edx sub eax,edx cmp eax,96 ja bp_physics_not_ready inc esi cmp esi,10 jb bp_physics_quiet bp_physics_ready: mov eax,1 ret bp_physics_not_ready: xor eax,eax ret BowlingPlayReady3D ENDP