aboutsummaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/render.v157
1 files changed, 157 insertions, 0 deletions
diff --git a/render/render.v b/render/render.v
new file mode 100644
index 0000000..910e524
--- /dev/null
+++ b/render/render.v
@@ -0,0 +1,157 @@
+module render
+
+import os
+import math
+
+@[packed]
+pub struct SpaceBody {
+pub mut:
+ id u32
+ parent_id u32
+ rel_x i64
+ rel_y i64
+ rel_z i64
+ radius u32
+ body_type u8
+ flags [3]u8
+ comment [24]u8
+}
+
+struct Color {
+ r u8
+ g u8
+ b u8
+}
+
+fn get_abs_x(id u32, bodies map[u32]SpaceBody) i64 {
+ if id == 0 || id !in bodies {
+ return 0
+ }
+ body := bodies[id]
+ if body.parent_id == 0 {
+ return body.rel_x
+ }
+ return body.rel_x + get_abs_x(body.parent_id, bodies)
+}
+
+pub fn draw_bodies_to_bmp(bodies []SpaceBody, output_path string, width int, height int) ! {
+ center_y := height / 2
+
+ mut body_map := map[u32]SpaceBody{}
+ for body in bodies {
+ body_map[body.id] = body
+ }
+
+ mut max_abs_x := f64(1)
+ for body in bodies {
+ abs_x := math.abs(f64(get_abs_x(body.id, body_map)))
+ if abs_x > max_abs_x {
+ max_abs_x = abs_x
+ }
+ }
+
+ mut pixels := []u8{len: width * height * 3, init: 10}
+
+ set_pixel := fn (mut px []u8, w int, h int, x int, y int, color Color) {
+ if x >= 0 && x < w && y >= 0 && y < h {
+ idx := (y * w + x) * 3
+ px[idx] = color.r
+ px[idx + 1] = color.g
+ px[idx + 2] = color.b
+ }
+ }
+
+ for body in bodies {
+ abs_x := f64(get_abs_x(body.id, body_map))
+
+ norm_x := math.sqrt(abs_x / max_abs_x)
+ px_x := int(50 + norm_x * f64(width - 100))
+
+ mut col := Color{r: 255, g: 255, b: 255}
+ mut draw_radius := 3
+
+ match body.body_type {
+ 1 {
+ col = Color{r: 255, g: 220, b: 50}
+ draw_radius = 12
+ }
+ 2 {
+ col = Color{r: 100, g: 180, b: 255}
+ draw_radius = 5
+ }
+ 3 {
+ col = Color{r: 180, g: 180, b: 180}
+ draw_radius = 2
+ }
+ 4 {
+ col = Color{r: 200, g: 130, b: 100}
+ draw_radius = 3
+ }
+ else {}
+ }
+
+ for dy := -draw_radius; dy <= draw_radius; dy++ {
+ for dx := -draw_radius; dx <= draw_radius; dx++ {
+ if dx * dx + dy * dy <= draw_radius * draw_radius {
+ set_pixel(mut pixels, width, height, px_x + dx, center_y + dy, col)
+ }
+ }
+ }
+ }
+
+ save_bmp(output_path, width, height, pixels)!
+}
+
+fn save_bmp(path string, width int, height int, rgb_pixels []u8) ! {
+ file_header_size := 14
+ info_header_size := 40
+ row_padding := (4 - (width * 3) % 4) % 4
+ pixel_array_size := (width * 3 + row_padding) * height
+ file_size := file_header_size + info_header_size + pixel_array_size
+
+ mut buf := []u8{cap: file_size}
+
+ // BMP Header
+ buf << `B`
+ buf << `M`
+ buf << u32_to_bytes(u32(file_size))
+ buf << [u8(0), 0, 0, 0]
+ buf << u32_to_bytes(u32(file_header_size + info_header_size))
+
+ // DIB Header
+ buf << u32_to_bytes(u32(info_header_size))
+ buf << i32_to_bytes(i32(width))
+ buf << i32_to_bytes(i32(-height))
+ buf << [u8(1), 0]
+ buf << [u8(24), 0]
+ buf << u32_to_bytes(0)
+ buf << u32_to_bytes(u32(pixel_array_size))
+ buf << u32_to_bytes(2835)
+ buf << u32_to_bytes(2835)
+ buf << u32_to_bytes(0)
+ buf << u32_to_bytes(0)
+
+ // Pixeldaten (BGR-Reihenfolge)
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ idx := (y * width + x) * 3
+ buf << rgb_pixels[idx + 2] // B
+ buf << rgb_pixels[idx + 1] // G
+ buf << rgb_pixels[idx] // R
+ }
+ for p := 0; p < row_padding; p++ {
+ buf << u8(0)
+ }
+ }
+
+ os.write_file(path, buf.bytestr())!
+}
+
+fn u32_to_bytes(val u32) []u8 {
+ return [u8(val & 0xFF), u8((val >> 8) & 0xFF), u8((val >> 16) & 0xFF), u8((val >> 24) & 0xFF)]
+}
+
+fn i32_to_bytes(val i32) []u8 {
+ u := u32(val)
+ return [u8(u & 0xFF), u8((u >> 8) & 0xFF), u8((u >> 16) & 0xFF), u8((u >> 24) & 0xFF)]
+}