only re-calculate all xforms before publishing game tick
This commit is contained in:
parent
a7d8e19784
commit
dbeb0f0f72
BIN
res/graphics/gun.ase
(Stored with Git LFS)
Normal file
BIN
res/graphics/gun.ase
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
res/graphics/tim.ase
(Stored with Git LFS)
BIN
res/graphics/tim.ase
(Stored with Git LFS)
Binary file not shown.
@ -81,8 +81,7 @@ struct entity {
|
||||
struct string sprite_span_name;
|
||||
u32 sprite_tint;
|
||||
|
||||
struct xform sprite_local_xform; /* Sprite transform in relation to xform_world */
|
||||
struct xform sprite_global_xform;
|
||||
struct xform sprite_local_xform; /* Sprite transform in relation to entity */
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Animation */
|
||||
|
||||
145
src/game.c
145
src/game.c
@ -197,74 +197,6 @@ INTERNAL void publish_game_tick(void)
|
||||
sys_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: Remove this(?) */
|
||||
#if 0
|
||||
INTERNAL void recalculate_world_xforms_recurse(struct entity *parent)
|
||||
{
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
|
||||
struct stack_node {
|
||||
struct entity *entity;
|
||||
struct xform parent_xform_world;
|
||||
};
|
||||
|
||||
/* Depth first iteration */
|
||||
*arena_push(scratch.arena, struct stack_node) = (struct stack_node) { .entity = parent, .parent_xform_world = XFORM_IDENT };
|
||||
u64 stack_count = 1;
|
||||
while (stack_count > 0) {
|
||||
/* Pull from top of stack */
|
||||
struct stack_node node;
|
||||
arena_pop(scratch.arena, struct stack_node, &node);
|
||||
--stack_count;
|
||||
|
||||
struct entity *child = node.entity;
|
||||
|
||||
/* Calculate world xform */
|
||||
struct xform xform_world = xform_mul(node.parent_xform_world, child->_xform);
|
||||
child->_xform_world = xform_world;
|
||||
|
||||
/* Calculate sprite world xform */
|
||||
struct xform sprite_xform_world = xform_mul(xform_world, child->sprite_xform);
|
||||
child->sprite_xform_world = sprite_xform_world;
|
||||
|
||||
/* Append sub-children to stack */
|
||||
struct entity *subchild = entity_from_handle(G.world.entity_store, child->last);
|
||||
while (subchild->valid) {
|
||||
*arena_push(scratch.arena, struct stack_node) = (struct stack_node) { .entity = subchild, .parent_xform_world = xform_world };
|
||||
++stack_count;
|
||||
subchild = entity_from_handle(G.world.entity_store, subchild->prev);
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
#else
|
||||
INTERNAL void recalculate_world_xforms_recurse(struct entity *ent)
|
||||
{
|
||||
struct xform xform_global = entity_get_xform(ent);
|
||||
//struct xform xform_local = entity_get_local_xform(ent);
|
||||
(UNUSED)xform_global;
|
||||
//(UNUSED)xform_local;
|
||||
|
||||
struct entity_store *store = G.world.entity_store;
|
||||
struct xform sprite_global_xform = xform_mul(xform_global, ent->sprite_local_xform);
|
||||
ent->sprite_global_xform = sprite_global_xform;
|
||||
for (struct entity *child = entity_from_handle(store, ent->first); child->valid; child = entity_from_handle(store, child->next)) {
|
||||
recalculate_world_xforms_recurse(child);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
INTERNAL void game_update(void)
|
||||
{
|
||||
__prof;
|
||||
@ -339,20 +271,13 @@ INTERNAL void game_update(void)
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct entity *root = entity_from_handle(store, store->root);
|
||||
struct entity_array entities_array = entity_store_as_array(store);
|
||||
|
||||
/* ========================== *
|
||||
* Update sprite
|
||||
* ========================== */
|
||||
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && ent->is_top) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (!ent->valid) continue;
|
||||
@ -410,14 +335,6 @@ INTERNAL void game_update(void)
|
||||
* Update entities pre-physics
|
||||
* ========================== */
|
||||
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && ent->is_top) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find active camera */
|
||||
struct entity *active_camera;
|
||||
{
|
||||
@ -540,14 +457,6 @@ INTERNAL void game_update(void)
|
||||
* Update entity physics
|
||||
* ========================== */
|
||||
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && ent->is_top) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (!ent->valid) continue;
|
||||
@ -587,14 +496,6 @@ INTERNAL void game_update(void)
|
||||
* Update entities post-physics
|
||||
* ========================== */
|
||||
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && ent->is_top) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
}
|
||||
}
|
||||
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (!ent->valid) continue;
|
||||
@ -666,12 +567,46 @@ INTERNAL void game_update(void)
|
||||
* Publish tick
|
||||
* ========================== */
|
||||
|
||||
/* Recalculate world xforms */
|
||||
for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) {
|
||||
struct entity *ent = &entities_array.entities[entity_index];
|
||||
if (ent->valid && ent->is_top) {
|
||||
recalculate_world_xforms_recurse(ent);
|
||||
/* Update cached global xforms to ensure they're accurate in published tick */
|
||||
{
|
||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||
|
||||
struct stack_node {
|
||||
struct entity *entity;
|
||||
struct xform parent_global_xform;
|
||||
};
|
||||
|
||||
/* Depth first iteration */
|
||||
*arena_push(temp.arena, struct stack_node) = (struct stack_node) { .entity = root, .parent_global_xform = XFORM_IDENT };
|
||||
u64 stack_count = 1;
|
||||
while (stack_count > 0) {
|
||||
/* Pull from top of stack */
|
||||
struct stack_node node;
|
||||
arena_pop(temp.arena, struct stack_node, &node);
|
||||
--stack_count;
|
||||
|
||||
struct entity *child = node.entity;
|
||||
|
||||
/* Calculate world xform */
|
||||
struct xform xf;
|
||||
if (child->cached_global_xform_dirty) {
|
||||
xf = xform_mul(node.parent_global_xform, child->local_xform);
|
||||
child->cached_global_xform = xf;
|
||||
child->cached_global_xform_dirty = false;
|
||||
} else {
|
||||
xf = child->cached_global_xform;
|
||||
}
|
||||
|
||||
/* Append sub-children to stack */
|
||||
struct entity *subchild = entity_from_handle(store, child->last);
|
||||
while (subchild->valid) {
|
||||
*arena_push(temp.arena, struct stack_node) = (struct stack_node) { .entity = subchild, .parent_global_xform = xf };
|
||||
++stack_count;
|
||||
subchild = entity_from_handle(store, subchild->prev);
|
||||
}
|
||||
}
|
||||
|
||||
arena_temp_end(temp);
|
||||
}
|
||||
|
||||
/* Publish tick */
|
||||
|
||||
23
src/user.c
23
src/user.c
@ -359,6 +359,10 @@ INTERNAL void debug_draw_xform(struct xform xf)
|
||||
struct v2 x_ray = xform_basis_mul_v2(G.world_view, xform_get_right(xf));
|
||||
struct v2 y_ray = xform_basis_mul_v2(G.world_view, xform_get_up(xf));
|
||||
|
||||
f32 ray_scale = 1;
|
||||
x_ray = v2_mul(x_ray, ray_scale);
|
||||
y_ray = v2_mul(y_ray, ray_scale);
|
||||
|
||||
struct quad quad = quad_from_rect(RECT(0, 0, 1, -1));
|
||||
quad = quad_mul_xform(quad_scale(quad, 0.075f), xf);
|
||||
|
||||
@ -454,6 +458,7 @@ INTERNAL void user_update(void)
|
||||
struct entity *e0 = &t0_entities.entities[i];
|
||||
struct entity *e1 = &t1_entities.entities[i];
|
||||
struct entity *e = &world_entities.entities[i];
|
||||
ASSERT(e->cached_global_xform_dirty == false); /* Game thread should have cached all global xforms before publishing */
|
||||
if (e0->handle.gen == e1->handle.gen && e0->continuity_gen == e1->continuity_gen) {
|
||||
e->local_xform = xform_lerp(e0->local_xform, e1->local_xform, tick_blend);
|
||||
e->cached_global_xform = xform_lerp(e0->cached_global_xform, e1->cached_global_xform, tick_blend);
|
||||
@ -464,7 +469,6 @@ INTERNAL void user_update(void)
|
||||
e->focus = v2_lerp(e0->focus, e1->focus, tick_blend);
|
||||
|
||||
e->sprite_local_xform = xform_lerp(e0->sprite_local_xform, e1->sprite_local_xform, tick_blend);
|
||||
e->sprite_global_xform = xform_lerp(e0->sprite_global_xform, e1->sprite_global_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_frame = (u32)math_round_to_int(math_lerp(e0->animation_frame, e1->animation_frame, tick_blend));
|
||||
|
||||
@ -774,11 +778,16 @@ INTERNAL void user_update(void)
|
||||
b32 skip_debug_draw = !G.debug_camera && ent == active_camera;
|
||||
b32 skip_debug_draw_transform = entity_has_prop(ent, ENTITY_PROP_CAMERA);
|
||||
|
||||
struct xform sprite_xform = xf;
|
||||
|
||||
/* Draw sprite */
|
||||
if (!sprite_tag_is_nil(ent->sprite)) {
|
||||
struct sprite_tag sprite = ent->sprite;
|
||||
/* Calculate sprite xform */
|
||||
sprite_xform = xform_mul(xf, ent->sprite_local_xform);
|
||||
|
||||
|
||||
/* Async load */
|
||||
struct sprite_tag sprite = ent->sprite;
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite);
|
||||
struct sprite_texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite);
|
||||
(UNUSED)texture;
|
||||
@ -786,7 +795,7 @@ INTERNAL void user_update(void)
|
||||
/* 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, ent->sprite_global_xform);
|
||||
struct quad quad = quad_mul_xform(QUAD_UNIT_SQUARE_CENTERED, sprite_xform);
|
||||
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);
|
||||
}
|
||||
@ -843,7 +852,7 @@ INTERNAL void user_update(void)
|
||||
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite);
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("hold"), ent->animation_frame);
|
||||
struct v2 start = xform_mul_v2(ent->sprite_global_xform, slice.center);
|
||||
struct v2 start = xform_mul_v2(sprite_xform, slice.center);
|
||||
start = xform_mul_v2(G.world_view, start);
|
||||
struct v2 end = v2_add(xf.og, ent->focus);
|
||||
end = xform_mul_v2(G.world_view, end);
|
||||
@ -862,12 +871,12 @@ INTERNAL void user_update(void)
|
||||
for (u32 j = 0; j < group->per_frame_count; ++j) {
|
||||
struct sprite_sheet_slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j];
|
||||
|
||||
struct v2 center = xform_mul_v2(ent->sprite_global_xform, slice.center);
|
||||
struct v2 center = xform_mul_v2(sprite_xform, slice.center);
|
||||
center = xform_mul_v2(G.world_view, center);
|
||||
|
||||
if (!slice.has_ray) {
|
||||
struct quad quad = quad_from_rect(slice.rect);
|
||||
quad = quad_mul_xform(quad, ent->sprite_global_xform);
|
||||
quad = quad_mul_xform(quad, sprite_xform);
|
||||
quad = quad_mul_xform(quad, G.world_view);
|
||||
draw_solid_quad_line(G.viewport_canvas, quad, 2, RGBA_32_F(1, 0, 0.5, 1));
|
||||
}
|
||||
@ -875,7 +884,7 @@ INTERNAL void user_update(void)
|
||||
draw_solid_circle(G.viewport_canvas, center, 3, RGBA_32_F(1, 0, 0, 1), 20);
|
||||
|
||||
if (slice.has_ray) {
|
||||
struct v2 ray = xform_basis_mul_v2(ent->sprite_global_xform, slice.dir);
|
||||
struct v2 ray = xform_basis_mul_v2(sprite_xform, slice.dir);
|
||||
ray = xform_basis_mul_v2(G.world_view, ray);
|
||||
ray = v2_mul(v2_norm(ray), 25);
|
||||
draw_solid_arrow_ray(G.viewport_canvas, center, ray, 2, 10, RGBA_32_F(1, 0, 0.5, 1));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user