proper xform tree iteration

This commit is contained in:
jacob 2024-03-11 19:39:26 -05:00
parent ff3fbecc10
commit 0f67701761
7 changed files with 188 additions and 65 deletions

View File

@ -3,14 +3,15 @@
#include "memory.h"
// #define arena_clear(a) (a->pos = 0)
#define arena_push(a, type) ((type *)_arena_push_bytes((a), sizeof(type), ALIGNOF(type)))
#define arena_push_zero(a, type) ((type *)_arena_push_bytes_zero((a), sizeof(type), ALIGNOF(type)))
#define arena_push_array(a, type, n) ((type *)_arena_push_bytes((a), (sizeof(type) * (n)), ALIGNOF(type)))
#define arena_push_array_zero(a, type, n) ((type *)_arena_push_bytes_zero((a), (sizeof(type) * (n)), ALIGNOF(type)))
#define arena_pop(a, type) ((type *)_arena_pop((a), sizeof(type)))
#define arena_pop_array(a, type, n) ((type *)_arena_pop((a), sizeof(type) * (n)))
/* Returns a pointer to where the next allocation would be (at alignment of type).
* Equivalent arena_push but without actually allocating anything. */
#define arena_dry_push(a, type) (type *)(_arena_dry_push((a), ALIGNOF(type)))
@ -39,11 +40,18 @@ INLINE void *_arena_push_bytes_zero(struct arena *arena, u64 size, u64 align)
return p;
}
INLINE void arena_pop_to(struct arena *arena, u64 pos)
INLINE void *_arena_pop_to(struct arena *arena, u64 pos)
{
ASSERT(arena->pos >= pos);
ASAN_POISON(arena->base + pos, arena->pos - pos);
arena->pos = pos;
return (void *)(arena->base + arena->pos);
}
INLINE void *_arena_pop(struct arena *arena, u64 size)
{
ASSERT(arena->pos >= size);
return _arena_pop_to(arena, arena->pos - size);
}
INLINE struct temp_arena arena_temp_begin(struct arena *arena)
@ -56,12 +64,12 @@ INLINE struct temp_arena arena_temp_begin(struct arena *arena)
INLINE void arena_temp_end(struct temp_arena temp)
{
arena_pop_to(temp.arena, temp.start_pos);
_arena_pop_to(temp.arena, temp.start_pos);
}
INLINE void arena_reset(struct arena *arena)
{
arena_pop_to(arena, 0);
_arena_pop_to(arena, 0);
}
INLINE struct buffer arena_to_buffer(struct arena *arena)
@ -89,12 +97,12 @@ INLINE void *_arena_align(struct arena *arena, u64 align)
if (align_bytes > 0) {
return (void *)arena_push_array(arena, u8, align_bytes);
} else {
return (void *)arena->pos;
return (void *)(arena->base + arena->pos);
}
} else {
/* 0 alignment */
ASSERT(false);
return (void *)arena->pos;
return (void *)(arena->base + arena->pos);
}
}

View File

@ -93,14 +93,8 @@ void draw_texture_rect(struct renderer_canvas *canvas, struct draw_texture_param
* Solid fill shapes
* ========================== */
void draw_solid_poly(struct renderer_canvas *canvas, struct v2_array array, u32 color)
INTERNAL void draw_solid_poly_internal(struct renderer_canvas *canvas, struct v2_array array, u32 color)
{
if (array.count < 3) {
return;
}
renderer_canvas_ensure_texture_cmd(canvas, (struct texture_shader_parameters) { .texture = L.solid_white });
u32 num_tris = array.count - 2;
u32 num_indices = num_tris * 3;
@ -125,6 +119,16 @@ void draw_solid_poly(struct renderer_canvas *canvas, struct v2_array array, u32
}
}
void draw_solid_poly(struct renderer_canvas *canvas, struct v2_array array, u32 color)
{
if (array.count < 3) {
return;
}
renderer_canvas_ensure_texture_cmd(canvas, (struct texture_shader_parameters) { .texture = L.solid_white });
draw_solid_poly_internal(canvas, array, color);
}
void draw_solid_circle(struct renderer_canvas *canvas, struct v2 pos, f32 radius, u32 color, u32 detail)
{
struct temp_arena scratch = scratch_begin_no_conflict();
@ -164,13 +168,6 @@ void draw_solid_rect(struct renderer_canvas *canvas, struct rect rect, u32 color
* Solid line shapes
* ========================== */
void draw_solid_ray(struct renderer_canvas *canvas, struct v2 pos, struct v2 rel, f32 thickness, u32 color)
{
renderer_canvas_ensure_texture_cmd(canvas, (struct texture_shader_parameters) { .texture = L.solid_white });
struct quad quad = quad_from_ray(pos, rel, thickness);
draw_texture_quad_internal(canvas, CLIP_ALL, color, quad);
}
void draw_solid_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, u32 color)
{
renderer_canvas_ensure_texture_cmd(canvas, (struct texture_shader_parameters) { .texture = L.solid_white });
@ -178,6 +175,13 @@ void draw_solid_line(struct renderer_canvas *canvas, struct v2 start, struct v2
draw_texture_quad_internal(canvas, CLIP_ALL, color, quad);
}
void draw_solid_ray(struct renderer_canvas *canvas, struct v2 pos, struct v2 rel, f32 thickness, u32 color)
{
renderer_canvas_ensure_texture_cmd(canvas, (struct texture_shader_parameters) { .texture = L.solid_white });
struct quad quad = quad_from_ray(pos, rel, thickness);
draw_texture_quad_internal(canvas, CLIP_ALL, color, quad);
}
void draw_solid_poly_line(struct renderer_canvas *canvas, struct v2_array array, b32 loop, f32 thickness, u32 color)
{
if (array.count < 2) {
@ -212,6 +216,44 @@ void draw_solid_rect_line(struct renderer_canvas *canvas, struct rect rect, f32
draw_solid_quad_line(canvas, q, thickness, color);
}
void draw_solid_arrow_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color)
{
renderer_canvas_ensure_texture_cmd(canvas, (struct texture_shader_parameters) { .texture = L.solid_white });
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
const f32 max_height_to_line_ratio = 0.9f; /* Maximum length of arrowhead relative to total line length */
arrowhead_height = min_f32(arrowhead_height, v2_len(v2_sub(end, start)) * max_height_to_line_ratio);
struct v2 head_start_dir = v2_sub(start, end);
head_start_dir = v2_norm(head_start_dir);
head_start_dir = v2_mul(head_start_dir, arrowhead_height);
struct v2 head_start = v2_add(end, head_start_dir);
struct v2 head_p1_dir = v2_mul(v2_perp(head_start_dir), head_width_ratio);
struct v2 head_p2_dir = v2_neg(head_p1_dir);
struct v2 head_p1 = v2_add(head_start, head_p1_dir);
struct v2 head_p2 = v2_add(head_start, head_p2_dir);
struct v2 head_points[] = { end, head_p1, head_p2 };
struct v2_array head_points_v2_array = {
.points = head_points,
.count = ARRAY_COUNT(head_points)
};
draw_solid_poly_internal(canvas, head_points_v2_array, color);
struct quad line_quad = quad_from_line(start, head_start, thickness);
draw_texture_quad_internal(canvas, CLIP_ALL, color, line_quad);
}
void draw_solid_arrow_ray(struct renderer_canvas *canvas, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color)
{
struct v2 end = v2_add(pos, rel);
draw_solid_arrow_line(canvas, pos, end, thickness, arrowhead_height, color);
}
/* ========================== *
* Text
* ========================== */

View File

@ -25,11 +25,13 @@ void draw_solid_circle(struct renderer_canvas *canvas, struct v2 pos, f32 radius
void draw_solid_quad(struct renderer_canvas *canvas, struct quad quad, u32 color);
void draw_solid_rect(struct renderer_canvas *canvas, struct rect rect, u32 color);
void draw_solid_ray(struct renderer_canvas *canvas, struct v2 start, struct v2 ray, f32 thickness, u32 color);
void draw_solid_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, u32 color);
void draw_solid_ray(struct renderer_canvas *canvas, struct v2 start, struct v2 ray, f32 thickness, u32 color);
void draw_solid_poly_line(struct renderer_canvas *canvas, struct v2_array array, b32 loop, f32 thickness, u32 color);
void draw_solid_quad_line(struct renderer_canvas *canvas, struct quad quad, f32 thickness, u32 color);
void draw_solid_rect_line(struct renderer_canvas *canvas, struct rect rect, f32 thickness, u32 color);
void draw_solid_arrow_line(struct renderer_canvas *canvas, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color);
void draw_solid_arrow_ray(struct renderer_canvas *canvas, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color);
void draw_text(struct renderer_canvas *canvas, struct font *font, struct v2 pos, struct string str);
void draw_text_ex(struct renderer_canvas *canvas, struct font *font, struct v2 pos, f32 scale, struct string str);

View File

@ -1,3 +1,9 @@
#include "entity.h"
#include "math.h"
READONLY struct entity _g_entity_nil = { 0 };
READONLY struct entity _g_entity_nil = {
.rel_xform = XFORM_IDENT,
.world_xform = XFORM_IDENT,
.sprite_xform = XFORM_IDENT,
.sprite_tint = COLOR_WHITE
};

View File

@ -95,7 +95,7 @@ INTERNAL void game_update(void)
/* Player ent */
struct entity *player_ent;
{
struct v2 pos = V2(0, 0);
struct v2 pos = V2(1, 1);
struct v2 size = V2(1, 1);
f32 r = 0;
@ -143,9 +143,36 @@ INTERNAL void game_update(void)
}
/* Child ent */
for (u64 i = 0; i < 100; ++i) {
//struct v2 pos = V2(0, 0.001);
struct v2 pos = V2(0, 0.25 * (i + 1));
struct entity *parent = player_ent;
{
#if 0
f32 x_pos = 0;
f32 y_pos = 0;
if (parent == player_ent) {
x_pos = (((f32)sys_rand_u32() - (U32_MAX / 2)) / U32_MAX) * 10;
y_pos = (((f32)sys_rand_u32() - (U32_MAX / 2)) / U32_MAX) * 10;
} else {
u64 child_count = 0;
struct entity *sibling = world_entity_from_handle(&L.world, parent->first);
while (sibling->valid) {
++child_count;
sibling = world_entity_from_handle(&L.world, sibling->next);
}
x_pos = 0.5f * child_count;
//if (child_count % 2 != 0) {
//x_pos = -x_pos;
//}
y_pos = 1.0;
}
struct v2 pos = V2(x_pos, y_pos);
#else
struct v2 pos = V2(0, 0.25);
#endif
//struct v2 pos = V2(0, 0.25 * (i + 1));
struct v2 size = V2(1, 1);
f32 r = 0;
@ -178,7 +205,7 @@ INTERNAL void game_update(void)
e->sprite_name = sprite_name;
e->sprite_tag_name = sprite_tag_name;
e->sprite_tint = RGBA_F(0.3, 0.3, 0.3, 0.3);
e->sprite_tint = RGBA_F(0.5, 0.5, 0, 1);
//entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
//e->player_max_speed = 5.f;
@ -189,7 +216,17 @@ INTERNAL void game_update(void)
//entity_enable_prop(e, ENTITY_PROP_TEST);
//entity_enable_prop(e, ENTITY_PROP_TEST_FOLLOW_MOUSE);
world_link_entities(&L.world, player_ent, e);
world_link_entities(&L.world, parent, e);
if (sys_rand_u32() % 2 == 0) {
u64 parent_idx = sys_rand_u32() % L.world.entities_count;
struct entity *rand_ent = world_entity_from_handle(&L.world, (struct entity_handle) { .idx = parent_idx, .gen = 1 });
if (rand_ent->valid) {
parent = rand_ent;
} else {
parent = e;
}
}
}
/* Camera ent */
@ -380,33 +417,41 @@ INTERNAL void game_update(void)
* Calculate xforms
* ========================== */
ent->world_xform = ent->rel_xform;
{
struct temp_arena stack = arena_temp_begin(scratch.arena);
struct entity *child = world_entity_from_handle(&L.world, ent->first);
struct xform parent_xform = ent->world_xform;
while (child->valid) {
/* Calculate child world xform */
child->world_xform = xform_mul(parent_xform, child->rel_xform);
struct xform_stack_node {
struct entity *entity;
struct xform parent_xform;
};
/* Depth first iteration */
if (child->first.gen) {
/* Next child */
parent_xform = child->world_xform;
child = world_entity_from_handle(&L.world, child->first);
} else if (child->next.gen) {
/* Next sibling */
child = world_entity_from_handle(&L.world, child->next);
} else if (child->parent.gen && world_entity_from_handle(&L.world, child->parent)->next.gen) {
/* Next parent sibling */
struct entity *parent = world_entity_from_handle(&L.world, child->parent);
struct entity *grandparent = world_entity_from_handle(&L.world, parent->parent);
parent_xform = grandparent->world_xform;
child = world_entity_from_handle(&L.world, parent->next);
} else {
child = entity_nil();
*arena_push(stack.arena, struct xform_stack_node) = (struct xform_stack_node) { .entity = ent, .parent_xform = XFORM_IDENT };
u64 stack_count = 1;
while (stack_count > 0) {
/* Pull from top of stack */
struct xform_stack_node node = *arena_pop(stack.arena, struct xform_stack_node);
--stack_count;
/* Calculate child world xform */
struct entity *child = node.entity;
struct xform world_xform = xform_mul(node.parent_xform, child->rel_xform);
child->world_xform = world_xform;
/* Append sub-children to stack */
struct entity *subchild = world_entity_from_handle(&L.world, child->last);
while (subchild->valid) {
*arena_push(stack.arena, struct xform_stack_node) = (struct xform_stack_node) {
.entity = subchild,
.parent_xform = world_xform
};
++stack_count;
subchild = world_entity_from_handle(&L.world, subchild->prev);
}
}
arena_temp_end(stack);
}
}
/* ========================== *

View File

@ -255,6 +255,7 @@ INTERNAL struct v2 view_mouse_pos(struct view view)
INTERNAL void debug_draw_xform(struct xform xf)
{
f32 thickness = 2.f / PIXELS_PER_UNIT / L.world_view.zoom;
f32 arrowhead_len = 15.f / PIXELS_PER_UNIT / L.world_view.zoom;
u32 color = RGBA_F(0, 1, 1, 0.3);
u32 color_x = RGBA_F(1, 0, 0, 0.3);
u32 color_y = RGBA_F(0, 1, 0, 0.3);
@ -266,8 +267,8 @@ INTERNAL void debug_draw_xform(struct xform xf)
struct quad quad = quad_from_rect(RECT(0, 0, 1, -1));
quad = quad_mul_xform(quad_scale(quad, 0.075), xf);
draw_solid_ray(L.world_canvas, pos, x_ray, thickness, color_x);
draw_solid_ray(L.world_canvas, pos, y_ray, thickness, color_y);
draw_solid_arrow_ray(L.world_canvas, pos, x_ray, thickness, arrowhead_len, color_x);
draw_solid_arrow_ray(L.world_canvas, pos, y_ray, thickness, arrowhead_len, color_y);
draw_solid_quad(L.world_canvas, quad, color);
}
@ -650,8 +651,8 @@ INTERNAL void user_update(void)
draw_texture_quad(L.world_canvas, params, quad);
if (L.debug_draw && !is_camera) {
#if 0
if (L.debug_draw && !is_camera) {
/* Debug draw sprite quad */
{
f32 thickness = 2.f;
@ -669,8 +670,8 @@ INTERNAL void user_update(void)
u32 color = RGBA_F(1, 0, 0, 1);
draw_solid_circle(L.world_canvas, ent->world_xform.og, 0.02, color, 20);
}
#endif
}
#endif
}
}
@ -678,6 +679,7 @@ INTERNAL void user_update(void)
if (L.debug_draw && !is_camera) {
struct temp_arena temp = arena_temp_begin(scratch.arena);
#if 0
struct font *disp_font = font_load_async(STR("res/fonts/fixedsys.ttf"), 12.0f);
if (disp_font) {
struct xform xf = ent->world_xform;
@ -715,6 +717,23 @@ INTERNAL void user_update(void)
debug_draw_xform(ent->world_xform);
debug_draw_movement(ent);
#else
(UNUSED)view_xform_point;
(UNUSED)debug_draw_xform;
(UNUSED)debug_draw_movement;
#endif
/* Draw hierarchy */
struct entity *parent = world_entity_from_handle(&L.world, ent->parent);
if (parent->valid && !v2_eq(ent->world_xform.og, V2(0, 0))) {
u32 color = RGBA_F(1, 0.7, 0.7, 0.75);
f32 thickness = 3;
f32 arrow_height = 15;
struct v2 start = view_xform_point(L.world_view, ent->world_xform.og);
struct v2 end = view_xform_point(L.world_view, parent->world_xform.og);
draw_solid_arrow_line(L.ui_canvas, start, end, thickness, arrow_height, color);
}
arena_temp_end(temp);
}
@ -728,10 +747,12 @@ INTERNAL void user_update(void)
/* Send world mouse pos */
struct v2 world_mouse = view_mouse_pos(L.world_view);
if (!L.debug_camera) {
queue_game_cmd(&cmd_list, (struct game_cmd) {
.kind = GAME_CMD_KIND_PLAYER_FOCUS,
.pos = world_mouse
});
}
/* Debug draw info */
if (L.debug_draw) {

View File

@ -30,21 +30,20 @@ void world_copy_replace(struct world *dest, struct world *src)
struct entity *world_alloc_entity(struct world *world)
{
struct entity *entity = NULL;
struct entity_handle handle;
if (world->first_free_entity.gen) {
/* Reuse from free list */
entity = world_entity_from_handle(world, world->first_free_entity);
world->first_free_entity = entity->next_free;
*entity = (struct entity) {
.handle = entity->handle
};
handle = entity->handle;
} else {
/* Make new */
u64 idx = world->entities_count++;
entity = arena_push(&world->entities_arena, struct entity);
*entity = (struct entity) {
.handle = { .gen = 1, .idx = idx }
};
handle = (struct entity_handle) { .gen = 1, .idx = idx };
}
*entity = *entity_nil();
entity->handle = handle;
return entity;
}