From 3409f5051a11de9ceb905da2fb0e1ddc4d463712 Mon Sep 17 00:00:00 2001 From: peony Date: Sun, 10 Nov 2024 09:03:14 -0600 Subject: [PATCH] Circle rendering support (janky) (#18) circle rendering Reviewed-on: https://git.ablecorp.us/AbleOS/ableos/pulls/18 Co-authored-by: peony Co-committed-by: peony --- sysdata/libraries/render/src/lib.hb | 12 ++- sysdata/libraries/render/src/software.hb | 84 +++++++++++++++++++ .../render_example/src/examples/orbit.hb | 36 ++++++++ sysdata/programs/render_example/src/main.hb | 2 +- sysdata/system_config.toml | 12 +-- 5 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 sysdata/programs/render_example/src/examples/orbit.hb diff --git a/sysdata/libraries/render/src/lib.hb b/sysdata/libraries/render/src/lib.hb index c72b8cd..00279a3 100644 --- a/sysdata/libraries/render/src/lib.hb +++ b/sysdata/libraries/render/src/lib.hb @@ -38,14 +38,20 @@ $light_cyan := Color.(255, 255, 0, 255) put_pixel := mode.put_pixel put_rect := mode.put_rect put_filled_rect := mode.put_filled_rect +put_trirect := mode.put_trirect +put_circle := mode.put_circle +put_filled_circle := mode.put_filled_circle +put_textured_circle := mode.put_textured_circle put_line := mode.put_line +put_vline := mode.put_vline +put_hline := mode.put_hline clear := mode.clear put_surface := mode.put_surface put_text := mode.put_text // thanks peony for these three! -put_trirect := mode.put_trirect -put_vline := mode.put_vline -put_hline := mode.put_hline +//put_trirect := mode.put_trirect +//put_vline := mode.put_vline +//put_hline := mode.put_hline // Display sync := mode.sync \ No newline at end of file diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb index efc8d92..0c4780e 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -251,6 +251,90 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo return } + +put_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void { + x := 0 + y := radius + error := @as(int, 3) - @as(int, @intcast(2 * radius)); + *@inline(indexptr, surface, pos.x + radius, pos.y) = color; + *@inline(indexptr, surface, pos.x - radius, pos.y) = color; + *@inline(indexptr, surface, pos.x, pos.y + radius) = color; + *@inline(indexptr, surface, pos.x, pos.y - radius) = color + + loop if y < x break else { + x += 1 + + if error > 0 { + y -= 1 + error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10 + } else { + error += 4 * @intcast(x) + 6 + }; + *@inline(indexptr, surface, pos.x + x, pos.y + y) = color; + *@inline(indexptr, surface, pos.x + y, pos.y + x) = color; + *@inline(indexptr, surface, pos.x - x, pos.y + y) = color; + *@inline(indexptr, surface, pos.x - y, pos.y + x) = color; + *@inline(indexptr, surface, pos.x + x, pos.y - y) = color; + *@inline(indexptr, surface, pos.x + y, pos.y - x) = color; + *@inline(indexptr, surface, pos.x - x, pos.y - y) = color; + *@inline(indexptr, surface, pos.x - y, pos.y - x) = color + } + + return +} + +put_filled_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void { + x := 0 + y := radius + error := @as(int, 3) - @as(int, @intcast(2 * radius)) + @inline(put_hline, surface, pos.y - x, pos.x - radius, pos.x + radius, color); + *@inline(indexptr, surface, pos.x, pos.y + radius) = color; + *@inline(indexptr, surface, pos.x, pos.y - radius) = color + + loop if y < x break else { + x += 1 + + if error > 0 { + @inline(put_hline, surface, pos.y + y, pos.x - x, pos.x + x, color) + @inline(put_hline, surface, pos.y - y, pos.x - x, pos.x + x, color) + y -= 1 + error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10 + } else { + error += 4 * @intcast(x) + 6 + } + @inline(put_hline, surface, pos.y + x, pos.x - y, pos.x + y, color) + @inline(put_hline, surface, pos.y - x, pos.x - y, pos.x + y, color) + } + + return +} + +put_textured_circle := fn(surface: Surface, source: Surface, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void { + x := 0 + y := radius + error := @as(int, 3) - @as(int, @intcast(2 * radius)) + @inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - y, source_pos.y), @inline(indexptr, surface, pos.x - y, pos.y), 2 * y); + *@inline(indexptr, surface, pos.x, pos.y + y) = *@inline(indexptr, source, source_pos.x, source_pos.y + y); + *@inline(indexptr, surface, pos.x, pos.y - y) = *@inline(indexptr, source, source_pos.x, source_pos.y - y) + + loop if y < x break else { + x += 1 + + if error > 0 { + @inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - x, source_pos.y + y), @inline(indexptr, surface, pos.x - x, pos.y + y), 2 * x) + @inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - x, source_pos.y - y), @inline(indexptr, surface, pos.x - x, pos.y - y), 2 * x) + y -= 1 + error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10 + } else { + error += 4 * @intcast(x) + 6 + } + @inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - y, source_pos.y + x), @inline(indexptr, surface, pos.x - y, pos.y + x), 2 * y) + @inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - y, source_pos.y - x), @inline(indexptr, surface, pos.x - y, pos.y - x), 2 * y) + } + + return +} + utf8_len_table := [u8].(0, 0, 2, 3) put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void { diff --git a/sysdata/programs/render_example/src/examples/orbit.hb b/sysdata/programs/render_example/src/examples/orbit.hb new file mode 100644 index 0000000..84b47e3 --- /dev/null +++ b/sysdata/programs/render_example/src/examples/orbit.hb @@ -0,0 +1,36 @@ +.{Vec2, sin, cos, PI} := @use("../../../../libraries/stn/src/lib.hb").math +render := @use("../../../../libraries/render/src/lib.hb") + +able_bmp := @embed("../../../../assets/able.bmp") +mini_bmp := @embed("../../../../assets/mini.bmp") + +/* expected result: + two textured circles rotating + around one yellow filled circle + with a blue line showing their + 'orbit' */ + +example := fn(): void { + able := render.image.from(@bitcast(&able_bmp)) + mini := render.image.from(@bitcast(&mini_bmp)) + if able == null | mini == null { + return + } + + angle := 0.0 + + screen := render.init(true) + + loop { + render.clear(screen, render.black) + render.put_filled_circle(screen, .(screen.width / 2, screen.height / 2), 128, render.light_yellow) + render.put_circle(screen, .(screen.width / 2, screen.height / 2), 256, render.light_blue) + // Precision issues? + render.put_textured_circle(screen, able, .(able.width / 2, able.height / 2), .(screen.width / 2 + @intcast(@fti(sin(angle) * 256)), screen.height / 2 + @intcast(@fti(cos(angle) * 256))), able.width / 2 - 1) + render.put_textured_circle(screen, mini, .(mini.width / 2, mini.height / 2), .(screen.width / 2 + @intcast(@fti(sin(angle + PI) * 256)), screen.height / 2 + @intcast(@fti(cos(angle + PI) * 256))), mini.width / 2 - 1) + render.sync(screen) + + angle += 0.01 + } + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb index 77cb04c..ab66cfa 100644 --- a/sysdata/programs/render_example/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1 +1 @@ -.{example: main} := @use("./examples/text.hb") \ No newline at end of file +.{example: main} := @use("./examples/orbit.hb") \ No newline at end of file diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml index 1992a80..93bd739 100644 --- a/sysdata/system_config.toml +++ b/sysdata/system_config.toml @@ -22,14 +22,14 @@ resolution = "1024x768x24" [boot.limine.ableos.modules] -# [boot.limine.ableos.modules.render_example] -# path = "boot:///render_example.hbf" +[boot.limine.ableos.modules.render_example] +path = "boot:///render_example.hbf" -[boot.limine.ableos.modules.horizon] -path = "boot:///horizon.hbf" +# [boot.limine.ableos.modules.horizon] +# path = "boot:///horizon.hbf" -[boot.limine.ableos.modules.ps2_mouse_driver] -path = "boot:///ps2_mouse_driver.hbf" +# [boot.limine.ableos.modules.ps2_mouse_driver] +# path = "boot:///ps2_mouse_driver.hbf" # [boot.limine.ableos.modules.ps2_keyboard_driver] # path = "boot:///ps2_keyboard_driver.hbf"