push_event_to_buffer(esp, event_size, 0x03, [ ev.clientX, ev.clientY, -1 ]);
});
+ document.addEventListener("wheel", (ev) => {
+ push_event_to_buffer(esp, event_size, 0x07, [ ev.clientX, ev.clientY, ev.deltaY >= 0 ? 0x04 : 0x03 ]);
+ });
+
window.addEventListener("resize", (ev) => {
push_event_to_buffer(esp, event_size, 0x06, [ window.innerWidth, window.innerHeight ]);
});
// NOTE: These need to match exactly what is in the corresponding javascript
DomEventKind :: enum {
- None :: 0x00;
+ None :: 0x00;
- MouseDown :: 0x01;
- MouseUp :: 0x02;
- MouseMove :: 0x03;
+ MouseDown :: 0x01;
+ MouseUp :: 0x02;
+ MouseMove :: 0x03;
+ MouseWheel :: 0x07;
- KeyDown :: 0x04;
- KeyUp :: 0x05;
+ KeyDown :: 0x04;
+ KeyUp :: 0x05;
- Resize :: 0x06;
+ Resize :: 0x06;
}
DomEvent :: struct {
}
AtlasSprite :: struct {
- x : i32 = 0;
- y : i32 = 0;
- w : i32 = 0;
- h : i32 = 0;
+ x : f32 = 0.0f;
+ y : f32 = 0.0f;
+ w : f32 = 0.0f;
+ h : f32 = 0.0f;
}
atlas_create :: proc (tex: ^Texture) -> Atlas {
i32map_put(^map, id, sprite);
}
+atlas_lookup :: proc (use atlas: ^Atlas, id: i32) -> AtlasSprite {
+ sprite := i32map_get(^map, id, AtlasSprite.{});
+ sprite.x /= ~~texture.width;
+ sprite.y /= ~~texture.width;
+ sprite.w /= ~~texture.width;
+ sprite.h /= ~~texture.width;
+ return sprite;
+}
+
atlas_apply_to_quad :: proc (use atlas: ^Atlas, id: i32, quad: ^Quad) {
sprite := i32map_get(^map, id, AtlasSprite.{});
- quad.tex_size.x = cast(f32) sprite.w / ~~texture.width;
- quad.tex_size.y = cast(f32) sprite.h / ~~texture.height;
- quad.tex_pos.x = cast(f32) sprite.x / ~~texture.width;
- quad.tex_pos.y = cast(f32) sprite.y / ~~texture.height;
+ quad.tex_size.x = sprite.w / ~~texture.width;
+ quad.tex_size.y = sprite.h / ~~texture.height;
+ quad.tex_pos.x = sprite.x / ~~texture.width;
+ quad.tex_pos.y = sprite.y / ~~texture.height;
}
use package gl as gl
use package gl_utils as gl_utils
use package vecmath
-use package main { window_width, window_height }
+use package main { half_window_width, half_window_height }
#private_file
quad_program : gl.GLProgram = -1;
indexBuffer : gl.GLBuffer;
quadBuffer : gl.GLBuffer;
- u_proj_loc : gl.GLUniformLocation;
+ u_proj_loc : gl.GLUniformLocation;
+ u_world_loc : gl.GLUniformLocation;
is_data_dirty : bool = false;
}
u_proj_loc = gl.getUniformLocation(quad_program, "u_proj");
quad_renderer_update_view(qr);
+
+ u_world_loc = gl.getUniformLocation(quad_program, "u_world");
+ quad_renderer_update_world(qr);
}
quad_renderer_draw :: proc (use qr: ^QuadRenderer, count := -1) {
// Orthographic projection matrix shamelessly stolen from:
// https://en.wikipedia.org/wiki/Orthographic_projection
- r :: cast(f32) window_width;
- l :: 0.0f;
- t :: 0.0f;
- b :: cast(f32) window_height;
+ r :: cast(f32) half_window_width;
+ l :: -cast(f32) half_window_width;
+ t :: -cast(f32) half_window_height;
+ b :: cast(f32) half_window_height;
proj_mat[0 * 4 + 0] = 2.0f / (r - l);
proj_mat[0 * 4 + 3] = -(r + l) / (r - l);
gl.uniformMatrix4(u_proj_loc, true, proj_mat);
}
+quad_renderer_update_world :: proc (use qr: ^QuadRenderer,
+ scale_x := 1.0f, scale_y := 1.0f, trans_x := 0.0f, trans_y := 0.0f) {
+ world_mat : [4 * 4] gl.GLfloat;
+ for ^it: world_mat do *it = 0.0f;
+
+ world_mat[0 * 4 + 0] = scale_x;
+ world_mat[1 * 4 + 1] = scale_y;
+ world_mat[2 * 4 + 2] = 0.0f;
+ world_mat[3 * 4 + 3] = 1.0f;
+
+ world_mat[3 * 4 + 0] = trans_x * scale_x;
+ world_mat[3 * 4 + 1] = trans_y * scale_y;
+
+ gl.uniformMatrix4(u_world_loc, false, world_mat);
+}
+
quad_update_at_index :: proc (use qr: ^QuadRenderer, idx: i32, quad: Quad) {
quad_data[idx] = quad;
is_data_dirty = true;
use package event as event
use package core { print }
+use package main { half_window_width, half_window_height }
#private_file KEY_COUNT :: 256
#private_file BUTTON_COUNT :: 3
keys_just_down : [KEY_COUNT] bool;
mouse : struct {
- x : u32;
- y : u32;
+ x : i32;
+ y : i32;
buttons_down : [BUTTON_COUNT] bool;
buttons_just_down : [BUTTON_COUNT] bool;
+
+ wheel_ups : u8;
+ wheel_downs : u8;
};
}
mouse.x = 0;
mouse.y = 0;
+
+ mouse.wheel_ups = ~~0;
+ mouse.wheel_downs = ~~0;
}
process_event :: proc (use state: ^InputState, ev: ^event.Event) {
+ use event.DomEventKind;
+
switch ev.kind {
- case event.DomEventKind.KeyDown {
+ case KeyDown {
keys_just_down[ev.keyboard.keycode] = !keys_down[ev.keyboard.keycode];
keys_down[ev.keyboard.keycode] = true;
}
- case event.DomEventKind.KeyUp {
+ case KeyUp {
keys_down[ev.keyboard.keycode] = false;
keys_just_down[ev.keyboard.keycode] = false;
}
- case event.DomEventKind.MouseDown {
- mouse.x = ev.mouse.pos_x;
- mouse.y = ev.mouse.pos_y;
+ case MouseDown {
+ mouse.x = ev.mouse.pos_x - half_window_width;
+ mouse.y = ev.mouse.pos_y - half_window_height;
mouse.buttons_just_down[cast(u32) ev.mouse.button] = !mouse.buttons_down[cast(u32) ev.mouse.button];
mouse.buttons_down[cast(u32) ev.mouse.button] = true;
}
- case event.DomEventKind.MouseUp {
- mouse.x = ev.mouse.pos_x;
- mouse.y = ev.mouse.pos_y;
+ case MouseUp {
+ mouse.x = ev.mouse.pos_x - half_window_width;
+ mouse.y = ev.mouse.pos_y - half_window_height;
mouse.buttons_down[cast(u32) ev.mouse.button] = false;
mouse.buttons_just_down[cast(u32) ev.mouse.button] = false;
}
- case event.DomEventKind.MouseMove {
- mouse.x = ev.mouse.pos_x;
- mouse.y = ev.mouse.pos_y;
+ case MouseMove {
+ mouse.x = ev.mouse.pos_x - half_window_width;
+ mouse.y = ev.mouse.pos_y - half_window_height;
+ }
+
+ case MouseWheel {
+ // @TEST: These may be backwards
+ is_up := ev.mouse.button == event.MouseButton.WheelUp;
+
+ // @FIXME: This could overflow... if there were 256+ wheel up/down events
+ // in one frame. Still something that should be considered.
+ if is_up do mouse.wheel_ups += ~~1;
+ else do mouse.wheel_downs += ~~1;
}
}
}
postupdate :: proc (use state: ^InputState) {
for ^key: keys_just_down do *key = false;
for ^button: mouse.buttons_just_down do *button = false;
+
+ if mouse.wheel_ups > ~~0 do mouse.wheel_ups -= ~~1;
+ if mouse.wheel_downs > ~~0 do mouse.wheel_downs -= ~~1;
}
curr_quad_idx: i32 = 0;
max_quad_idx: i32 = 0;
+ scale : f32 = 1.0f;
+ trans_x : f32 = 0.0f;
+ trans_y : f32 = 0.0f;
+
color: Color4f32 = Color4f32.{ 1.0f, 1.0f, 1.0f, 1.0f };
}
}
render_context_flush :: proc (use rc: ^RenderContext) {
+ quad_renderer_update_world(quad_renderer, scale, scale, trans_x, trans_y);
quad_rebuffer_data(quad_renderer);
quad_renderer_draw(quad_renderer, curr_quad_idx);
- // for i: 0 .. curr_quad_idx do quad_update_at_index(quad_renderer, i, Quad.{});
-
curr_quad_idx = 0;
}
// @Cleanup
window_width := 0
window_height := 0
+half_window_width := 0
+half_window_height := 0
renderer : RenderContext
input_state : input.InputState
ev : event.Event;
while event.poll(^ev) do switch ev.kind {
- case KeyDown, KeyUp, MouseDown, MouseUp, MouseMove do input.process_event(^input_state, ^ev);
-
case Resize {
window_width = ev.resize.width;
window_height = ev.resize.height;
+ half_window_width = window_width / 2;
+ half_window_height = window_height / 2;
+
gl.canvasSize(window_width, window_height);
gl.viewport(0, 0, window_width, window_height);
quad_renderer_update_view(renderer.quad_renderer);
}
+
+ case #default do input.process_event(^input_state, ^ev);
}
}
if input.key_just_down(^input_state, Key.Space) do simulating = !simulating;
+ if input.key_down(^input_state, Key.ArrowUp) do renderer.trans_y += 10.0f;
+ if input.key_down(^input_state, Key.ArrowDown) do renderer.trans_y -= 10.0f;
+ if input.key_down(^input_state, Key.ArrowLeft) do renderer.trans_x += 10.0f;
+ if input.key_down(^input_state, Key.ArrowRight) do renderer.trans_x -= 10.0f;
+
+ if input_state.mouse.wheel_ups > ~~0 do renderer.scale *= 1.125f;
+ if input_state.mouse.wheel_downs > ~~0 do renderer.scale /= 1.125f;
+
if simulating {
quad_scratch : ScratchState;
quad_alloc : Allocator;
scratch_state_init(^quad_scratch, ~~quad_scratch_buffer, 512 * 1024);
scratch_alloc_init(^quad_alloc, ^quad_scratch);
- quadtree_init(^dude_tree, AABB.{ 0.0f, 0.0f, ~~window_width, ~~window_height });
+ quadtree_init(^dude_tree, AABB.{ ~~-half_window_width, ~~-half_window_height, ~~window_width, ~~window_height });
for ^d: dudes do quadtree_insert(^dude_tree, d, quad_alloc);
for ^d: dudes do dude_update(d, ^dude_tree);
for ^d: dudes {
- if !d.can_move_x do d.vel.x = -d.vel.x;
- if !d.can_move_y do d.vel.y = -d.vel.y;
+ if d.can_move_x do d.pos.x += d.vel.x;
+ if d.can_move_y do d.pos.y += d.vel.y;
- d.pos.x += d.vel.x;
- d.pos.y += d.vel.y;
+ if !d.can_move_x && !d.can_move_y do d.couldnt_move_count += ~~1;
}
}
}
texture_use(^textures.tilemap);
- draw_quad_tree(^dude_tree);
-
- draw_rect(^renderer, ~~input_state.mouse.x, ~~input_state.mouse.y, 10f, 10f);
+ // draw_quad_tree(^dude_tree);
+ dude_sprite := atlas_lookup(^atlas, 0);
for ^d: dudes {
aabb := dude_get_aabb(d);
- draw_rect(^renderer, aabb.x, aabb.y, aabb.w, aabb.h);
+ renderer.color = d.color;
+ draw_textured_rect(^renderer, aabb.x, aabb.y, aabb.w, aabb.h,
+ dude_sprite.x, dude_sprite.y,
+ dude_sprite.w, dude_sprite.h);
}
+ renderer.color = Color4f32.{ 1.0f, 1.0f, 1.0f, 1.0f };
+ draw_rect(^renderer, ~~input_state.mouse.x, ~~input_state.mouse.y, 10f, 10f);
render_context_flush(^renderer);
}
-draw_quad_tree :: proc (qt: ^QuadTree($T), level := 0, corner := 0) {
+draw_quad_tree :: proc (qt: ^QuadTree($T)) {
col := cast(f32) (0.0f + ~~ qt.points_count * 0.25f);
if col > 1.0f do col = 1.0f;
- color := Color4f32.{ 0.0f, 0.0f, 0.0f, 1.0f };
-
- if corner == 1 do color.r = col;
- if corner == 2 do color.g = col;
- if corner == 3 do color.b = col;
+ color := Color4f32.{ col, col, col, 1.0f };
quad := Quad.{
pos = V2f.{ qt.region.x, qt.region.y },
draw_quad(^renderer, ^quad);
if qt.nw != null {
- draw_quad_tree(qt.nw, level + 1, 1);
- draw_quad_tree(qt.ne, level + 1, 2);
- draw_quad_tree(qt.sw, level + 1, 3);
- draw_quad_tree(qt.se, level + 1, 4);
+ draw_quad_tree(qt.nw);
+ draw_quad_tree(qt.ne);
+ draw_quad_tree(qt.sw);
+ draw_quad_tree(qt.se);
}
}
textures_init();
atlas = atlas_create(^textures.tilemap);
- atlas_map(^atlas, 0, AtlasSprite.{ x = 16, y = 0, w = 16, h = 16 });
+ atlas_map(^atlas, 0, AtlasSprite.{ x = 16.0f, y = 0.0f, w = 16.0f, h = 16.0f });
event.init();
input.init(^input_state);
+ Dude_Color_Table[0] = Color4f32.{ 1.0f, 0.0f, 0.0f, 1.0f };
+ Dude_Color_Table[1] = Color4f32.{ 0.0f, 1.0f, 0.0f, 1.0f };
+ Dude_Color_Table[2] = Color4f32.{ 0.0f, 0.0f, 1.0f, 1.0f };
+
array_init(^dudes);
- for i: 0 .. 2500 {
+ for i: 0 .. 4000 {
array_push(^dudes, dude_create_random());
}
}
-Dude_Color_Table : [4] Color4f32;
+Dude_Color_Table : [3] Color4f32;
Dude :: struct {
pos : V2f;
can_move_x : bool = true;
can_move_y : bool = true;
+ couldnt_move_count : u16 = ~~0;
}
dude_create_random :: proc () -> Dude {
return Dude.{
- pos = V2f.{ random_float(0.0f, 1000.0f), random_float(0.0f, 1000.0f) },
+ pos = V2f.{ random_float(-600.0f, 600.0f), random_float(-600.0f, 600.0f) },
vel = V2f.{ random_float(-3.0f, 3.0f), random_float(-3.0f, 3.0f) },
size = random_float(2.0f, 3.0f),
- color = Dude_Color_Table[random_between(0, 3)],
+ color = Dude_Color_Table[random() % 3],
};
}
dude_update :: proc (use dude: ^Dude, other_dudes: ^QuadTree(Dude)) {
- // if random_between(0, 100) < 1 {
- // vel.x = random_float(-2.0f, 2.0f);
- // vel.y = random_float(-2.0f, 2.0f);
- // }
+ if random_between(0, 100) < 1 || couldnt_move_count >= ~~2 {
+ vel.x = random_float(-3.0f, 3.0f);
+ vel.y = random_float(-3.0f, 3.0f);
+ couldnt_move_count = ~~0;
+ }
dude_try_move(dude, other_dudes);
}
collided := false;
pos.x += vel.x;
- if pos.x - size < 0.0f || pos.x + size >= ~~window_width do collided = true;
+ if pos.x - size < ~~-half_window_width || pos.x + size >= ~~half_window_width do collided = true;
dude_aabb := dude_get_aabb(dude);
for other: potential_dudes {
collided = false;
pos.y += vel.y;
- if pos.y - size < 0.0f || pos.y + size >= ~~window_height do collided = true;
+ if pos.y - size < ~~-half_window_height || pos.y + size >= ~~half_window_height do collided = true;
dude_aabb = dude_get_aabb(dude);
for other: potential_dudes {
qt.se = alloc(a, sizeof QuadTree(T));
quadtree_init(qt.nw, AABB.{ region.x, region.y, hw, hh });
- quadtree_init(qt.ne, AABB.{ region.x + hw, region.y, hw, hh });
+ quadtree_init(qt.ne, AABB.{ region.x + hw, region.y, hw, hh });
quadtree_init(qt.sw, AABB.{ region.x, region.y + hh, hw, hh });
quadtree_init(qt.se, AABB.{ region.x + hw, region.y + hh, hw, hh });
}
layout(location = 5) in vec4 a_col;
uniform mat4 u_proj;
-// uniform mat4 u_world;
+uniform mat4 u_world;
out vec2 v_tex_pos;
out vec4 v_col;
void main() {
- gl_Position = u_proj * vec4(a_vert_pos * a_size + a_pos, 0, 1);
+ gl_Position = u_proj * u_world * vec4(a_vert_pos * a_size + a_pos, 0, 1);
v_col = a_col;
if (a_tex_pos.x < 0.0) {
DomEvent src/events.onyx /^DomEvent :: struct {$/
DomEventKind src/events.onyx /^DomEventKind :: enum {$/
Dude src/main.onyx /^Dude :: struct {$/
-Dude_Color_Table src/main.onyx /^Dude_Color_Table : [4] Color4f32;$/
+Dude_Color_Table src/main.onyx /^Dude_Color_Table : [3] Color4f32;$/
ELEMENT_ARRAY_BUFFER /usr/share/onyx/core/js/webgl.onyx /^ELEMENT_ARRAY_BUFFER :: 0x8893$/
ELEMENT_ARRAY_BUFFER_BINDING /usr/share/onyx/core/js/webgl.onyx /^ELEMENT_ARRAY_BUFFER_BINDING :: 0x8895$/
EQUAL /usr/share/onyx/core/js/webgl.onyx /^EQUAL :: 0x0202$/
atlas src/main.onyx /^atlas : Atlas$/
atlas_apply_to_quad src/gfx/atlas.onyx /^atlas_apply_to_quad :: proc (use atlas: ^Atlas, id: i32, quad: ^Quad) {$/
atlas_create src/gfx/atlas.onyx /^atlas_create :: proc (tex: ^Texture) -> Atlas {$/
+atlas_lookup src/gfx/atlas.onyx /^atlas_lookup :: proc (use atlas: ^Atlas, id: i32) -> AtlasSprite {$/
atlas_map src/gfx/atlas.onyx /^atlas_map :: proc (use atlas: ^Atlas, id: i32, sprite: AtlasSprite) {$/
attachShader /usr/share/onyx/core/js/webgl.onyx /^attachShader :: proc (program: GLProgram, shader: GLShader) -> GLProgram #foreign "gl" "attachShader" ---$/
bezier_curve src/font.onyx /^bezier_curve :: proc (t: f32, ps: [] V2f) -> V2f {$/
drawElements /usr/share/onyx/core/js/webgl.onyx /^drawElements :: proc (mode: GLenum, count: GLsizei, type: GLenum, offset: GLint) #foreign "gl" "drawElements" ---$/
drawElementsInstanced /usr/share/onyx/core/js/webgl.onyx /^drawElementsInstanced :: proc (mode: GLenum, count: GLsizei, type: GLenum, offset: GLint, instanceCount: GLsizei) #foreign "gl" "drawElementsInstanced" ---$/
draw_quad src/main.onyx /^draw_quad :: proc (use rc: ^RenderContext, quad: ^Quad) {$/
-draw_quad_tree src/main.onyx /^draw_quad_tree :: proc (qt: ^QuadTree($T), level := 0, corner := 0) {$/
+draw_quad_tree src/main.onyx /^draw_quad_tree :: proc (qt: ^QuadTree($T)) {$/
draw_rect src/main.onyx /^draw_rect :: proc (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32) {$/
draw_textured_rect src/main.onyx /^draw_textured_rect :: proc (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32, tx: f32, ty: f32, tw: f32, th: f32) {$/
dude_create_random src/main.onyx /^dude_create_random :: proc () -> Dude {$/
getShaderParameter /usr/share/onyx/core/js/webgl.onyx /^getShaderParameter :: proc (shader: GLShader, pname: GLenum) -> GLenum #foreign "gl" "getShaderParameter" ---$/
getUniformLocation /usr/share/onyx/core/js/webgl.onyx /^getUniformLocation :: proc (program: GLProgram, name: string) -> GLUniformLocation #foreign "gl" "getUniformLocation" ---$/
getVertexAttribOffset /usr/share/onyx/core/js/webgl.onyx /^getVertexAttribOffset :: proc (index: GLuint, pname: GLenum) #foreign "gl" "getVertexAttribOffset" ---$/
+half_window_height src/main.onyx /^half_window_height := 0$/
+half_window_width src/main.onyx /^half_window_width := 0$/
heap_alloc /usr/share/onyx/core/alloc.onyx /^heap_alloc :: proc (size_: u32, align: u32) -> rawptr {$/
heap_alloc_proc /usr/share/onyx/core/alloc.onyx /^heap_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {$/
heap_allocator /usr/share/onyx/core/alloc.onyx /^heap_allocator : Allocator;$/
quad_renderer_draw src/gfx/quad_renderer.onyx /^quad_renderer_draw :: proc (use qr: ^QuadRenderer, count := -1) {$/
quad_renderer_init src/gfx/quad_renderer.onyx /^quad_renderer_init :: proc (use qr: ^QuadRenderer, initial_quads := 10) {$/
quad_renderer_update_view src/gfx/quad_renderer.onyx /^quad_renderer_update_view :: proc (use qr: ^QuadRenderer) {$/
+quad_renderer_update_world src/gfx/quad_renderer.onyx /^quad_renderer_update_world :: proc (use qr: ^QuadRenderer,$/
quad_scratch_buffer src/main.onyx /^quad_scratch_buffer : [512 * 1024] u8;$/
quad_update_at_index src/gfx/quad_renderer.onyx /^quad_update_at_index :: proc (use qr: ^QuadRenderer, idx: i32, quad: Quad) {$/
quadtree_free src/quad_tree.onyx /^quadtree_free :: proc (qt: ^QuadTree($T), initial := true) {$/