diff options
Diffstat (limited to 'render/render.v')
| -rw-r--r-- | render/render.v | 157 |
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)] +} |
