EBLAN_ENGINE/include/engine_math.inc
Artvasil09 a1d1baa869 feat: complete engine and editor subsystems (Stages 1-5 from TODO_ARTEM)
- Stage 1: Eliminate fish-eye distortion with precomputed tangential ray offset table and fractional DDA depth
- Stage 2: Full asset management in EblanStudio (stb_image/stb_image_write, 128x128 BGRA texture packaging, WAV sound manager)
- Stage 3: Multi-level room streaming, LevelTransition/CELL_PORTAL trigger system, 16-frame screen fade to black
- Stage 4: 60Hz cutscene engine in pure x86 ASM (v4 binary track, waypoint camera motion, shortest-arc pan, CP1251 Russian subtitles, letterbox overlay, audio)
- Stage 5: EblanStudio cutscene timeline (F6) and windowless Live ASM Viewport over shared-memory IPC directly rendered into DX11
- Tooling & Tests: comprehensive regression test suite (94 editor + 107 engine tests), IPC tests, and cutscene demo
2026-10-22 16:24:22 +03:00

147 lines
4.2 KiB
PHP

; ==============================================================================
; EBLAN ENGINE - Math, Fixed-Point Trigonometry & RNG
; ==============================================================================
.data
fAngleDiv REAL4 256.0
fFixedScale REAL4 65536.0
fScreenHalfW REAL4 160.0
fTanHalfFov REAL4 0.66817864 ; tan(48 * PI / 256) = tan(33.75 deg)
fRadToAngle REAL4 81.48733 ; 256.0 / PI
.code
; ------------------------------------------------------------------------------
; InitMathTables: Builds 512-entry Sin & Cos tables in 16.16 fixed point,
; and 320-entry tangential ray angle offset table for flat-plane projection.
; ------------------------------------------------------------------------------
InitMathTables PROC uses eax ecx edi
LOCAL curVal:DWORD
; 1. Generate 512-entry Sin/Cos tables
mov ecx, 0
init_angle_loop:
mov curVal, ecx
fldpi
fimul curVal
fdiv fAngleDiv ; st(0) = (angle * PI) / 256
fsincos ; st(0) = cos, st(1) = sin
; Process Cosine
fmul fFixedScale
fistp DWORD PTR [tableCos + ecx*4]
; Process Sine
fmul fFixedScale
fistp DWORD PTR [tableSin + ecx*4]
inc ecx
cmp ecx, ANGLE_512
jl init_angle_loop
; 2. Generate 320-entry Ray Angle Offset table (tangential perspective correction)
; and precomputed cosine table for instant fish-eye correction.
; angleOffset = round( atan(((x - 160.0) / 160.0) * tan(FOV/2)) * (256.0 / PI) )
mov ecx, 0
init_ray_loop:
mov curVal, ecx
fild curVal ; st(0) = x
fsub fScreenHalfW ; st(0) = x - 160.0
fdiv fScreenHalfW ; st(0) = (x - 160.0) / 160.0 = cameraX
fmul fTanHalfFov ; st(0) = cameraX * tan(FOV/2)
fld1 ; st(0) = 1.0, st(1) = cameraX * tan(FOV/2)
fpatan ; st(0) = atan(st(1)/st(0)) = radOffset
fmul fRadToAngle ; st(0) = radOffset * (256.0 / PI)
fistp DWORD PTR [tableRayAngleOffset + ecx*4]
; Precompute tableRayCos[ecx] = cos(angleOffset)
mov eax, DWORD PTR [tableRayAngleOffset + ecx*4]
and eax, ANGLE_MASK
mov edx, [tableCos + eax*4]
mov DWORD PTR [tableRayCos + ecx*4], edx
inc ecx
cmp ecx, SCREEN_W
jl init_ray_loop
ret
InitMathTables ENDP
; ------------------------------------------------------------------------------
; RandomRange: Generates pseudo-random uint in [0, maxVal-1]
; Input: maxVal (eax)
; Output: eax
; ------------------------------------------------------------------------------
RandomRange PROC uses ecx edx, maxVal:DWORD
cmp maxVal, 1
jle rand_zero
mov eax, rngSeed
imul eax, 1103515245
add eax, 12345
mov rngSeed, eax
shr eax, 16
xor edx, edx
div maxVal
mov eax, edx
ret
rand_zero:
xor eax, eax
ret
RandomRange ENDP
; ------------------------------------------------------------------------------
; FixedMul: Multiplies two 16.16 fixed-point numbers
; Input: a, b
; Output: eax = (a * b) >> 16
; ------------------------------------------------------------------------------
FixedMul PROC uses edx, valA:DWORD, valB:DWORD
mov eax, valA
imul valB
shrd eax, edx, 16
ret
FixedMul ENDP
; ------------------------------------------------------------------------------
; FixedDiv: Divides two 16.16 fixed-point numbers
; Input: a, b
; Output: eax = (a << 16) / b
; ------------------------------------------------------------------------------
FixedDiv PROC uses ebx edx, valA:DWORD, valB:DWORD
mov eax, valA
mov ebx, valB
test ebx, ebx
jz div_zero
cdq
shld edx, eax, 16
shl eax, 16
idiv ebx
ret
div_zero:
mov eax, 7FFFFFFFh ; Return max int on divide-by-zero
ret
FixedDiv ENDP
; ------------------------------------------------------------------------------
; ClampInt: Clamps value between minVal and maxVal
; ------------------------------------------------------------------------------
ClampInt PROC val:DWORD, minVal:DWORD, maxVal:DWORD
mov eax, val
cmp eax, minVal
jge @F
mov eax, minVal
ret
@@:
cmp eax, maxVal
jle @F
mov eax, maxVal
@@:
ret
ClampInt ENDP