forked from MightyPork/crsn
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
This commit is contained in:
@@ -3,22 +3,25 @@
|
||||
(sc-opt SCREEN_AUTOBLIT 0)
|
||||
(def W 1024)
|
||||
(def H 768)
|
||||
(def MAXITER 50)
|
||||
(sym MAXITER g0)
|
||||
(ld MAXITER 50)
|
||||
|
||||
(lds @cout "Interactive Mandelbrot\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")
|
||||
|
||||
(sym asciigr r10)
|
||||
|
||||
(sym mb_x r2)
|
||||
(sym mb_y r3)
|
||||
(sym mb_s r4)
|
||||
(sym mb_row r5)
|
||||
(sym mb_x r7)
|
||||
(sym mb_y r8)
|
||||
(sym mb_s r9)
|
||||
(sym mb_row r10)
|
||||
|
||||
; 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
|
||||
(def COL_SKIP 8)
|
||||
@@ -26,9 +29,9 @@
|
||||
; 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)
|
||||
(sym mb_skip_table_x r12)
|
||||
(sym mb_skip_table_y r13)
|
||||
(sym mb_size_table r14)
|
||||
(mkbf mb_skip_table_x (
|
||||
0 4 0 4 2 6 0 2 4 6 2 6 0 2 4 6
|
||||
; 8x8 grid
|
||||
@@ -60,10 +63,15 @@
|
||||
(ld mb_x 0.0)
|
||||
(ld mb_y 0.0)
|
||||
(ld mb_s 1.0)
|
||||
(sym did_change r14)
|
||||
(sym is_first_render r15)
|
||||
(sym did_change r15)
|
||||
(sym is_first_render r6)
|
||||
(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
|
||||
; size - pixel size
|
||||
; col - column offset
|
||||
@@ -72,11 +80,6 @@
|
||||
; 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)
|
||||
@@ -87,7 +90,7 @@
|
||||
(rcmp res0 1 r0
|
||||
(eq?
|
||||
(mod r0 res0 16)
|
||||
(bfrd r0 @gradient r0)
|
||||
(bfrd r0 @GRADIENT r0)
|
||||
)
|
||||
(else? (ld r0 0))
|
||||
)
|
||||
@@ -96,96 +99,134 @@
|
||||
(cmp x W)
|
||||
(j.lt :col)
|
||||
(sc-blit)
|
||||
(ret))
|
||||
(ret)
|
||||
)
|
||||
|
||||
(:slp)
|
||||
(sc-poll)
|
||||
; did_change -- did the user interact during this frame?
|
||||
(ld did_change 0)
|
||||
(:loop)
|
||||
(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)
|
||||
(sym pstep r2)
|
||||
(sym zstep r3)
|
||||
(ld pstep PAN_STEP)
|
||||
(ld zstep ZOOM_STEP)
|
||||
(sc-key _ KEY_ShiftL (nz?
|
||||
; turbo mode
|
||||
(fmul pstep 5.0)
|
||||
(fmul zstep 5.0)
|
||||
))
|
||||
(fadd zstep 1.0)
|
||||
|
||||
; A <
|
||||
(sc-key r0 KEY_A)
|
||||
(j.z :a_not_pressed)
|
||||
(fsub mb_x r1)
|
||||
(ld did_change 1)
|
||||
(:a_not_pressed)
|
||||
; scaled movement speed
|
||||
(fdiv pstep mb_s)
|
||||
|
||||
; W ^
|
||||
(sc-key r0 KEY_W)
|
||||
(j.z :w_not_pressed)
|
||||
(fsub mb_y r1)
|
||||
(ld did_change 1)
|
||||
(:w_not_pressed)
|
||||
(tst is_first_render (z?
|
||||
; A <
|
||||
(sc-key _ KEY_A (nz?
|
||||
(fsub mb_x pstep)
|
||||
(ld did_change 1)
|
||||
(lds @cout "Pan left\n")
|
||||
))
|
||||
|
||||
; S v
|
||||
(sc-key r0 KEY_S)
|
||||
(j.z :s_not_pressed)
|
||||
(fadd mb_y r1)
|
||||
(ld did_change 1)
|
||||
(:s_not_pressed)
|
||||
; W ^
|
||||
(sc-key _ KEY_W (nz?
|
||||
(fsub mb_y pstep)
|
||||
(ld did_change 1)
|
||||
(lds @cout "Pan up\n")
|
||||
))
|
||||
|
||||
; D >
|
||||
(sc-key r0 KEY_D)
|
||||
(j.z :d_not_pressed)
|
||||
(fadd mb_x r1)
|
||||
(ld did_change 1)
|
||||
(:d_not_pressed)
|
||||
; S v
|
||||
(sc-key _ KEY_S (nz?
|
||||
(fadd mb_y pstep)
|
||||
(ld did_change 1)
|
||||
(lds @cout "Pan down\n")
|
||||
))
|
||||
|
||||
; Q +
|
||||
(sc-key r0 KEY_Q)
|
||||
(j.z :q_not_pressed)
|
||||
(fmul mb_s 1.01)
|
||||
(ld did_change 1)
|
||||
(:q_not_pressed)
|
||||
; D >
|
||||
(sc-key _ KEY_D (nz?
|
||||
(fadd mb_x pstep)
|
||||
(ld did_change 1)
|
||||
(lds @cout "Pan right\n")
|
||||
))
|
||||
|
||||
; E -
|
||||
(sc-key r0 KEY_E)
|
||||
(j.z :e_not_pressed)
|
||||
(fdiv mb_s 1.01)
|
||||
(ld did_change 1)
|
||||
(:e_not_pressed)
|
||||
; Q +
|
||||
(sc-key r0 KEY_Q (nz?
|
||||
(fmul mb_s zstep)
|
||||
(ld did_change 1)
|
||||
(lds @cout "Zoom in\n")
|
||||
))
|
||||
|
||||
(cmp did_change 0)
|
||||
(j.eq :did_not_move)
|
||||
; if something changed...
|
||||
; E -
|
||||
(sc-key r0 KEY_E (nz?
|
||||
(fdiv mb_s zstep)
|
||||
(ld did_change 1)
|
||||
(lds @cout "Zoom out\n")
|
||||
))
|
||||
|
||||
; 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)
|
||||
; R iter+
|
||||
(sc-key r0 KEY_R (nz?
|
||||
(add MAXITER 50)
|
||||
(lds @cout "ITER=") (call printnum MAXITER) (ld @cout '\n')
|
||||
(mslp 200) ; Avoid unexpected rapid change
|
||||
))
|
||||
|
||||
(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)
|
||||
; F iter-
|
||||
(sc-key r0 KEY_F (nz?
|
||||
(cmp MAXITER 50)
|
||||
(sub.gt MAXITER 50)
|
||||
(lds @cout "ITER=") (call printnum MAXITER) (ld @cout '\n')
|
||||
(mslp 200) ; Avoid unexpected rapid change
|
||||
))
|
||||
|
||||
; 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)
|
||||
; G force redraw
|
||||
(sc-key r0 KEY_G (nz?
|
||||
(ld did_change 1)
|
||||
))
|
||||
|
||||
(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)
|
||||
(tst did_change (nz?
|
||||
; 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)
|
||||
; Start from top
|
||||
(ld mb_row 0)
|
||||
))
|
||||
))
|
||||
(unsym pstep)
|
||||
(unsym zstep)
|
||||
|
||||
(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)
|
||||
(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
|
||||
(sym x0 r7)
|
||||
@@ -239,5 +280,21 @@
|
||||
(:end)
|
||||
(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)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user