From c4c096c6473ca6825749307f294a778ade185931 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Wed, 28 Apr 2021 23:14:22 -0500 Subject: [PATCH] proper ui; wall particle --- lib/gl/gl_utils.onyx | 2 +- lib/immediate_renderer.onyx | 32 +++++++- lib/shaders/immediate_vertex.glsl | 5 +- site/sand_toy.wasm | Bin 38305 -> 37934 bytes src/sand_toy.onyx | 110 +++++++++++++++++++------ src/simulation.onyx | 130 ++++++++++++++---------------- 6 files changed, 179 insertions(+), 100 deletions(-) diff --git a/lib/gl/gl_utils.onyx b/lib/gl/gl_utils.onyx index b306d5a..29b749f 100644 --- a/lib/gl/gl_utils.onyx +++ b/lib/gl/gl_utils.onyx @@ -1,4 +1,4 @@ -package imgui.gl +package imgui.gl_utils use package core #private_file gl :: package gl diff --git a/lib/immediate_renderer.onyx b/lib/immediate_renderer.onyx index 5a7c315..98343f8 100644 --- a/lib/immediate_renderer.onyx +++ b/lib/immediate_renderer.onyx @@ -3,7 +3,7 @@ package imgui #load "lib/gl/gl_utils" use package core -use package imgui.gl +use package imgui.gl_utils #private_file gl :: package gl Vector2 :: struct { @@ -40,6 +40,9 @@ Immediate_Renderer :: struct { texture_uniform : gl.GLUniformLocation; use_texture_uniform : gl.GLUniformLocation; + view_uniform : gl.GLUniformLocation; + world_uniform : gl.GLUniformLocation; + // Needs to be a multiple of 3!! Default_Max_Verticies :: 1023; @@ -58,6 +61,8 @@ Immediate_Renderer :: struct { texture_uniform = gl.getUniformLocation(shader.program, "u_texture"); use_texture_uniform = gl.getUniformLocation(shader.program, "u_use_texture"); + view_uniform = gl.getUniformLocation(shader.program, "u_view"); + world_uniform = gl.getUniformLocation(shader.program, "u_world"); verticies = memory.make_slice(Immediate_Vertex, max_verticies); memory.set(verticies.data, 0, verticies.count * sizeof Immediate_Vertex); @@ -83,6 +88,14 @@ Immediate_Renderer :: struct { gl.vertexAttribPointer(2, 2, gl.FLOAT, false, sizeof Immediate_Vertex, 6 * sizeof f32); gl.bindBuffer(gl.ARRAY_BUFFER, -1); + + + + // TEMPORARY + gl.uniformMatrix4(world_uniform, false, f32.[ 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 ]); } free :: (use ir: ^Immediate_Renderer) { @@ -112,7 +125,7 @@ Immediate_Renderer :: struct { push_vertex :: proc { // If a color is not provided, the previous color is used. (use ir: ^Immediate_Renderer, position: Vector2) { - push_vertex(ir, position, texture = .{ 0, 0 }, color = verticies[vertex_count - 1].color); + push_vertex(ir, position, color = verticies[vertex_count - 1].color); }, (use ir: ^Immediate_Renderer, position: Vector2, color: Color4, texture: Vector2 = .{0,0}) { @@ -154,6 +167,17 @@ Immediate_Renderer :: struct { gl.uniform1i(texture_uniform, math.max(texture_id, 0)); gl.uniform1i(use_texture_uniform, cast(i32) (texture_id >= 0)); } + + use_ortho_projection :: (use ir: ^Immediate_Renderer, left: f32, right: f32, top: f32, bottom: f32) { + projection_matrix := f32.[ + 2 / (right - left), 0, 0, -(right + left) / (right - left), + 0, 2 / (top - bottom), 0, -(top + bottom) / (top - bottom), + 0, 0, -2, -1, + 0, 0, 0, 1 + ]; + + gl.uniformMatrix4(view_uniform, true, projection_matrix); + } } @@ -192,3 +216,7 @@ immediate_textured_quad :: (position: Vector2, size: Vector2, texture_position: immediate_flush :: () do immediate_renderer->flush(); immediate_set_texture :: (texture_id: i32 = -1) do immediate_renderer->set_texture(texture_id); + +use_ortho_projection :: (left: f32, right: f32, top: f32, bottom: f32) { + immediate_renderer->use_ortho_projection(left, right, top, bottom); +} diff --git a/lib/shaders/immediate_vertex.glsl b/lib/shaders/immediate_vertex.glsl index cf95128..d3fdcab 100644 --- a/lib/shaders/immediate_vertex.glsl +++ b/lib/shaders/immediate_vertex.glsl @@ -4,11 +4,14 @@ layout(location = 0) in vec2 a_vertex; layout(location = 1) in vec4 a_color; layout(location = 2) in vec2 a_texture; +uniform mat4 u_view; +uniform mat4 u_world; + out vec4 v_color; out vec2 v_texture; void main() { - gl_Position = vec4(a_vertex, 0, 1); + gl_Position = u_view * u_world * vec4(a_vertex, 0, 1); v_color = a_color; v_texture = a_texture; diff --git a/site/sand_toy.wasm b/site/sand_toy.wasm index 98b2ec3f07e8393aec3c0de6da2efe904818a548..49bc6f47d2957d2ef9e05b45fad247eaa12d20a2 100644 GIT binary patch delta 13171 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 Rsb46{vRFro#+4n delta 13391 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 1 { - radius := 10.0f; - for i: 100 { - rx := random.float(-1, 1); - ry := random.float(-1, 1); +handle_ui_mouse :: (event: ^events.MouseEvent) { + if event.button == .Left { + selected_particle = Particle.types[cast(u32) math.floor(~~event.pos_x / BAR_HEIGHT)]; + } +} + +spawn_particles :: (x: i32, y: i32, radius: i32, type: Particle.Type, count := 100) { + for i: count { + r := random.float(0, ~~radius); + a := random.float(0, 2 * math.PI); + + dx := r * math.cos(a); + dy := r * math.sin(a); + + particle_set(^particle_board, + get_index(^particle_board, ~~(~~x + dx), ~~(~~y + dy)), + .{ type }); + } +} +remove_particles :: (x: i32, y: i32, radius: i32) { + for yy: y - radius .. y + radius { + for xx: x - radius .. x + radius { particle_set(^particle_board, - get_index(^particle_board, ~~(200 + rx * radius), ~~(100 + ry * radius)), - .{ .Sand }); + get_index(^particle_board, ~~xx, ~~yy), + .{ .Empty }); } } +} +update :: () { update_particles(^particle_board); } @@ -98,21 +124,53 @@ prepare_world_texture :: () { } draw :: () { + use imgui; + prepare_world_texture(); + use_ortho_projection(0, ~~window_width, 0, ~~window_height); gl.clearColor(0, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); - use imgui { immediate_set_texture, immediate_textured_quad, immediate_flush }; - - gl.bindTexture(gl.TEXTURE_2D, world_texture); + draw_selection_bar(); + gl.bindTexture(gl.TEXTURE_2D, world_texture); + immediate_set_texture(0); - immediate_textured_quad(.{ -1, 1 }, .{ 2, -2 }, .{ 0, 0 }, .{ 1, 1 }, color=.{ 1, 1, 1 }); + immediate_textured_quad(.{ 0, BAR_HEIGHT }, .{ ~~window_width, ~~window_height - BAR_HEIGHT }, .{ 0, 0 }, .{ 1, 1 }, color=.{ 1, 1, 1 }); + immediate_set_texture(); immediate_flush(); gl.bindTexture(gl.TEXTURE_2D, -1); + + + draw_selection_bar :: () { + use imgui; + + immediate_quad(.{ 0, 0 }, .{ ~~window_width, BAR_HEIGHT }, color=.{.2,.2,.2}); + + x_off := 4.0f; + for type: Particle.types { + if type == selected_particle { + immediate_quad(.{ x_off - 4, 0 }, .{ BAR_HEIGHT, BAR_HEIGHT }, color=.{1,1,0}); + } + + color := particle_type_to_color(type) |> convert_color(); + immediate_quad(.{ x_off, 4 }, .{ BAR_HEIGHT - 8, BAR_HEIGHT - 8 }, color=color); + + x_off += BAR_HEIGHT; + } + } + + + convert_color :: (use c: Color) -> imgui.Color4 { + return .{ + ~~cast(i32) r / 255.0f, + ~~cast(i32) g / 255.0f, + ~~cast(i32) b / 255.0f, + }; + } } #export "loop" () { diff --git a/src/simulation.onyx b/src/simulation.onyx index d5c68fe..93a12fa 100644 --- a/src/simulation.onyx +++ b/src/simulation.onyx @@ -4,12 +4,13 @@ Color :: struct { Empty :: Color.{ 22, 22, 22 }; Sand :: Color.{ 226, 214, 173 }; Water :: Color.{ 100, 100, 255 }; + Wall :: Color.{ 60, 60, 30 }; r, g, b: u8; } Vec2 :: struct { - zero :: Vec2.{ 0, 0 }; + zero :: Vec2.{ 0, 0 }; up :: Vec2.{ 0, -1 }; down :: Vec2.{ 0, 1 }; left :: Vec2.{ -1, 0 }; @@ -32,7 +33,10 @@ Particle :: struct { Empty; Sand; Water; + Wall; } + + types :: Type.[ .Sand, .Water, .Wall ]; type: Type = .Empty; life: f32 = 0; @@ -43,6 +47,7 @@ particle_type_to_color :: (t: Particle.Type) -> Color { switch t { case .Sand do return .Sand; case .Water do return .Water; + case .Wall do return .Wall; case #default do return .Empty; } } @@ -96,6 +101,7 @@ update_particles :: (use board: ^ParticleBoard) { switch particle_type { case .Sand do update_sand(board, x, y); case .Water do update_water(board, x, y); + case .Wall --- // Walls do not need updating case .Empty --- } } @@ -108,12 +114,43 @@ particle_set :: (use board: ^ParticleBoard, index: i32, particle: Particle) { particles[index] = particle; } +particle_switch :: (use board: ^ParticleBoard, a_index: i32, b_index: i32) { + if a_index < 0 || b_index < 0 do return; + + particles[a_index], particles[b_index] = particles[b_index], particles[a_index]; +} + // This should get inlined by Onyx, when inlining is a thing. get_index :: (use board: ^ParticleBoard, x: i32, y: i32) -> i32 { if x < 0 || y < 0 || x >= width || y >= height do return -1; return y * width + x; } +#private_file +particle_is_liquid :: (type: Particle.Type) -> bool { + switch type { + case .Water do return true; + case #default do return false; + } +} + +#private_file +first_empty :: (use board: ^ParticleBoard, indicies: ..i32) -> i32 { + for index: indicies { + if index < 0 do continue; + + if particles[index].type == .Empty { + return index; + } + } + + return -1; +} + +#private_file +can_sink :: (use board: ^ParticleBoard, below_index: i32) -> bool { + return particle_is_liquid(particles[below_index].type); +} #private_file update_sand :: (use board: ^ParticleBoard, x: i32, y: i32) { @@ -123,34 +160,21 @@ update_sand :: (use board: ^ParticleBoard, x: i32, y: i32) { bl_index := get_index(board, x - 1, y + 1); br_index := get_index(board, x + 1, y + 1); - // NOTE: These do NOT short circuit so we are accessing memory that is not - // technically in our control on the second part of the condition!! This - // does not affect too many things as the accessing does not modify or damage - // the data. - if b_index > 0 && particles[b_index].type == .Empty { - particle_set(board, b_index, particles[index]); + move_to_index := -1; + if time % 2 == 0 { + move_to_index = first_empty(board, b_index, bl_index, br_index); + } else { + move_to_index = first_empty(board, b_index, br_index, bl_index); + } + + if move_to_index != -1 { + particle_set(board, move_to_index, particles[index]); particle_set(board, index, .{ .Empty }); + return; } - else { - if time % 2 == 0 { - if bl_index > 0 && particles[bl_index].type == .Empty { - particle_set(board, bl_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif br_index > 0 && particles[br_index].type == .Empty { - particle_set(board, br_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - } else { - if br_index > 0 && particles[br_index].type == .Empty { - particle_set(board, br_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif bl_index > 0 && particles[bl_index].type == .Empty { - particle_set(board, bl_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - } + + if can_sink(board, b_index) { + particle_switch(board, index, b_index); } } @@ -164,49 +188,15 @@ update_water :: (use board: ^ParticleBoard, x: i32, y: i32) { l_index := get_index(board, x - 1, y); r_index := get_index(board, x + 1, y); - // NOTE: These do NOT short circuit so we are accessing memory that is not - // technically in our control on the second part of the condition!! This - // does not affect too many things as the accessing does not modify or damage - // the data. - if b_index > 0 && particles[b_index].type == .Empty { - particle_set(board, b_index, particles[index]); - particle_set(board, index, .{ .Empty }); + move_to_index := -1; + if time % 2 == 1 { + move_to_index = first_empty(board, b_index, bl_index, br_index, l_index, r_index); + } else { + move_to_index = first_empty(board, b_index, br_index, bl_index, r_index, l_index); } - else { - if time % 2 == 1 { - if bl_index > 0 && particles[bl_index].type == .Empty { - particle_set(board, bl_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif br_index > 0 && particles[br_index].type == .Empty { - particle_set(board, br_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif l_index > 0 && particles[l_index].type == .Empty { - particle_set(board, l_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif r_index > 0 && particles[r_index].type == .Empty { - particle_set(board, r_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - } else { - if br_index > 0 && particles[br_index].type == .Empty { - particle_set(board, br_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif bl_index > 0 && particles[bl_index].type == .Empty { - particle_set(board, bl_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif r_index > 0 && particles[r_index].type == .Empty { - particle_set(board, r_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - elseif l_index > 0 && particles[l_index].type == .Empty { - particle_set(board, l_index, particles[index]); - particle_set(board, index, .{ .Empty }); - } - } + + if move_to_index != -1 { + particle_set(board, move_to_index, particles[index]); + particle_set(board, index, .{ .Empty }); } } -- 2.25.1