Fix entity AABB computation

This commit is contained in:
2025-06-06 15:22:20 +02:00
parent c05ab2d3ae
commit 4652a83218
9 changed files with 112 additions and 37 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.
+12 -3
View File
@@ -1,11 +1,17 @@
#include "chunkman.h"
/* TODO: Lots of entities are generated per-chunk. Perhaps adding them
to a queue would be better. */
/* TODO: Add queues regardless. */
int n_frame_chunks;
static GHashTable *chunks;
static GHashTable *chunk_meshes;
static bool bound = false;
static int frame_chunks = 0;
guint
chunkman_ivec2_hash (gconstpointer key)
@@ -108,6 +114,7 @@ chunkman_tick (vec3 position)
chunkman_world_to_chunk (position[0], position[2], &cx, &cz);
unsigned int frame_time = SDL_GetTicks ();
frame_chunks = 0;
for (int z = cz - RENDER_DISTANCE - 1; z <= cz + RENDER_DISTANCE + 1; ++z)
{
@@ -115,12 +122,13 @@ chunkman_tick (vec3 position)
{
if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= (RENDER_DISTANCE + 1) * (RENDER_DISTANCE + 1))
{
if (chunkman_get_Chunk_at (x, z) == NULL)
if (chunkman_get_Chunk_at (x, z) == NULL)
{
chunkman_generate_Chunk_at (x, z);
++frame_chunks;
}
if (SDL_GetTicks () - frame_time > FRAME_BUDGET)
if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET)
{
return;
}
@@ -137,9 +145,10 @@ chunkman_tick (vec3 position)
if (chunkman_get_ChunkMesh_at (x, z) == NULL)
{
chunkman_generate_ChunkMesh_at (x, z);
++frame_chunks;
}
if (SDL_GetTicks () - frame_time > FRAME_BUDGET)
if (frame_chunks > CHUNKS_PER_FRAME || SDL_GetTicks () - frame_time > FRAME_BUDGET)
{
return;
}
+2 -1
View File
@@ -13,7 +13,8 @@
#define RENDER_DISTANCE 5
#define RENDER_SQR (RENDER_DISTANCE*RENDER_DISTANCE)
#define TERRAIN_HEIGHT 8.0
#define FRAME_BUDGET 3
#define FRAME_BUDGET 5
#define CHUNKS_PER_FRAME 1
void chunkman_init ();
void chunkman_tick (vec3 position);
+17 -15
View File
@@ -33,21 +33,23 @@ typedef struct Entity
static inline void
entity_compute_aabb (Entity *e, vec3 out_min, vec3 out_max)
{
vec3 half = { 0.5f * e->scale[0], 0.5f * e->scale[1], 0.5f * e->scale[2] };
// The half extent is 1.0f, in that the mesh goes from -1 to 1.
vec3 half = { e->scale[0] * 1.0f, e->scale[1] * 1.0f, e->scale[2] * 1.0f };
out_min[0] = e->position[0] - half[0];
out_max[0] = e->position[0] + half[0];
if (e->origin == ORIGIN_BOTTOM)
{
out_min[0] = e->position[0] - half[0];
out_min[1] = e->position[1];
out_min[2] = e->position[2] - half[2];
out_max[0] = e->position[0] + half[0];
out_max[1] = e->position[1] + e->scale[1];
out_max[2] = e->position[2] + half[2];
}
{
out_min[1] = e->position[1];
out_max[1] = e->position[1] + 2.0f * half[1];
}
else
{
glm_vec3_sub (e->position, half, out_min);
glm_vec3_add (e->position, half, out_max);
}
{
out_min[1] = e->position[1] - half[1];
out_max[1] = e->position[1] + half[1];
}
out_min[2] = e->position[2] - half[2];
out_max[2] = e->position[2] + half[2];
}
+20 -15
View File
@@ -14,7 +14,7 @@ int n_frame_ents;
/* The GArray is the fastest of all sequence types. Should work fine
for a billion entities. */
static GArray *entities;
static SimpleMesh mesh_quad1, mesh_quad2, mesh_quad_x;
static SimpleMesh mesh_quad1, mesh_quad2, mesh_quad_x, mesh_cube;
static unsigned int last_program = -1;
static unsigned int last_type = -1;
static unsigned int last_texture = -1;
@@ -32,6 +32,7 @@ entman_init ()
mesh_quad1 = SimpleMesh_make_quad1 ();
mesh_quad2 = SimpleMesh_make_quad2 ();
mesh_quad_x = SimpleMesh_make_quad_x ();
mesh_cube = SimpleMesh_make_cube ();
player_entity = malloc (sizeof (Entity));
*player_entity = (Entity) {
@@ -88,9 +89,10 @@ entman_render_entity (Entity *entity, void *userdata)
{
return;
}
float cull_dist = entity->cull_distance * RENDER_DISTANCE * CHUNK_DIM;
if (glm_vec3_distance (camera_position, entity->position)
> entity->cull_distance * RENDER_DISTANCE * CHUNK_DIM && !entity->dont_cull)
if (glm_vec3_distance2 (camera_position, entity->position) > glm_pow2 (cull_dist) && !entity->dont_cull)
{
return;
}
@@ -101,7 +103,7 @@ entman_render_entity (Entity *entity, void *userdata)
#if FRUSTUM_CULL
vec3 aabb[2];
entity_compute_aabb (entity, aabb[0], aabb[1]);
if (!glm_aabb_frustum (aabb, *vp->frustum_planes))
{
return;
@@ -200,6 +202,17 @@ entman_render_entity (Entity *entity, void *userdata)
n_frame_ents++;
}
static inline int
entman_compare (gconstpointer a, gconstpointer b)
/* This function is used to sort Entities by their mesh type, so that
diferrent buffers aren't bound every single frame. */
{
const Entity *entity1 = a;
const Entity *entity2 = b;
return (int) entity1->mesh_type - (int) entity2->mesh_type;
}
void
entman_render (mat4 *view, vec4 planes[6])
{
@@ -224,6 +237,9 @@ entman_render (mat4 *view, vec4 planes[6])
#endif
};
/* Sort entities by mesh type. */
g_array_sort (entities, entman_compare);
for (guint i = 0; i < entities->len; ++i)
{
Entity *e = g_array_index (entities, Entity*, i);
@@ -231,17 +247,6 @@ entman_render (mat4 *view, vec4 planes[6])
}
}
static inline int
entman_compare (gconstpointer a, gconstpointer b)
/* This function is used to sort Entities by their mesh type, so that
diferrent buffers aren't bound every single frame. */
{
const Entity *entity1 = a;
const Entity *entity2 = b;
return (int) entity1->mesh_type - (int) entity2->mesh_type;
}
void
entman_add_entity (Entity *entity)
{
+58
View File
@@ -179,3 +179,61 @@ SimpleMesh_make_quad_x ()
return mesh;
}
SimpleMesh
SimpleMesh_make_cube ()
{
/* The positions are trivial. */
float positions[24] = {
-1.0f, -1.0f, -1.0f,
+1.0f, -1.0f, -1.0f,
+1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
+1.0f, -1.0f, 1.0f,
+1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f
};
unsigned int indices[36] = {
4, 5, 6, 6, 7, 4,
0, 3, 2, 2, 1, 0,
0, 4, 7, 7, 3, 0,
1, 2, 6, 6, 5, 1,
0, 1, 5, 5, 4, 0,
3, 7, 6, 6, 2, 3
};
float uvs[16] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0
};
SimpleMesh mesh;
mesh.indices_len = 36;
glGenBuffers (1, &mesh.pbo);
glGenBuffers (1, &mesh.uvbo);
glGenBuffers (1, &mesh.ebo);
glBindBuffer (GL_ARRAY_BUFFER, mesh.pbo);
glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 24, positions, GL_STATIC_DRAW);
glEnableVertexAttribArray (0);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, sizeof (float) * 3, 0);
glBindBuffer (GL_ARRAY_BUFFER, mesh.uvbo);
glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 16, uvs, GL_STATIC_DRAW);
glEnableVertexAttribArray (1);
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, sizeof (float) * 2, 0);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh.ebo);
glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (unsigned int) * mesh.indices_len, indices, GL_STATIC_DRAW);
return mesh;
}
+1 -1
View File
@@ -19,4 +19,4 @@ void SimpleMesh_render (SimpleMesh *mesh);
SimpleMesh SimpleMesh_make_quad1 ();
SimpleMesh SimpleMesh_make_quad2 ();
SimpleMesh SimpleMesh_make_quad_x ();
SimpleMesh SimpleMesh_make_cube ();
+2 -2
View File
@@ -152,7 +152,7 @@ resources_init ()
RAP ("chunk", RLP ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
RAP ("clouds", RLP ("res/shaders/clouds.vert", "res/shaders/clouds.frag"));
RAP ("uielement", RLP ("res/shaders/uielement.vert", "res/shaders/uielement.frag"));
RAT ("terrain0", RLT ("res/textures/dirt.png"));
RAT ("terrain1", RLT ("res/textures/drygrass.png"));
RAT ("terrain2", RLT ("res/textures/grass.png"));
@@ -167,7 +167,7 @@ resources_init ()
#undef RAP
#undef RLP
#undef RAT
#undef RLP
#undef RLT
program_use (RESPRG ("chunk"));
program_set_int_array (RESPRG ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });