z ordering for outer blocks + improve entity aabb collisions

efd/v1
Dominik Madarász 2022-10-16 00:49:29 +02:00
parent a7622ceeec
commit 50967aa046
11 changed files with 133 additions and 58 deletions

View File

@ -269,29 +269,46 @@ void game_request_close() {
} }
} }
typedef struct {
uint64_t key;
entity_view *data;
zpl_f32 y;
} game_world_render_entry;
static game_world_render_entry* render_queue = NULL; static game_world_render_entry* render_queue = NULL;
static void game__world_view_render_push_entry(uint64_t key, entity_view * data) { static void game__world_view_render_push_entry(uint64_t key, entity_view * data) {
if (data->kind == EKIND_CHUNK) return;
if (!data) return; if (!data) return;
if (data->kind == EKIND_CHUNK) {
world_view *view = game_world_view_get_active();
float size = (float)(view->chunk_size * WORLD_BLOCK_SIZE);
float offset = 0.0;
for (size_t ty = 0; ty < view->chunk_size; ty++) {
for (size_t tx = 0; tx < view->chunk_size; tx++) {
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
if (blk_id != 0) {
game_world_render_entry entry = {
.key = key,
.data = data,
.blk_id = blk_id,
.x = (data->x*size + offset) + (float)tx*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
.y = (data->y*size + offset) + (float)ty*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
};
zpl_array_append(render_queue, entry);
}
}
}
return;
}
game_world_render_entry entry = { game_world_render_entry entry = {
.key = key, .key = key,
.data = data, .data = data,
.x = data->x,
.y = data->y, .y = data->y,
.blk_id = 0,
}; };
zpl_array_append(render_queue, entry); zpl_array_append(render_queue, entry);
} }
static void game__world_view_render_ground(uint64_t key, entity_view * data) { static void game__world_view_render_ground(uint64_t key, entity_view * data) {
if (data->kind != EKIND_CHUNK) return; if (data->kind != EKIND_CHUNK) return;
renderer_draw_entry(key, data); renderer_draw_entry(key, data, 0);
} }
void game_world_view_render_world(void) { void game_world_view_render_world(void) {
@ -300,12 +317,15 @@ void game_world_view_render_world(void) {
} }
zpl_array_clear(render_queue); zpl_array_clear(render_queue);
game_world_view_active_entity_map(game__world_view_render_push_entry);
zpl_sort_array(render_queue, zpl_array_count(render_queue), zpl_f32_cmp(zpl_offset_of(game_world_render_entry, y))); profile(PROF_RENDER_PUSH_AND_SORT_ENTRIES) {
game_world_view_active_entity_map(game__world_view_render_push_entry);
zpl_sort_array(render_queue, zpl_array_count(render_queue), zpl_f32_cmp(zpl_offset_of(game_world_render_entry, y)));
}
game_world_view_active_entity_map(game__world_view_render_ground); game_world_view_active_entity_map(game__world_view_render_ground);
for (zpl_isize i = 0; i < zpl_array_count(render_queue); i++) { for (zpl_isize i = 0; i < zpl_array_count(render_queue); i++) {
renderer_draw_entry(render_queue[i].key, render_queue[i].data); renderer_draw_entry(render_queue[i].key, render_queue[i].data, &render_queue[i]);
} }
} }

View File

@ -232,6 +232,7 @@ static debug_item items[] = {
{ .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta }, { .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta }, { .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta }, { .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_RENDER_PUSH_AND_SORT_ENTRIES, .proc = DrawProfilerDelta },
{ .kind = DITEM_END }, { .kind = DITEM_END },
}, },
.is_collapsed = 1 .is_collapsed = 1

View File

@ -15,6 +15,7 @@ static profiler profilers[] = {
{ .id = PROF_UPDATE_SYSTEMS, .name = "update systems" }, { .id = PROF_UPDATE_SYSTEMS, .name = "update systems" },
{ .id = PROF_ENTITY_LERP, .name = "entity lerp" }, { .id = PROF_ENTITY_LERP, .name = "entity lerp" },
{ .id = PROF_INTEGRATE_POS, .name = "entity movement" }, { .id = PROF_INTEGRATE_POS, .name = "entity movement" },
{ .id = PROF_RENDER_PUSH_AND_SORT_ENTRIES, .name = "push&sort entries" },
}; };
static_assert((sizeof(profilers)/sizeof(profilers[0])) == MAX_PROF, "mismatched profilers"); static_assert((sizeof(profilers)/sizeof(profilers[0])) == MAX_PROF, "mismatched profilers");

View File

@ -10,6 +10,7 @@ typedef enum {
PROF_UPDATE_SYSTEMS, PROF_UPDATE_SYSTEMS,
PROF_ENTITY_LERP, PROF_ENTITY_LERP,
PROF_INTEGRATE_POS, PROF_INTEGRATE_POS,
PROF_RENDER_PUSH_AND_SORT_ENTRIES,
MAX_PROF, MAX_PROF,
PROF_FORCE_UINT8 = UINT8_MAX PROF_FORCE_UINT8 = UINT8_MAX

View File

@ -1,14 +1,23 @@
#pragma once #pragma once
#include "platform/system.h" #include "platform/system.h"
#include "world/entity_view.h" #include "world/entity_view.h"
#include "world/blocks.h"
#include "raylib.h" #include "raylib.h"
typedef struct {
uint64_t key;
entity_view *data;
float x;
float y;
block_id blk_id;
} game_world_render_entry;
void renderer_draw(void); void renderer_draw(void);
void renderer_init(void); void renderer_init(void);
void renderer_shutdown(void); void renderer_shutdown(void);
void renderer_debug_draw(void); void renderer_debug_draw(void);
float renderer_zoom_get(void); float renderer_zoom_get(void);
void renderer_draw_single(float x, float y, asset_id id, Color color); void renderer_draw_single(float x, float y, asset_id id, Color color);
void renderer_draw_entry(uint64_t key, entity_view * data); void renderer_draw_entry(uint64_t key, entity_view * data, game_world_render_entry* entry);
void renderer_bake_chunk(uint64_t key, entity_view * data); void renderer_bake_chunk(uint64_t key, entity_view * data);
void renderer_switch(int kind); void renderer_switch(int kind);

View File

@ -19,11 +19,15 @@
#include "modules/system_producer.c" #include "modules/system_producer.c"
#include "modules/system_blueprint.c" #include "modules/system_blueprint.c"
static inline float physics_correction(float x, float vx, float bounce) { static inline float physics_correction(float x, float vx, float bounce, float dim) {
float r = (((zpl_max(0.0f, (WORLD_BLOCK_SIZE/2.0f) - zpl_abs(x))*zpl_sign(x)))*(WORLD_BLOCK_SIZE/2.0f)); float r = (((zpl_max(0.0f, dim - zpl_abs(x))*zpl_sign(x)))*dim);
return r + (-vx*bounce); return r + (-vx*bounce);
} }
static inline bool physics_check_aabb(float a1x, float a2x, float a1y, float a2y, float b1x, float b2x, float b1y, float b2y) {
return (a1x < b2x && a2x > b1x && a1y < b2y && a2y > b1y);
}
void IntegratePositions(ecs_iter_t *it) { void IntegratePositions(ecs_iter_t *it) {
profile(PROF_INTEGRATE_POS) { profile(PROF_INTEGRATE_POS) {
Position *p = ecs_field(it, Position, 1); Position *p = ecs_field(it, Position, 1);
@ -47,8 +51,15 @@ void IntegratePositions(ecs_iter_t *it) {
world_block_lookup lookup = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y); world_block_lookup lookup = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y);
uint32_t flags = blocks_get_flags(lookup.bid); uint32_t flags = blocks_get_flags(lookup.bid);
float bounce = blocks_get_bounce(lookup.bid); float bounce = blocks_get_bounce(lookup.bid);
if (flags & BLOCK_FLAG_COLLISION) { if (flags & BLOCK_FLAG_COLLISION && physics_check_aabb(p[i].x-WORLD_BLOCK_SIZE/4, p[i].x+WORLD_BLOCK_SIZE/4, p[i].y-0.5f, p[i].y+0.5f, lookup.aox-WORLD_BLOCK_SIZE/2, lookup.aox+WORLD_BLOCK_SIZE/2, lookup.aoy-WORLD_BLOCK_SIZE/2, lookup.aoy+WORLD_BLOCK_SIZE/2)) {
v[i].x = physics_correction(lookup.ox, v[i].x, bounce); #if 1
{
debug_v2 a = {p[i].x-WORLD_BLOCK_SIZE/4 + PHY_LOOKAHEAD(v[i].x), p[i].y-0.5f};
debug_v2 b = {p[i].x+WORLD_BLOCK_SIZE/4 + PHY_LOOKAHEAD(v[i].x), p[i].y+0.5f};
debug_push_rect(a, b, 0xFF0000FF);
}
#endif
v[i].x = physics_correction(lookup.ox, v[i].x, bounce, WORLD_BLOCK_SIZE/2);
} }
} }
@ -57,8 +68,22 @@ void IntegratePositions(ecs_iter_t *it) {
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y+PHY_LOOKAHEAD(v[i].y)); world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y+PHY_LOOKAHEAD(v[i].y));
uint32_t flags = blocks_get_flags(lookup.bid); uint32_t flags = blocks_get_flags(lookup.bid);
float bounce = blocks_get_bounce(lookup.bid); float bounce = blocks_get_bounce(lookup.bid);
if (flags & BLOCK_FLAG_COLLISION) { #if 0
v[i].y = physics_correction(lookup.oy, v[i].y, bounce); {
debug_v2 a = {lookup.aox-WORLD_BLOCK_SIZE/2, lookup.aoy-WORLD_BLOCK_SIZE/2};
debug_v2 b = {lookup.aox+WORLD_BLOCK_SIZE/2, lookup.aoy+WORLD_BLOCK_SIZE/2};
debug_push_rect(a, b, 0xFFFFFFFF);
}
#endif
if (flags & BLOCK_FLAG_COLLISION && physics_check_aabb(p[i].x-WORLD_BLOCK_SIZE/4, p[i].x+WORLD_BLOCK_SIZE/4, p[i].y-0.5f, p[i].y+0.5f, lookup.aox-WORLD_BLOCK_SIZE/2, lookup.aox+WORLD_BLOCK_SIZE/2, lookup.aoy-WORLD_BLOCK_SIZE/2, lookup.aoy+WORLD_BLOCK_SIZE/2)) {
#if 1
{
debug_v2 a = {p[i].x-WORLD_BLOCK_SIZE/4, p[i].y-0.5f + PHY_LOOKAHEAD(v[i].y)};
debug_v2 b = {p[i].x+WORLD_BLOCK_SIZE/4, p[i].y+0.5f + PHY_LOOKAHEAD(v[i].y)};
debug_push_rect(a, b, 0xFF0000FF);
}
#endif
v[i].y = physics_correction(lookup.oy, v[i].y, bounce, WORLD_BLOCK_SIZE/4);
} }
} }
#endif #endif
@ -71,6 +96,12 @@ void IntegratePositions(ecs_iter_t *it) {
debug_v2 b = {p[i].x+v[i].x, p[i].y+v[i].y}; debug_v2 b = {p[i].x+v[i].x, p[i].y+v[i].y};
debug_push_line(a, b, 0xFFFFFFFF); debug_push_line(a, b, 0xFFFFFFFF);
} }
{
debug_v2 a = {p[i].x-WORLD_BLOCK_SIZE/4, p[i].y-0.5f};
debug_v2 b = {p[i].x+WORLD_BLOCK_SIZE/4, p[i].y+0.5f};
debug_push_rect(a, b, 0xFFFFFFFF);
}
} }
} }
} }

View File

@ -488,6 +488,10 @@ world_block_lookup world_block_from_realpos(float x, float y) {
float box = chx - bx * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f; float box = chx - bx * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f;
float boy = chy - by * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f; float boy = chy - by * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f;
// NOTE(zaklaus): absolute pos in world.
float abox = (uint16_t)(x / WORLD_BLOCK_SIZE) * (float)WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2.0f;
float aboy = (uint16_t)(y / WORLD_BLOCK_SIZE) * (float)WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2.0f;
world_block_lookup lookup = { world_block_lookup lookup = {
.id = block_idx, .id = block_idx,
.bid = bid, .bid = bid,
@ -495,6 +499,8 @@ world_block_lookup world_block_from_realpos(float x, float y) {
.chunk_e = e, .chunk_e = e,
.ox = box, .ox = box,
.oy = boy, .oy = boy,
.aox = abox,
.aoy = aboy,
.is_outer = is_outer, .is_outer = is_outer,
}; };

View File

@ -83,6 +83,7 @@ typedef struct {
ecs_entity_t chunk_e; ecs_entity_t chunk_e;
int64_t chunk_id; int64_t chunk_id;
float ox, oy; float ox, oy;
float aox, aoy;
bool is_outer; bool is_outer;
} world_block_lookup; } world_block_lookup;

View File

@ -39,7 +39,7 @@ void DEBUG_draw_overlay(uint64_t key, entity_view * data) {
} }
} }
void renderer_draw_entry(uint64_t key, entity_view *data) { void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entry* entry) {
float size = 16.f; float size = 16.f;
switch (data->kind) { switch (data->kind) {
@ -51,19 +51,14 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
float x = data->x * size + offset; float x = data->x * size + offset;
float y = data->y * size + offset; float y = data->y * size + offset;
RenderTexture2D tex = GetChunkTexture(key); if (entry == NULL) {
float scale = (size)/(float)(tex.texture.width); RenderTexture2D tex = GetChunkTexture(key);
tex.texture.width *= (int32_t)scale; float scale = (size)/(float)(tex.texture.width);
tex.texture.height *= (int32_t)scale; tex.texture.width *= (int32_t)scale;
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time)); tex.texture.height *= (int32_t)scale;
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
for (size_t ty = 0; ty < view->chunk_size; ty++) { } else {
for (size_t tx = 0; tx < view->chunk_size; tx++) { DrawTextureRec(GetBlockImage(entry->blk_id), ASSET_SRC_RECT(), (Vector2){entry->x-(WORLD_BLOCK_SIZE/2), entry->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
if (blk_id != 0) {
DrawTextureRec(GetBlockImage(blk_id), ASSET_SRC_RECT(), (Vector2){x+tx*WORLD_BLOCK_SIZE, y+ty*WORLD_BLOCK_SIZE}, ColorAlpha(WHITE, data->tran_time));
}
}
} }
}break; }break;
case EKIND_VEHICLE: { case EKIND_VEHICLE: {

View File

@ -41,7 +41,7 @@ void DEBUG_draw_overlay(uint64_t key, entity_view * data) {
extern bool inv_is_open; extern bool inv_is_open;
void renderer_draw_entry(uint64_t key, entity_view *data) { void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entry* entry) {
float size = 16.f; float size = 16.f;
switch (data->kind) { switch (data->kind) {
@ -53,19 +53,14 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
float x = data->x * size + offset; float x = data->x * size + offset;
float y = data->y * size + offset; float y = data->y * size + offset;
RenderTexture2D tex = GetChunkTexture(key); if (entry == NULL) {
float scale = (size)/(float)(tex.texture.width); RenderTexture2D tex = GetChunkTexture(key);
tex.texture.width *= (int32_t)scale; float scale = (size)/(float)(tex.texture.width);
tex.texture.height *= (int32_t)scale; tex.texture.width *= (int32_t)scale;
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time)); tex.texture.height *= (int32_t)scale;
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
for (size_t ty = 0; ty < view->chunk_size; ty++) { } else {
for (size_t tx = 0; tx < view->chunk_size; tx++) { DrawTextureRec(GetBlockImage(entry->blk_id), ASSET_SRC_RECT(), (Vector2){entry->x-(WORLD_BLOCK_SIZE/2), entry->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
if (blk_id != 0) {
DrawTextureRec(GetBlockImage(blk_id), ASSET_SRC_RECT(), (Vector2){x+tx*WORLD_BLOCK_SIZE, y+ty*WORLD_BLOCK_SIZE}, ColorAlpha(WHITE, data->tran_time));
}
}
} }
}break; }break;
case EKIND_VEHICLE: { case EKIND_VEHICLE: {
@ -94,15 +89,25 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
case EKIND_DEMO_NPC: { case EKIND_DEMO_NPC: {
float x = data->x; float x = data->x;
float y = data->y; float y = data->y;
if (!data->inside_vehicle) {
DrawCircleEco(x, y, size, ColorAlpha(BLUE, data->tran_time));
} else {
y -= 32.f;
}
DrawNametag("Demo", key, data, x, y); DrawNametag("Demo", key, data, x, y);
DrawCircleEco(x, y, size, ColorAlpha(BLUE, data->tran_time));
}break; }break;
case EKIND_PLAYER: { case EKIND_PLAYER: {
float x = data->x; float x = data->x;
float y = data->y; float y = data->y;
float health = (data->hp / data->max_hp); float health = (data->hp / data->max_hp);
if (!data->inside_vehicle) {
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
} else {
y -= 32.f;
}
DrawNametag("Player", key, data, x, y); DrawNametag("Player", key, data, x, y);
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
if (data->has_items && !data->inside_vehicle) { if (data->has_items && !data->inside_vehicle) {
float ix = data->x; float ix = data->x;
@ -120,6 +125,11 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
case EKIND_MACRO_BOT: { case EKIND_MACRO_BOT: {
float x = data->x; float x = data->x;
float y = data->y; float y = data->y;
if (!data->inside_vehicle) {
DrawCircleEco(x, y, size, ColorAlpha(GREEN, data->tran_time));
} else {
y -= 32.f;
}
DrawNametag("Bot", key, data, x, y); DrawNametag("Bot", key, data, x, y);
}break; }break;
case EKIND_ITEM: { case EKIND_ITEM: {