Mandelbrot interactive fixes + improvements

- fix memory leak caused by gradient table
- refactor to conditional branches
- reset drawing on move
- add keys to change itercount and force redraw
master
Ondřej Hruška 4 years ago
parent 191ba495f2
commit 506a4e42a2
Signed by untrusted user: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 277
      examples/mandelbrot/mandelbrot-interactive.csn

@ -3,22 +3,25 @@
(sc-opt SCREEN_AUTOBLIT 0) (sc-opt SCREEN_AUTOBLIT 0)
(def W 1024) (def W 1024)
(def H 768) (def H 768)
(def MAXITER 50) (sym MAXITER g0)
(ld MAXITER 50)
(lds @cout "Interactive Mandelbrot\n") (lds @cout "Interactive Mandelbrot\n")
(lds @cout "----------------------\n") (lds @cout "----------------------\n")
(lds @cout "Navigate using WASD, zoom using Q/E\n") (lds @cout "Navigate using WASD, zoom: Q+/E-, detail: R+/F-; fast move/zoom: LShift, force redraw: G\n")
(lds @cout "To get a high-res image, stop interacting for while\n") (lds @cout "To get a high-res image, stop interacting for while\n")
(sym asciigr r10) (sym mb_x r7)
(sym mb_y r8)
(sym mb_x r2) (sym mb_s r9)
(sym mb_y r3) (sym mb_row r10)
(sym mb_s r4)
(sym mb_row r5)
; index into the skip/size table ; index into the skip/size table
(sym mb_skip_index r6) (sym mb_skip_index r11)
; Interactive movement speed
(def ZOOM_STEP 0.1)
(def PAN_STEP 0.3)
; size of big pixels ; size of big pixels
(def COL_SKIP 8) (def COL_SKIP 8)
@ -26,9 +29,9 @@
; incrementally renders 1x1, 2x2, 4x4, ... ; incrementally renders 1x1, 2x2, 4x4, ...
(def MB_SKIP_TABLE_SIZE 80) (def MB_SKIP_TABLE_SIZE 80)
(def MB_SKIP_REPEAT_INDEX 16) (def MB_SKIP_REPEAT_INDEX 16)
(sym mb_skip_table_x r7) (sym mb_skip_table_x r12)
(sym mb_skip_table_y r8) (sym mb_skip_table_y r13)
(sym mb_size_table r12) (sym mb_size_table r14)
(mkbf mb_skip_table_x ( (mkbf mb_skip_table_x (
0 4 0 4 2 6 0 2 4 6 2 6 0 2 4 6 0 4 0 4 2 6 0 2 4 6 2 6 0 2 4 6
; 8x8 grid ; 8x8 grid
@ -60,10 +63,15 @@
(ld mb_x 0.0) (ld mb_x 0.0)
(ld mb_y 0.0) (ld mb_y 0.0)
(ld mb_s 1.0) (ld mb_s 1.0)
(sym did_change r14) (sym did_change r15)
(sym is_first_render r15) (sym is_first_render r6)
(ld is_first_render 1) (ld is_first_render 1)
(sym GRADIENT g1)
(mkbf GRADIENT (
0x421e0f 0x19071a 0x09012f 0x040449 0x000764 0x0c2c8a 0x1852b1 0x397dd1
0x86b5e5 0xd3ecf8 0xf1e9bf 0xf8c95f 0xffaa00 0xcc8000 0x995700 0x6a3403))
; render row ; render row
; size - pixel size ; size - pixel size
; col - column offset ; col - column offset
@ -72,11 +80,6 @@
; scale - scaling ; scale - scaling
; row - row position ; row - row position
(proc render_row size col px py scale row (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 x r7)
(sym y r8) (sym y r8)
(add y row) (add y row)
@ -87,7 +90,7 @@
(rcmp res0 1 r0 (rcmp res0 1 r0
(eq? (eq?
(mod r0 res0 16) (mod r0 res0 16)
(bfrd r0 @gradient r0) (bfrd r0 @GRADIENT r0)
) )
(else? (ld r0 0)) (else? (ld r0 0))
) )
@ -96,96 +99,134 @@
(cmp x W) (cmp x W)
(j.lt :col) (j.lt :col)
(sc-blit) (sc-blit)
(ret)) (ret)
)
(:slp)
(sc-poll) (:loop)
; did_change -- did the user interact during this frame? (sc-poll)
(ld did_change 0) ; did_change -- did the user interact during this frame?
(ld did_change 0)
; scaled movement speed in r1
(fdiv r1 0.03 mb_s) (sym pstep r2)
(sym zstep r3)
; A < (ld pstep PAN_STEP)
(sc-key r0 KEY_A) (ld zstep ZOOM_STEP)
(j.z :a_not_pressed) (sc-key _ KEY_ShiftL (nz?
(fsub mb_x r1) ; turbo mode
(ld did_change 1) (fmul pstep 5.0)
(:a_not_pressed) (fmul zstep 5.0)
))
; W ^ (fadd zstep 1.0)
(sc-key r0 KEY_W)
(j.z :w_not_pressed) ; scaled movement speed
(fsub mb_y r1) (fdiv pstep mb_s)
(ld did_change 1)
(:w_not_pressed) (tst is_first_render (z?
; A <
; S v (sc-key _ KEY_A (nz?
(sc-key r0 KEY_S) (fsub mb_x pstep)
(j.z :s_not_pressed) (ld did_change 1)
(fadd mb_y r1) (lds @cout "Pan left\n")
(ld did_change 1) ))
(:s_not_pressed)
; W ^
; D > (sc-key _ KEY_W (nz?
(sc-key r0 KEY_D) (fsub mb_y pstep)
(j.z :d_not_pressed) (ld did_change 1)
(fadd mb_x r1) (lds @cout "Pan up\n")
(ld did_change 1) ))
(:d_not_pressed)
; S v
; Q + (sc-key _ KEY_S (nz?
(sc-key r0 KEY_Q) (fadd mb_y pstep)
(j.z :q_not_pressed) (ld did_change 1)
(fmul mb_s 1.01) (lds @cout "Pan down\n")
(ld did_change 1) ))
(:q_not_pressed)
; D >
; E - (sc-key _ KEY_D (nz?
(sc-key r0 KEY_E) (fadd mb_x pstep)
(j.z :e_not_pressed) (ld did_change 1)
(fdiv mb_s 1.01) (lds @cout "Pan right\n")
(ld did_change 1) ))
(:e_not_pressed)
; Q +
(cmp did_change 0) (sc-key r0 KEY_Q (nz?
(j.eq :did_not_move) (fmul mb_s zstep)
; if something changed... (ld did_change 1)
(lds @cout "Zoom in\n")
; mark this as a first render and reset col_skip and row_skip ))
(ld is_first_render 1)
(ld mb_skip_index 0) ; E -
(:did_not_move) (sc-key r0 KEY_E (nz?
(fdiv mb_s zstep)
(sym mb_col_skip r9) (ld did_change 1)
(sym mb_row_skip r11) (lds @cout "Zoom out\n")
(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) ; R iter+
(sc-key r0 KEY_R (nz?
; render row mb_row + row skip (add MAXITER 50)
(ld r0 mb_row) (lds @cout "ITER=") (call printnum MAXITER) (ld @cout '\n')
(add r0 mb_row_skip) (mslp 200) ; Avoid unexpected rapid change
(call render_row r1 mb_col_skip mb_x mb_y mb_s r0) ))
(cmp mb_row H) ; F iter-
(j.ge :render_done) (sc-key r0 KEY_F (nz?
; if mb_row < H (cmp MAXITER 50)
(add mb_row ROW_SKIP) (sub.gt MAXITER 50)
(j :render_not_done) (lds @cout "ITER=") (call printnum MAXITER) (ld @cout '\n')
(:render_done) (mslp 200) ; Avoid unexpected rapid change
; otherwise, this frame is done ))
(ld mb_row 0)
(add mb_skip_index 1) ; G force redraw
(ld is_first_render 0) (sc-key r0 KEY_G (nz?
(ld did_change 1)
(cmp mb_skip_index MB_SKIP_TABLE_SIZE) ))
; if skip index is out of bounds, go back to repeating area
(j.lt :not_end) (tst did_change (nz?
(ld mb_skip_index MB_SKIP_REPEAT_INDEX) ; something changed...
(:not_end) ; mark this as a first render and reset col_skip and row_skip
(:render_not_done) (ld is_first_render 1)
(j :slp) (ld mb_skip_index 0)
; Start from top
(ld mb_row 0)
))
))
(unsym pstep)
(unsym zstep)
(sym mb_col_skip r2)
(sym mb_row_skip r3)
(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)
(unsym mb_col_skip)
(unsym mb_row_skip)
(cmp mb_row H
(lt?
; if mb_row < H
(add mb_row ROW_SKIP)
)
(else?
; 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 (ge?
; if skip index is out of bounds, go back to repeating area
(ld mb_skip_index MB_SKIP_REPEAT_INDEX)
))
)
)
(j :loop)
(proc pixel xi yi off_x off_y scale (proc pixel xi yi off_x off_y scale
(sym x0 r7) (sym x0 r7)
@ -239,5 +280,21 @@
(:end) (:end)
(ret iter) (ret iter)
) )
(proc printnum num
(mkbf r15)
(ld r1 num)
(tst r1 (<0? (mul r1 -1)))
(:next)
(mod r0 r1 10)
(add r0 '0')
(bfrpush @r15 r0)
(div r1 10 (z?
(tst num (<0? (bfrpush @r15 '-')))
(lds @cout @r15)
(del @r15)
(ret)))
(j :next)
)
) )

Loading…
Cancel
Save