fix sprite slice size off-by-one. dont calculate entity animation in user thread. debug draw slices

This commit is contained in:
jacob 2024-07-31 20:01:43 -05:00
parent fd3ab6146b
commit 5c51b555b2
4 changed files with 36 additions and 51 deletions

View File

@ -954,8 +954,8 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct buff
slice->start = start; slice->start = start;
slice->x1 = x; slice->x1 = x;
slice->y1 = y; slice->y1 = y;
slice->x2 = max_u32((x + width) - 1, 0); slice->x2 = x + width;
slice->y2 = max_u32((y + height) - 1, 0); slice->y2 = y + height;
} }
++num_slice_keys; ++num_slice_keys;

View File

@ -175,7 +175,6 @@ INTERNAL void game_update(void)
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
e->sprite_span_name = STR("idle.unarmed"); e->sprite_span_name = STR("idle.unarmed");
//e->sprite_span_name = STR("idle.two_handed"); //e->sprite_span_name = STR("idle.two_handed");
e->sprite_quad_xform = XFORM_TRS(.s = size);
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED); entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
e->player_max_speed = 4.f; e->player_max_speed = 4.f;
@ -187,7 +186,6 @@ INTERNAL void game_update(void)
player_ent = e; player_ent = e;
//entity_enable_prop(e, ENTITY_PROP_TEST); //entity_enable_prop(e, ENTITY_PROP_TEST);
//entity_enable_prop(e, ENTITY_PROP_TEST_FOLLOW_MOUSE);
} }
/* Camera ent */ /* Camera ent */
@ -300,6 +298,18 @@ INTERNAL void game_update(void)
ent->animation_frame = span_frame_offset; ent->animation_frame = span_frame_offset;
} }
/* ========================== *
* Calculate sprite xform
* ========================== */
if (!sprite_tag_is_nil(ent->sprite)) {
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
struct v2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT);
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("pivot"), ent->animation_frame);
struct v2 pivot_pos = v2_mul_v2(slice.center_norm, sprite_size);
ent->sprite_quad_xform = xform_with_scale(XFORM_POS(v2_neg(pivot_pos)), sprite_size);
}
/* ========================== * /* ========================== *
* Test * Test
* ========================== */ * ========================== */
@ -324,29 +334,12 @@ INTERNAL void game_update(void)
ent->rel_xform = xform_with_scale(ent->rel_xform, s); ent->rel_xform = xform_with_scale(ent->rel_xform, s);
} }
/* ========================== *
* Calculate sprite xform
* ========================== */
if (ent->sprite.hash != 0) {
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
struct v2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT);
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("pivot"), ent->animation_frame);
struct v2 pivot_pos = v2_mul_v2(slice.center_norm, sprite_size);
/* Apply Pivot */
struct xform sprite_xf = XFORM_POS(v2_neg(pivot_pos));
sprite_xf = xform_scale(sprite_xf, sprite_size);
ent->sprite_quad_xform = sprite_xf;
}
/* ========================== * /* ========================== *
* Calculate player aim angle * Calculate player aim angle
* ========================== */ * ========================== */
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
#if 1
/* Update focus */ /* Update focus */
ent->focus = G.world.player_aim; ent->focus = G.world.player_aim;
@ -355,6 +348,16 @@ INTERNAL void game_update(void)
struct v2 look_pos = v2_add(ent_pos, ent->focus); struct v2 look_pos = v2_add(ent_pos, ent->focus);
f32 r = v2_angle_to_point(ent_pos, look_pos) + PI / 2; f32 r = v2_angle_to_point(ent_pos, look_pos) + PI / 2;
ent->rel_xform = xform_with_rotation(ent->rel_xform, r); ent->rel_xform = xform_with_rotation(ent->rel_xform, r);
#else
/* Update focus */
ent->focus = G.world.player_aim;
/* Update view angle */
struct v2 ent_pos = ent->rel_xform.og;
struct v2 look_pos = v2_add(ent_pos, ent->focus);
f32 r = v2_angle_to_point(ent_pos, look_pos) + PI / 2;
ent->rel_xform = xform_with_rotation(ent->rel_xform, r);
#endif
} }
} }

View File

@ -650,7 +650,7 @@ INTERNAL void cache_node_load_sheet(struct cache_node *n, struct sprite_tag tag)
logf_info("Loading sprite sheet \"%F\"", FMT_STR(path)); logf_info("Loading sprite sheet \"%F\"", FMT_STR(path));
sys_timestamp_t start_ts = sys_timestamp(); sys_timestamp_t start_ts = sys_timestamp();
ASSERT(string_ends_with(path, STR(".ase"))); //ASSERT(string_ends_with(path, STR(".ase")));
ASSERT(n->kind == CACHE_NODE_KIND_SHEET); ASSERT(n->kind == CACHE_NODE_KIND_SHEET);
n->arena = arena_alloc(SHEET_ARENA_RESERVE); n->arena = arena_alloc(SHEET_ARENA_RESERVE);
@ -671,7 +671,7 @@ INTERNAL void cache_node_load_sheet(struct cache_node *n, struct sprite_tag tag)
n->sheet->loaded = true; n->sheet->loaded = true;
n->sheet->valid = true; n->sheet->valid = true;
} else { } else {
logf_error("Sprite \"%F\" not found", path); logf_error("Sprite \"%F\" not found", FMT_STR(path));
} }
} }
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
@ -899,7 +899,6 @@ INTERNAL void *data_from_tag_internal(struct sprite_scope *scope, struct sprite_
sys_mutex_unlock(&lock); sys_mutex_unlock(&lock);
} }
} }
} }

View File

@ -457,6 +457,7 @@ INTERNAL void user_update(void)
e->sprite_quad_xform = xform_lerp(e0->sprite_quad_xform, e1->sprite_quad_xform, tick_blend); e->sprite_quad_xform = xform_lerp(e0->sprite_quad_xform, e1->sprite_quad_xform, tick_blend);
e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend); e->animation_time_in_frame = math_lerp64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
e->animation_frame = (u32)math_round_to_int(math_lerp(e0->animation_frame, e1->animation_frame, tick_blend));
e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend); e->camera_quad_xform = xform_lerp(e0->camera_quad_xform, e1->camera_quad_xform, tick_blend);
e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend); e->camera_rel_xform_target = xform_lerp(e0->camera_rel_xform_target, e1->camera_rel_xform_target, tick_blend);
@ -765,29 +766,10 @@ INTERNAL void user_update(void)
struct sprite_texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite); struct sprite_texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite);
(UNUSED)texture; (UNUSED)texture;
if (sheet->loaded) {
struct sprite_sheet_frame frame;
{
struct sprite_sheet_span span = sprite_sheet_get_span(sheet, ent->sprite_span_name);
u32 frame_index = span.start + ent->animation_frame;
frame = sprite_sheet_get_frame(sheet, frame_index);
if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) {
f64 time_in_frame = ent->animation_time_in_frame;
while (time_in_frame > frame.duration) {
time_in_frame -= frame.duration;
++frame_index;
if (frame_index > span.end) {
/* Loop animation */
frame_index = span.start;
}
frame = sprite_sheet_get_frame(sheet, frame_index);
}
}
}
struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, xform_mul(ent->world_xform, ent->sprite_quad_xform));
/* TODO: Fade in placeholder if texture isn't loaded */ /* TODO: Fade in placeholder if texture isn't loaded */
if (sheet->loaded) {
struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, ent->animation_frame);
struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, xform_mul(ent->world_xform, ent->sprite_quad_xform));
struct draw_sprite_params params = DRAW_SPRITE_PARAMS(.sprite = sprite, .tint = ent->sprite_tint, .clip = frame.clip); struct draw_sprite_params params = DRAW_SPRITE_PARAMS(.sprite = sprite, .tint = ent->sprite_tint, .clip = frame.clip);
draw_sprite_quad(G.world_canvas, params, quad); draw_sprite_quad(G.world_canvas, params, quad);
} }
@ -840,9 +822,8 @@ INTERNAL void user_update(void)
debug_draw_xform(ent->world_xform); debug_draw_xform(ent->world_xform);
} }
#if 0
/* Draw slices */ /* Draw slices */
{ if (!sprite_tag_is_nil(ent->sprite)) {
struct sprite_tag sprite = ent->sprite; struct sprite_tag sprite = ent->sprite;
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite); struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
@ -850,12 +831,14 @@ INTERNAL void user_update(void)
struct sprite_sheet_slice_group *group = &sheet->slice_groups[i]; struct sprite_sheet_slice_group *group = &sheet->slice_groups[i];
for (u32 j = 0; j < group->per_frame_count; ++j) { for (u32 j = 0; j < group->per_frame_count; ++j) {
group->frame_slices[(j * group->per_frame_count) + k]; struct sprite_sheet_slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j];
struct quad quad = quad_from_rect(slice.rect_norm);
quad = quad_mul_xform(quad, xform_mul(ent->world_xform, ent->sprite_quad_xform));
draw_solid_quad_line(G.viewport_canvas, quad_mul_xform(quad, G.world_view), 3, COLOR_RED);
}
} }
} }
}
#endif
/* Draw hierarchy */ /* Draw hierarchy */
struct entity *parent = entity_from_handle(&G.world.entity_store, ent->parent); struct entity *parent = entity_from_handle(&G.world.entity_store, ent->parent);
if (parent->valid) { if (parent->valid) {