Add interactive mandelbrot example #24

Merged
MightyPork merged 2 commits from cpsdqs/crsn:master into master 3 years ago
  1. 243
      examples/mandelbrot/mandelbrot-interactive.csn

@ -0,0 +1,243 @@
(
(sc-init 1024 768)
(sc-opt SCREEN_AUTOBLIT 0)
(def W 1024)
(def H 768)
(def MAXITER 50)
(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)
; index into the skip/size table
(sym mb_skip_index r6)
; size of big pixels
(def COL_SKIP 8)
(def ROW_SKIP 8)
; incrementally renders 1x1, 2x2, 4x4, ...
(def MB_SKIP_TABLE_SIZE 80)
(def MB_SKIP_REPEAT_INDEX 16)
(sym mb_skip_table_x r7)
(sym mb_skip_table_y r8)
(sym mb_size_table r12)
(mkbf mb_skip_table_x (
0 4 0 4 2 6 0 2 4 6 2 6 0 2 4 6
; 8x8 grid
1 3 5 7 1 3 5 7 1 3 5 7 1 3 5 7
0 2 4 6 0 2 4 6 0 2 4 6 0 2 4 6
1 3 5 7 1 3 5 7 1 3 5 7 1 3 5 7
; do top left pixels again
0 2 4 6 0 2 4 6 0 2 4 6 0 2 4 6
))
(mkbf mb_skip_table_y (
0 0 4 4 0 0 2 2 2 2 4 4 6 6 6 6
; 8x8 grid
0 0 0 0 2 2 2 2 4 4 4 4 6 6 6 6
1 1 1 1 3 3 3 3 5 5 5 5 7 7 7 7
1 1 1 1 3 3 3 3 5 5 5 5 7 7 7 7
; do top left pixels again
0 0 0 0 2 2 2 2 4 4 4 4 6 6 6 6
))
(mkbf mb_size_table (
8 4 4 4 2 2 2 2 2 2 2 2 2 2 2 2
; 8x8 grid
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
; do top left pixels again
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
))
(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
; size - pixel size
; col - column offset
; px - offset x
; py - offset y
; scale - scaling
; row - row position
(proc render_row size 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)
(:col)
(call pixel x y px py scale)
(sub r0 MAXITER 1)
(rcmp res0 1 r0
(eq?
(mod r0 res0 16)
(bfrd r0 @gradient r0)
)
(else? (ld r0 0))
)
(sc-rect x y size size r0)
(add x COL_SKIP)
(cmp x W)
(j.lt :col)
(sc-blit)
(ret))
(:slp)
(sc-poll)
; 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)
(:a_not_pressed)
; W ^
(sc-key r0 KEY_W)
(j.z :w_not_pressed)
(fsub mb_y r1)
(ld did_change 1)
(:w_not_pressed)
; S v
(sc-key r0 KEY_S)
(j.z :s_not_pressed)
(fadd mb_y r1)
(ld did_change 1)
(:s_not_pressed)
; D >
(sc-key r0 KEY_D)
(j.z :d_not_pressed)
(fadd mb_x r1)
(ld did_change 1)
(:d_not_pressed)
; Q +
(sc-key r0 KEY_Q)
(j.z :q_not_pressed)
(fmul mb_s 1.01)
(ld did_change 1)
(:q_not_pressed)
; E -
(sc-key r0 KEY_E)
(j.z :e_not_pressed)
(fdiv mb_s 1.01)
(ld did_change 1)
(:e_not_pressed)
(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_skip_index 0)
(:did_not_move)
(sym mb_col_skip r9)
(sym mb_row_skip r11)
(bfrd mb_col_skip @mb_skip_table_x mb_skip_index)
(bfrd mb_row_skip @mb_skip_table_y mb_skip_index)
(bfrd r1 @mb_size_table mb_skip_index)
; render row mb_row + row skip
(ld r0 mb_row)
(add r0 mb_row_skip)
(call render_row r1 mb_col_skip mb_x mb_y mb_s r0)
(cmp mb_row H)
(j.ge :render_done)
; if mb_row < H
(add mb_row ROW_SKIP)
(j :render_not_done)
(:render_done)
; otherwise, this frame is done
(ld mb_row 0)
(add mb_skip_index 1)
(ld is_first_render 0)
(cmp mb_skip_index MB_SKIP_TABLE_SIZE)
; if skip index is out of bounds, go back to repeating area
(j.lt :not_end)
(ld mb_skip_index MB_SKIP_REPEAT_INDEX)
(:not_end)
(:render_not_done)
(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)
(:iter)
(cmp iter MAXITER)
(j.eq :end)
(fmul r0 x x)
(fmul r1 y y)
(fadd r2 r1)
(fcmp r2 4.0)
(j.gt :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)
(:end)
(ret iter)
)
)
Loading…
Cancel
Save