Add interactive mandelbrot example

cpsdqs 4 years ago
parent 40d4b272e4
commit ae82157d19
Signed by untrusted user: cpsdqs
GPG Key ID: 3F59586BB7448DD1
  1. 212

@ -0,0 +1,212 @@
(sc-init 1024 768)
(def W 1024)
(def H 768)
(def MAXITER 50)
; size of big pixels
(def COL_SKIP 8)
(def ROW_SKIP 8)
(lds @cout "Interactive Mandelbrot\n")
(lds @cout "----------------------\n")
(lds @cout "Navigate using WASD, zoom using Q/E\n")
(lds @cout "To get a high-res image, stop interacting for while\n")
(sym asciigr r10)
(sym mb_x r2)
(sym mb_y r3)
(sym mb_s r4)
(sym mb_row r5)
(sym mb_col_skip r6)
(sym mb_row_skip r7)
(ld mb_x 0.0)
(ld mb_y 0.0)
(ld mb_s 1.0)
(sym did_change r14)
(sym is_first_render r15)
(ld is_first_render 1)
; render row
; big - is this the first render? if yes, use big pixels
; col - mb_col_skip column offset
; px - offset x
; py - offset y
; scale - scaling
; row - row position
(proc render_row big col px py scale row
(sym gradient r9)
(mkbf gradient (
0x421e0f 0x19071a 0x09012f 0x040449 0x000764 0x0c2c8a 0x1852b1 0x397dd1
0x86b5e5 0xd3ecf8 0xf1e9bf 0xf8c95f 0xffaa00 0xcc8000 0x995700 0x6a3403))
(sym x r7)
(sym y r8)
(add y row)
(ld x col)
(call pixel x y px py scale)
(sub r0 MAXITER 1)
(rcmp res0 1 r0
(mod r0 res0 16)
(bfrd r0 @gradient r0)
(else? (ld r0 0))
(cmp big 1)
( :not_big)
(sc-rect x y COL_SKIP ROW_SKIP r0)
(j :was_big)
(sc-wr x y r0)
(add x COL_SKIP)
(cmp x W)
( :col)
; did_change -- did the user interact during this frame?
(ld did_change 0)
; scaled movement speed in r1
(fdiv r1 0.03 mb_s)
; A <
(sc-key r0 KEY_A)
(j.z :a_not_pressed)
(fsub mb_x r1)
(ld did_change 1)
; W ^
(sc-key r0 KEY_W)
(j.z :w_not_pressed)
(fsub mb_y r1)
(ld did_change 1)
; S v
(sc-key r0 KEY_S)
(j.z :s_not_pressed)
(fadd mb_y r1)
(ld did_change 1)
; D >
(sc-key r0 KEY_D)
(j.z :d_not_pressed)
(fadd mb_x r1)
(ld did_change 1)
; Q +
(sc-key r0 KEY_Q)
(j.z :q_not_pressed)
(fmul mb_s 1.01)
(ld did_change 1)
; E -
(sc-key r0 KEY_E)
(j.z :e_not_pressed)
(fdiv mb_s 1.01)
(ld did_change 1)
(cmp did_change 0)
(j.eq :did_not_move)
; if something changed...
; mark this as a first render and reset col_skip and row_skip
(ld is_first_render 1)
(ld mb_col_skip 0)
(ld mb_row_skip 0)
; render row mb_row + mb_row_skip
(ld r0 mb_row)
(add r0 mb_row_skip)
(call render_row is_first_render mb_col_skip mb_x mb_y mb_s r0)
(cmp mb_row H)
( :render_done)
; if mb_row < H
(add mb_row ROW_SKIP)
(j :render_not_done)
; otherwise, this frame is done
(ld mb_row 0)
(add mb_col_skip 1)
(ld is_first_render 0)
(mod mb_col_skip COL_SKIP)
; if mb_col_skip wrapped back to zero increase mb_row_skip
(cmp mb_col_skip 0)
( :not_col)
(add mb_row_skip 1)
(mod mb_row_skip ROW_SKIP)
(j :slp)
(proc pixel xi yi off_x off_y scale
(sym x0 r7)
(sym y0 r8)
(itf x0 xi)
(itf y0 yi)
; Scale to the interesting range x -2.5..1 and y -1..1
(itf r0 W)
(itf r1 H)
(fdiv x0 r0)
(fmul x0 3.5)
(fsub x0 2.5)
(fdiv y0 r1)
(fmul y0 2.4)
(fsub y0 1.2)
(fdiv x0 scale)
(fdiv y0 scale)
(fadd x0 off_x)
(fadd y0 off_y)
(sym x r5)
(sym y r6)
(ld x 0.0)
(ld y 0.0)
(sym iter r4)
(cmp iter MAXITER)
(j.eq :end)
(fmul r0 x x)
(fmul r1 y y)
(fadd r2 r1)
(fcmp r2 4.0)
( :end)
(fsub r2 r0 r1)
(fadd r2 x0)
(fmul r0 x y)
(fmul r0 2.0)
(fadd r0 y0)
(ld y r0)
(ld x r2)
(inc iter)
(j :iter)
(ret iter)