Remove the billions of structs and globals

This commit is contained in:
2025-06-04 14:39:40 +02:00
parent 0a0ba010b5
commit 0e5b0d1e32
24 changed files with 374 additions and 408 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
SRC=src/main.c src/program.c src/resources.c src/camera.c src/chunk/chunk.c \
SRC=src/main.c src/program.c src/res.c src/camera.c src/chunk/chunk.c \
src/chunk/mesh.c src/flags.c src/texture.c src/chunk/manager.c \
src/event/manager.c src/event/handlers.c src/state.c src/graphics.c \
src/entity/meshes.c src/entity/manager.c src/entity/templates.c
+14 -31
View File
@@ -1,54 +1,37 @@
#include "camera.h"
Camera
Camera_default ()
{
Camera cam = {
.position = { 0.0f, 0.0f, 0.0f },
.rotation = { 0.0f, 0.0f, 0.0f },
.fov = 80,
.near = 0.1,
.far = 1000.0
};
return cam;
}
vec3 camera_position;
vec3 camera_rotation;
void
Camera_get_direction (Camera *camera, vec3 dest)
camera_get_direction (vec3 dest)
{
dest[0] = sinf (camera->rotation[0]) * cosf (camera->rotation[1]);
dest[1] = sinf (camera->rotation[1]);
dest[2] = cosf (camera->rotation[0]) * cosf (camera->rotation[1]);
dest[0] = sinf (camera_rotation[0]) * cosf (camera_rotation[1]);
dest[1] = sinf (camera_rotation[1]);
dest[2] = cosf (camera_rotation[0]) * cosf (camera_rotation[1]);
glm_vec3_normalize (dest);
}
void
Camera_get_right (Camera *camera, vec3 dest)
camera_get_right (vec3 dest)
{
vec3 dir;
Camera_get_direction (camera, dir);
camera_get_direction (dir);
glm_vec3_cross (dir, GLM_YUP, dest);
glm_vec3_normalize (dest);
}
void
Camera_get_view (Camera *camera, mat4 dest)
camera_get_view (mat4 dest)
{
vec3 dir, center;
Camera_get_direction (camera, dir);
glm_vec3_add (camera->position, dir, center);
glm_lookat (camera->position, center, GLM_YUP, dest);
camera_get_direction (dir);
glm_vec3_add (camera_position, dir, center);
glm_lookat (camera_position, center, GLM_YUP, dest);
}
void
Camera_get_projection (Camera *camera, float aspect, mat4 dest)
camera_get_projection (float aspect, mat4 dest)
{
glm_perspective (DEGTORAD (camera->fov), aspect, camera->near, camera->far, dest);
}
void
Camera_print (Camera *camera)
{
INFO ("Camera position: (%6.1f, %6.1f, %6.1f)", camera->position[0], camera->position[1], camera->position[2]);
glm_perspective (glm_rad (90), aspect, 0.1, 1000.0, dest);
}
+4 -16
View File
@@ -4,19 +4,7 @@
#include "util.h"
typedef struct Camera
{
vec3 position;
vec3 rotation;
int fov;
float near;
float far;
} Camera;
Camera Camera_default ();
void Camera_get_direction (Camera *camera, vec3 dest);
void Camera_get_right (Camera *camera, vec3 dest);
void Camera_get_view (Camera *camera, mat4 dest);
void Camera_get_projection (Camera *camera, float aspect, mat4 dest);
void Camera_print (Camera *camera);
void camera_get_direction (vec3 dest);
void camera_get_right (vec3 dest);
void camera_get_view (mat4 dest);
void camera_get_projection (float aspect, mat4 dest);
+4 -7
View File
@@ -2,9 +2,6 @@
#include <math.h>
extern GHashTable *entity_templates;
extern GSequence *entity_manager;
Chunk *
Chunk_new ()
{
@@ -31,22 +28,22 @@ Chunk_random (Chunk *chunk, int xoffset, int zoffset)
if (rand() % 100 < 2)
{
Entity *tree = malloc (sizeof (Entity));
*tree = ET_ENTGET ("tree");
*tree = ETEMPLGET ("tree");
tree->position[0] = x + xoffset;
tree->position[1] = chunk->heightmap [INDEX (x, z)];
tree->position[2] = z + zoffset;
tree->rotation = rand () % 180;
EM_ENTADD (tree);
em_add_entity (tree);
}
if (rand() % 100 < 10)
{
Entity *grass = malloc (sizeof (Entity));
*grass = ET_ENTGET ("grass");
*grass = ETEMPLGET ("grass");
grass->position[0] = x + xoffset;
grass->position[1] = chunk->heightmap [INDEX (x, z)];
grass->position[2] = z + zoffset;
EM_ENTADD (grass);
em_add_entity (grass);
}
}
}
+30 -29
View File
@@ -3,7 +3,8 @@
/* TODO: perhaps render the chunks in a circle, not a square, around
the player? */
ChunkManager chunk_manager;
static GHashTable *chunks;
static GHashTable *chunk_meshes;
guint
cm_ivec2_hash (gconstpointer key)
@@ -37,17 +38,17 @@ cm_world_to_chunk (float x, float z, int *ox, int *oz)
}
void
ChunkManager_init ()
cm_init ()
{
chunk_manager.chunks = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free);
chunk_manager.chunk_meshes = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free);
chunks = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free);
chunk_meshes = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free);
}
/* TODO: Update the chunks only if the player has moved into another
chunk, to save frame time. */
void
ChunkManager_update (vec3 camera_position)
cm_update (vec3 camera_position)
{
int cx, cz;
cm_world_to_chunk (camera_position[0], camera_position[2], &cx, &cz);
@@ -56,9 +57,9 @@ ChunkManager_update (vec3 camera_position)
{
for (int x = cx - RENDER_DISTANCE - 1; x <= cx + RENDER_DISTANCE + 1; ++x)
{
if (ChunkManager_get_Chunk_at (x, z) == NULL)
if (cm_get_Chunk_at (x, z) == NULL)
{
ChunkManager_generate_Chunk_at (x, z);
cm_generate_Chunk_at (x, z);
}
}
}
@@ -67,16 +68,16 @@ ChunkManager_update (vec3 camera_position)
{
for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x)
{
if (ChunkManager_get_ChunkMesh_at (x, z) == NULL)
if (cm_get_ChunkMesh_at (x, z) == NULL)
{
ChunkManager_generate_ChunkMesh_at (x, z);
cm_generate_ChunkMesh_at (x, z);
}
}
}
}
void
ChunkManager_render (vec3 camera_position, int program)
cm_render (vec3 camera_position, int program)
{
int cx = 0, cz = 0;
cm_world_to_chunk (camera_position[0], camera_position[2], &cx, &cz);
@@ -85,7 +86,7 @@ ChunkManager_render (vec3 camera_position, int program)
{
for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x)
{
ChunkMesh *mesh = ChunkManager_get_ChunkMesh_at (x, z);
ChunkMesh *mesh = cm_get_ChunkMesh_at (x, z);
if (mesh != NULL)
{
program_set_vec3 (program, "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM);
@@ -96,50 +97,50 @@ ChunkManager_render (vec3 camera_position, int program)
}
Chunk *
ChunkManager_get_Chunk_at (int x, int z)
cm_get_Chunk_at (int x, int z)
{
return (Chunk *) g_hash_table_lookup (chunk_manager.chunks, (ivec2) { x, z });
return (Chunk *) g_hash_table_lookup (chunks, (ivec2) { x, z });
}
void
ChunkManager_set_Chunk_at (int x, int z, Chunk *chunk)
cm_set_Chunk_at (int x, int z, Chunk *chunk)
{
g_hash_table_insert (chunk_manager.chunks, cm_make_key (x, z), chunk);
g_hash_table_insert (chunks, cm_make_key (x, z), chunk);
}
void
ChunkManager_generate_Chunk_at (int x, int z)
cm_generate_Chunk_at (int x, int z)
{
Chunk *chunk = Chunk_new ();
Chunk_random (chunk, x * CHUNK_DIM, z * CHUNK_DIM);
ChunkManager_set_Chunk_at (x, z, chunk);
cm_set_Chunk_at (x, z, chunk);
}
void
ChunkManager_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc)
cm_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc)
{
*nr = ChunkManager_get_Chunk_at (x + 1, z);
*nd = ChunkManager_get_Chunk_at (x, z + 1);
*nc = ChunkManager_get_Chunk_at (x + 1, z + 1);
*nr = cm_get_Chunk_at (x + 1, z);
*nd = cm_get_Chunk_at (x, z + 1);
*nc = cm_get_Chunk_at (x + 1, z + 1);
}
ChunkMesh *
ChunkManager_get_ChunkMesh_at (int x, int z)
cm_get_ChunkMesh_at (int x, int z)
{
return (ChunkMesh *) g_hash_table_lookup (chunk_manager.chunk_meshes, (ivec2) { x, z });
return (ChunkMesh *) g_hash_table_lookup (chunk_meshes, (ivec2) { x, z });
}
void
ChunkManager_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh)
cm_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh)
{
g_hash_table_insert (chunk_manager.chunk_meshes, cm_make_key (x, z), mesh);
g_hash_table_insert (chunk_meshes, cm_make_key (x, z), mesh);
}
void
ChunkManager_generate_ChunkMesh_at (int x, int z)
cm_generate_ChunkMesh_at (int x, int z)
{
Chunk *nr, *nd, *nc;
ChunkManager_get_Chunk_neighbors_at (x, z, &nr, &nd, &nc);
ChunkManager_set_ChunkMesh_at
(x, z, ChunkMesh_build (ChunkManager_get_Chunk_at (x, z), nr, nd, nc));
cm_get_Chunk_neighbors_at (x, z, &nr, &nd, &nc);
cm_set_ChunkMesh_at
(x, z, ChunkMesh_build (cm_get_Chunk_at (x, z), nr, nd, nc));
}
+10 -19
View File
@@ -9,25 +9,16 @@
#define RENDER_DISTANCE 3
typedef struct ChunkManager
{
GHashTable *chunks;
GHashTable *chunk_meshes;
void cm_init ();
void cm_update (vec3 camera_position);
void cm_render (vec3 camera_position, int program);
GAsyncQueue *chunk_queue;
GAsyncQueue *chunk_mesh_queue;
} ChunkManager;
Chunk *cm_get_Chunk_at (int x, int z);
void cm_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc);
void cm_set_Chunk_at (int x, int z, Chunk *chunk);
void ChunkManager_init ();
void ChunkManager_update (vec3 camera_position);
void ChunkManager_render (vec3 camera_position, int program);
ChunkMesh *cm_get_ChunkMesh_at (int x, int z);
void cm_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh);
Chunk *ChunkManager_get_Chunk_at (int x, int z);
void ChunkManager_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc);
void ChunkManager_set_Chunk_at (int x, int z, Chunk *chunk);
ChunkMesh *ChunkManager_get_ChunkMesh_at (int x, int z);
void ChunkManager_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh);
void ChunkManager_generate_Chunk_at (int x, int z);
void ChunkManager_generate_ChunkMesh_at (int x, int z);
void cm_generate_Chunk_at (int x, int z);
void cm_generate_ChunkMesh_at (int x, int z);
+1 -3
View File
@@ -3,8 +3,6 @@
/* No need to bind the elements buffer all the time; it's the same for
every single ChunkMesh. */
extern GameFlags game_flags;
ChunkMesh *
ChunkMesh_build (Chunk *chunk, Chunk *nr, Chunk *nd, Chunk *nc)
/* nd --- down neighbor; nr --- right neighbor; nc --- corner neighbor */
@@ -110,7 +108,7 @@ ChunkMesh_render (ChunkMesh *mesh)
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, mesh->ebo);
if (game_flags.wireframe_enabled)
if (flags_get ("wireframe_enabled"))
{
glDrawElements (GL_LINES, CHUNK_SIZE * 6, GL_UNSIGNED_INT, 0);
}
+48 -22
View File
@@ -1,21 +1,15 @@
#include "manager.h"
/* TODO: Sort entities by mesh type AS WELL AS distance. Binding
buffers is very performance-sensitive, thus to conserve speed one
type should be rendered in one go, then the other type, etc. */
extern vec3 camera_position;
GSequence *entity_manager;
EntityMesh mesh_quad2, mesh_quad_x;
extern GameState game_state;
extern Resources resources;
unsigned int last_type = -1;
static GSequence *entities;
static EntityMesh mesh_quad2, mesh_quad_x;
static unsigned int last_type = -1;
void
EntityManager_init ()
em_init ()
{
entity_manager = g_sequence_new (NULL);
entities = g_sequence_new (NULL);
mesh_quad2 = EntityMesh_make_quad2 ();
mesh_quad_x = EntityMesh_make_quad_x ();
}
@@ -33,9 +27,9 @@ em_tick_internal (gpointer data, gpointer userdata)
}
void
EntityManager_tick ()
em_tick ()
{
g_sequence_foreach (entity_manager, em_tick_internal, NULL);
g_sequence_foreach (entities, em_tick_internal, NULL);
}
void
@@ -44,7 +38,7 @@ em_render_internal (gpointer data, gpointer userdata)
Entity *entity = data;
mat4 *view = userdata;
if (glm_vec3_distance (game_state.camera.position, entity->position) > EM_RENDER_DISTANCE)
if (glm_vec3_distance (camera_position, entity->position) > EM_RENDER_DISTANCE)
{
return;
}
@@ -55,7 +49,7 @@ em_render_internal (gpointer data, gpointer userdata)
vec4 planes[6];
mat4 proj, view_proj;
Camera_get_projection (&game_state.camera, 640.0 / 480.0, proj);
camera_get_projection (640.0 / 480.0, proj);
glm_mat4_mul (proj, *view, view_proj);
glm_frustum_planes (view_proj, planes);
@@ -113,7 +107,7 @@ em_render_internal (gpointer data, gpointer userdata)
/* It's not quite a "real" billboard, but the effect is much
better on the eye. */
vec3 delta;
glm_vec3_sub (game_state.camera.position, entity->position, delta);
glm_vec3_sub (camera_position, entity->position, delta);
delta[1] = 0.0;
glm_normalize (delta);
glm_rotate_at(model, entity->position, atan2f (delta[0], delta[2]), (vec3) { 0.0, 1.0, 0.0 });
@@ -132,11 +126,10 @@ em_render_internal (gpointer data, gpointer userdata)
glm_scale (model, entity->scale);
program_use (R_PRGGET ("default"));
program_set_mat4 (R_PRGGET ("default"), "model", model);
program_set_mat4 (RESPRG ("default"), "model", model);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, R_TEXGET (entity->texture));
glBindTexture (GL_TEXTURE_2D, RESTEX (entity->texture));
if (entity->mesh_type != last_type)
{
@@ -148,7 +141,40 @@ em_render_internal (gpointer data, gpointer userdata)
}
void
EntityManager_render (mat4 view)
em_render (mat4 view)
{
g_sequence_foreach (entity_manager, em_render_internal, view);
g_sequence_foreach (entities, em_render_internal, view);
}
static inline int
em_compare (gconstpointer a, gconstpointer b, gpointer userdata)
/* This function is used to sort Entities by their mesh type, so that
diferrent buffers aren't bound every single frame. */
{
UNUSED (userdata);
const Entity *entity1 = a;
const Entity *entity2 = b;
if (entity1->mesh_type == entity2->mesh_type)
{
return 0;
}
if (entity1->mesh_type == MESH_QUAD_X && entity2->mesh_type == MESH_QUAD2)
{
return -1;
}
if (entity1->mesh_type == MESH_QUAD2 && entity2->mesh_type == MESH_QUAD_X)
{
return 1;
}
return (int) entity1->mesh_type - (int) entity2->mesh_type;
}
void
em_add_entity (Entity *entity)
{
g_sequence_insert_sorted (entities, entity, em_compare, NULL);
}
+5 -33
View File
@@ -6,41 +6,13 @@
#include "entity.h"
#include "meshes.h"
#include "../util.h"
#include "../resources.h"
#include "../res.h"
#include "../state.h"
#include "../chunk/chunk.h"
#define EM_RENDER_DISTANCE (3*CHUNK_DIM/2)
#define EM_ENTADD(entity) (g_sequence_insert_sorted (entity_manager, entity, em_compare, NULL));
static inline int
em_compare (gconstpointer a, gconstpointer b, gpointer userdata)
/* This function is used to sort Entities by their mesh type, so that
diferrent buffers aren't bound every single frame. */
{
UNUSED (userdata);
const Entity *entity1 = a;
const Entity *entity2 = b;
if (entity1->mesh_type == entity2->mesh_type)
{
return 0;
}
if (entity1->mesh_type == MESH_QUAD_X && entity2->mesh_type == MESH_QUAD2)
{
return -1;
}
if (entity1->mesh_type == MESH_QUAD2 && entity2->mesh_type == MESH_QUAD_X)
{
return 1;
}
return (int) entity1->mesh_type - (int) entity2->mesh_type;
}
void EntityManager_init ();
void EntityManager_tick ();
void EntityManager_render ();
void em_init ();
void em_tick ();
void em_render ();
void em_add_entity (Entity *entity);
+1 -3
View File
@@ -2,8 +2,6 @@
/* TODO: Split binding/rendering */
extern GameFlags game_flags;
void
EntityMesh_bind (EntityMesh *mesh)
{
@@ -21,7 +19,7 @@ EntityMesh_bind (EntityMesh *mesh)
void
EntityMesh_render (EntityMesh *mesh)
{
if (game_flags.wireframe_enabled)
if (flags_get ("wireframe_enabled"))
{
glDrawElements (GL_LINES, mesh->indices_len, GL_UNSIGNED_INT, 0);
}
+17 -8
View File
@@ -1,11 +1,23 @@
#include "templates.h"
GHashTable *entity_templates;
static GHashTable *templates;
static inline void
ent_templates_add (char *key, Entity *entity)
{
g_hash_table_insert (templates, key, entity);
}
Entity
ent_templates_get (char *key)
{
return *(Entity *) g_hash_table_lookup (templates, key);
}
void
EntityTemplates_init ()
ent_templates_init ()
{
entity_templates = g_hash_table_new (g_str_hash, g_str_equal);
templates = g_hash_table_new (g_str_hash, g_str_equal);
Entity *tree = malloc (sizeof (Entity));
*tree = (Entity) {
@@ -17,7 +29,7 @@ EntityTemplates_init ()
.texture = "tree0"
};
ET_ENTADD ("tree", tree);
ent_templates_add ("tree", tree);
Entity *grass = malloc (sizeof (Entity));
*grass = (Entity) {
@@ -30,8 +42,5 @@ EntityTemplates_init ()
.texture = "grass0"
};
ET_ENTADD ("grass", grass);
ent_templates_add ("grass", grass);
}
/* To avoid confusion with EM_ENTADD. */
#undef ET_ENTADD
+3 -6
View File
@@ -1,8 +1,5 @@
#pragma once
/* TODO: Maybe make a function that allocates an Entity for you and
adds it's data from the template? */
#include <stdlib.h>
#include <glib-2.0/glib.h>
@@ -10,7 +7,7 @@
#include "entity.h"
#define ET_ENTGET(key) (*(Entity *) g_hash_table_lookup (entity_templates, key))
#define ET_ENTADD(key, entity) (g_hash_table_insert (entity_templates, key, entity))
#define ETEMPLGET(key) (ent_templates_get (key))
void EntityTemplates_init ();
void ent_templates_init ();
Entity ent_templates_get (char *key);
+16 -16
View File
@@ -1,7 +1,7 @@
#include "handlers.h"
extern GameState game_state;
extern GameFlags game_flags;
extern vec3 camera_position;
extern vec3 camera_rotation;
void
handlers_init ()
@@ -13,12 +13,12 @@ handlers_init ()
void
handler_lookaround (SDL_Event *event)
{
if (event->type == SDL_EVENT_MOUSE_MOTION && game_flags.can_free_look)
if (event->type == SDL_EVENT_MOUSE_MOTION)
{
game_state.camera.rotation[0] -= event->motion.xrel / 100.f;
game_state.camera.rotation[1] -= event->motion.yrel / 100.f;
game_state.camera.rotation[1] =
CLAMP (game_state.camera.rotation[1], -M_PI / 2 + 0.025, M_PI / 2 - 0.025);
camera_rotation[0] -= event->motion.xrel / 100.f;
camera_rotation[1] -= event->motion.yrel / 100.f;
camera_rotation[1] =
CLAMP (camera_rotation[1], -M_PI / 2 + 0.025, M_PI / 2 - 0.025);
}
}
@@ -30,19 +30,19 @@ handler_movement (SDL_Event *event)
switch (event->key.key)
{
case SDLK_W:
game_flags.moving_forward = 1;
flags_set ("moving_forward", true);
break;
case SDLK_A:
game_flags.moving_left = 1;
flags_set ("moving_left", true);
break;
case SDLK_S:
game_flags.moving_backward = 1;
flags_set ("moving_backward", true);
break;
case SDLK_D:
game_flags.moving_right = 1;
flags_set ("moving_right", true);
break;
case SDLK_F1:
game_flags.wireframe_enabled = !game_flags.wireframe_enabled;
flags_set ("wireframe_enabled", !flags_get ("wireframe_enabled"));
break;
}
}
@@ -52,16 +52,16 @@ handler_movement (SDL_Event *event)
switch (event->key.key)
{
case SDLK_W:
game_flags.moving_forward = 0;
flags_set ("moving_forward", false);
break;
case SDLK_A:
game_flags.moving_left = 0;
flags_set ("moving_left", false);
break;
case SDLK_S:
game_flags.moving_backward = 0;
flags_set ("moving_backward", false);
break;
case SDLK_D:
game_flags.moving_right = 0;
flags_set ("moving_right", false);
break;
}
}
+20 -1
View File
@@ -1,3 +1,22 @@
#include "flags.h"
GameFlags game_flags = { 0 };
static GHashTable *flags;
void
flags_init ()
{
flags = g_hash_table_new (g_str_hash, g_str_equal);
flags_set ("wireframe_enabled", false);
}
void
flags_set (char *flag, bool value)
{
g_hash_table_replace (flags, flag, GINT_TO_POINTER (value));
}
bool
flags_get (char *flag)
{
return GPOINTER_TO_INT (g_hash_table_lookup (flags, flag));
}
+5 -14
View File
@@ -1,18 +1,9 @@
#pragma once
typedef struct GameFlags
{
/* Volatile state flags, zeroed at start. */
int in_main_menu: 1;
int in_pause_menu: 1;
int in_game: 1;
#include <stdbool.h>
int can_free_look: 1;
int moving_forward: 1;
int moving_backward: 1;
int moving_left: 1;
int moving_right: 1;
#include <glib-2.0/glib.h>
int wireframe_enabled: 1;
/* Saved state flags, loaded from game save/map. */
} GameFlags;
void flags_init ();
void flags_set (char *flag, bool value);
bool flags_get (char *flag);
+34 -35
View File
@@ -1,22 +1,21 @@
#include "graphics.h"
GraphicsContext gfx;
extern vec3 camera_position;
extern ChunkManager chunk_manager;
extern GameState game_state;
extern Resources resources;
static SDL_Window *sdl_window;
static SDL_GLContext gl_context;
void
GraphicsContext_init ()
graphics_init ()
{
if (!SDL_Init (SDL_INIT_VIDEO))
{
FATAL ("Couldn't initialize SDL: %s", SDL_GetError ());
}
gfx.window = SDL_CreateWindow (GAME_NAME, 640, 480, SDL_WINDOW_OPENGL);
sdl_window = SDL_CreateWindow (GAME_NAME, 640, 480, SDL_WINDOW_OPENGL);
if (!gfx.window)
if (!sdl_window)
{
FATAL ("Couldn't create window: %s", SDL_GetError ());
}
@@ -27,66 +26,66 @@ GraphicsContext_init ()
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION, 0);
gfx.gl_context = SDL_GL_CreateContext (gfx.window);
gl_context = SDL_GL_CreateContext (sdl_window);
if (!gfx.gl_context)
if (!gl_context)
{
FATAL ("Couldn't create OpenGL context: %s", SDL_GetError ());
}
SDL_GL_MakeCurrent (gfx.window, gfx.gl_context);
SDL_SetWindowRelativeMouseMode (gfx.window, true);
SDL_GL_MakeCurrent (sdl_window, gl_context);
SDL_SetWindowRelativeMouseMode (sdl_window, true);
INFO ("Renderer: %s", glGetString (GL_RENDERER));
INFO ("OpenGL version: %s", glGetString (GL_VERSION));
INFO ("GLSL version: %s", glGetString (GL_SHADING_LANGUAGE_VERSION));
INFO ("Max vertex attributes: %d", GL_MAX_VERTEX_ATTRIBS);
glViewport(0, 0, 640, 480);
glViewport (0, 0, 640, 480);
glClearColor (0, 0.3, 0.8, 1);
glEnable (GL_CULL_FACE);
glEnable (GL_DEPTH_TEST);
glEnable (GL_DEPTH_TEST);
}
void
GraphicsContext_render ()
graphics_render ()
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mat4 projection, view;
Camera_get_projection (&game_state.camera, 640.0 / 480.0, projection);
Camera_get_view (&game_state.camera, view);
camera_get_projection (640.0 / 480.0, projection);
camera_get_view (view);
/* Set views and projections in all programs. TODO: make this dynamic*/
program_use (R_PRGGET ("default"));
program_set_mat4 (R_PRGGET ("default"), "projection", projection);
program_set_mat4 (R_PRGGET ("default"), "view", view);
program_use (R_PRGGET ("chunk"));
program_set_mat4 (R_PRGGET ("chunk"), "projection", projection);
program_set_mat4 (R_PRGGET ("chunk"), "view", view);
program_use (RESPRG ("chunk"));
program_set_mat4 (RESPRG ("chunk"), "projection", projection);
program_set_mat4 (RESPRG ("chunk"), "view", view);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain0"));
glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain0"));
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain1"));
glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain1"));
glActiveTexture (GL_TEXTURE2);
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain2"));
glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain2"));
glActiveTexture (GL_TEXTURE3);
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain3"));
glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain3"));
glActiveTexture (GL_TEXTURE4);
glBindTexture (GL_TEXTURE_2D, R_TEXGET ("terrain4"));
glBindTexture (GL_TEXTURE_2D, RESTEX ("terrain4"));
ChunkManager_render (game_state.camera.position, R_PRGGET ("chunk"));
EntityManager_render (view);
cm_render (camera_position, RESPRG ("chunk"));
SDL_GL_SwapWindow (gfx.window);
/* Set views and projections in all programs. TODO: make this dynamic*/
program_use (RESPRG ("default"));
program_set_mat4 (RESPRG ("default"), "projection", projection);
program_set_mat4 (RESPRG ("default"), "view", view);
em_render (view);
SDL_GL_SwapWindow (sdl_window);
}
void
GraphicsContext_free ()
graphics_free ()
{
SDL_GL_DestroyContext (gfx.gl_context);
SDL_DestroyWindow (gfx.window);
SDL_GL_DestroyContext (gl_context);
SDL_DestroyWindow (sdl_window);
}
+4 -10
View File
@@ -7,14 +7,8 @@
#include "chunk/manager.h"
#include "entity/manager.h"
#include "state.h"
#include "resources.h"
#include "res.h"
typedef struct GraphicsContext
{
SDL_Window *window;
SDL_GLContext gl_context;
} GraphicsContext;
void GraphicsContext_init ();
void GraphicsContext_render ();
void GraphicsContext_free ();
void graphics_init ();
void graphics_render ();
void graphics_free ();
+14 -17
View File
@@ -8,11 +8,10 @@
#include "chunk/manager.h"
#include "entity/templates.h"
#include "state.h"
#include "resources.h"
#include "res.h"
#include "graphics.h"
extern GameState game_state;
extern GameFlags game_flags;
extern vec3 camera_position;
SDL_AppResult
SDL_AppInit (void **appstate, int argc, char **argv)
@@ -20,16 +19,14 @@ SDL_AppInit (void **appstate, int argc, char **argv)
UNUSED (appstate, argc, argv);
SDL_SetAppMetadata (GAME_NAME, GAME_VERSION, "eur.chopininteractive.wschod-game");
GraphicsContext_init ();
graphics_init ();
handlers_init ();
Resources_init ();
ChunkManager_init ();
EntityManager_init ();
EntityTemplates_init ();
GameState_init (SDL_GetTicks ());
/* Set some basic game flags for testing. */
game_flags.can_free_look = 1;
game_flags.wireframe_enabled = 0;
res_init ();
cm_init ();
em_init ();
ent_templates_init ();
flags_init ();
game_state_init (SDL_GetTicks ());
return SDL_APP_CONTINUE;
}
@@ -53,10 +50,10 @@ SDL_AppIterate (void *appstate)
{
UNUSED (appstate);
GameState_tick (SDL_GetTicks ());
EntityManager_tick ();
ChunkManager_update (game_state.camera.position);
GraphicsContext_render ();
game_state_tick (SDL_GetTicks ());
em_tick ();
cm_update (camera_position);
graphics_render ();
return SDL_APP_CONTINUE;
}
@@ -65,5 +62,5 @@ void
SDL_AppQuit (void *appstate, SDL_AppResult result)
{
UNUSED (appstate, result);
GraphicsContext_free ();
graphics_free ();
}
+99
View File
@@ -0,0 +1,99 @@
#include "res.h"
static GHashTable *programs;
static GHashTable *textures;
unsigned int
res_load_program (const char *v_path, const char *f_path)
{
FILE *v_file = fopen (v_path, "r");
if (v_file == NULL)
{
WARN ("File `%s' does not exist.", v_path);
}
fseek (v_file, 0L, SEEK_END);
size_t v_len = ftell (v_file) + 1;
char *v_src = calloc (v_len, sizeof (char));
rewind (v_file);
INFO ("Read %zu bytes from vertex source.", fread (v_src, sizeof (char), v_len, v_file));
FILE *f_file = fopen (f_path, "r");
if (f_file == NULL)
{
WARN ("File `%s' does not exist.", f_path);
}
fseek (f_file, 0L, SEEK_END);
size_t f_len = ftell (f_file) + 1;
char *f_src = calloc (f_len, sizeof (char));
rewind (f_file);
INFO ("Read %zu bytes from fragment source.", fread (f_src, sizeof (char), f_len, f_file));
unsigned int program = program_create (v_src, f_src);
free (v_src);
free (f_src);
return program;
}
unsigned int
res_load_texture (const char *path)
{
SDL_Surface *surface = IMG_Load (path);
if (surface == NULL)
{
WARN ("Failed to load texture from path %s: %s", path, SDL_GetError ());
}
unsigned int texture = texture_create (surface->w, surface->h, surface->pixels);
return texture;
}
static inline void
res_add_program (char *key, unsigned int program)
{
g_hash_table_insert (programs, key, GINT_TO_POINTER (program));
}
static inline void
res_add_texture (char *key, unsigned int texture)
{
g_hash_table_insert (textures, key, GINT_TO_POINTER (texture));
}
unsigned int
res_get_program (char *key)
{
return GPOINTER_TO_INT (g_hash_table_lookup (programs, key));
}
unsigned int
res_get_texture (char *key)
{
return GPOINTER_TO_INT (g_hash_table_lookup (textures, key));
}
void
res_init ()
{
programs = g_hash_table_new (g_str_hash, g_str_equal);
textures = g_hash_table_new (g_str_hash, g_str_equal);
res_add_program ("default", res_load_program ("res/shaders/default.vert", "res/shaders/default.frag"));
res_add_program ("chunk", res_load_program ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
program_use (res_get_program ("chunk"));
program_set_int_array (res_get_program ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });
res_add_texture ("terrain0", res_load_texture ("res/textures/dirt.png"));
res_add_texture ("terrain1", res_load_texture ("res/textures/drygrass.png"));
res_add_texture ("terrain2", res_load_texture ("res/textures/grass.png"));
res_add_texture ("terrain3", res_load_texture ("res/textures/rock_cement.png"));
res_add_texture ("terrain4", res_load_texture ("res/textures/asphalt_gravel.png"));
res_add_texture ("tree0", res_load_texture ("res/textures/tree.png"));
res_add_texture ("grass0", res_load_texture ("res/textures/grass0.png"));
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <SDL3_image/SDL_image.h>
#include <glib-2.0/glib.h>
#include "program.h"
#include "texture.h"
#define RESPRG(key) (res_get_program (key))
#define RESTEX(key) (res_get_texture (key))
unsigned int res_get_program (char *key);
unsigned int res_get_texture (char *key);
void res_init ();
-74
View File
@@ -1,74 +0,0 @@
#include "resources.h"
Resources resources;
void
Resources_init ()
{
resources.programs = g_hash_table_new (g_str_hash, g_str_equal);
resources.textures = g_hash_table_new (g_str_hash, g_str_equal);
R_PRGADD ("default", R_PRGLOAD ("res/shaders/default.vert", "res/shaders/default.frag"));
R_PRGADD ("chunk", R_PRGLOAD ("res/shaders/chunk.vert", "res/shaders/chunk.frag"));
program_use (R_PRGGET ("chunk"));
program_set_int_array (R_PRGGET ("chunk"), "materials", 5, (int[5]) { 0, 1, 2, 3, 4 });
R_TEXADD ("terrain0", R_TEXLOAD ("res/textures/dirt.png"));
R_TEXADD ("terrain1", R_TEXLOAD ("res/textures/drygrass.png"));
R_TEXADD ("terrain2", R_TEXLOAD ("res/textures/grass.png"));
R_TEXADD ("terrain3", R_TEXLOAD ("res/textures/rock_cement.png"));
R_TEXADD ("terrain4", R_TEXLOAD ("res/textures/asphalt_gravel.png"));
R_TEXADD ("tree0", R_TEXLOAD ("res/textures/tree.png"));
R_TEXADD ("grass0", R_TEXLOAD ("res/textures/grass0.png"));
}
unsigned int
Resources_load_program (const char *v_path, const char *f_path)
{
FILE *v_file = fopen (v_path, "r");
if (v_file == NULL)
{
WARN ("File `%s' does not exist.", v_path);
}
fseek (v_file, 0L, SEEK_END);
size_t v_len = ftell (v_file) + 1;
char *v_src = calloc (v_len, sizeof (char));
rewind (v_file);
INFO ("Read %zu bytes from vertex source.", fread (v_src, sizeof (char), v_len, v_file));
FILE *f_file = fopen (f_path, "r");
if (f_file == NULL)
{
WARN ("File `%s' does not exist.", f_path);
}
fseek (f_file, 0L, SEEK_END);
size_t f_len = ftell (f_file) + 1;
char *f_src = calloc (f_len, sizeof (char));
rewind (f_file);
INFO ("Read %zu bytes from fragment source.", fread (f_src, sizeof (char), f_len, f_file));
unsigned int program = program_create (v_src, f_src);
free (v_src);
free (f_src);
return program;
}
unsigned int
Resources_load_texture (const char *path)
{
SDL_Surface *surface = IMG_Load (path);
if (surface == NULL)
{
WARN ("Failed to load texture from path %s: %s", path, SDL_GetError ());
}
unsigned int texture = texture_create (surface->w, surface->h, surface->pixels);
return texture;
}
-24
View File
@@ -1,24 +0,0 @@
#pragma once
#include <SDL3_image/SDL_image.h>
#include <glib-2.0/glib.h>
#include "program.h"
#include "texture.h"
#define R_PRGADD(key, program) (g_hash_table_insert (resources.programs, key, GINT_TO_POINTER (program)))
#define R_TEXADD(key, texture) (g_hash_table_insert (resources.textures, key, GINT_TO_POINTER (texture)))
#define R_PRGLOAD(v_path, f_path) (Resources_load_program (v_path, f_path))
#define R_TEXLOAD(path) (Resources_load_texture (path))
#define R_PRGGET(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.programs, key)))
#define R_TEXGET(key) (GPOINTER_TO_INT (g_hash_table_lookup (resources.textures, key)))
typedef struct Resources {
GHashTable *programs;
GHashTable *textures;
} Resources;
unsigned int Resources_load_program (const char *v_path, const char *f_path);
unsigned int Resources_load_texture (const char *path);
void Resources_init ();
+28 -29
View File
@@ -1,57 +1,56 @@
#include "state.h"
GameState game_state;
extern vec3 camera_position;
extern GameFlags game_flags;
float delta_time;
static int last_time;
void
GameState_init (int ticks)
game_state_init (int ticks)
{
game_state.last_time = ticks;
game_state.camera = Camera_default ();
game_state.camera.position[2] = -1.0;
last_time = ticks;
}
void
GameState_tick (int ticks)
game_state_tick (int ticks)
{
/* Caluclate stuff per frame. */
game_state.delta_time = (ticks - game_state.last_time) / 1000.0;
game_state.last_time = ticks;
delta_time = (ticks - last_time) / 1000.0;
last_time = ticks;
if (game_flags.moving_forward)
if (flags_get ("moving_forward"))
{
vec3 dir, change, new_pos;
Camera_get_direction (&game_state.camera, dir);
glm_vec3_scale (dir, game_state.delta_time * 5, change);
glm_vec3_add (game_state.camera.position, change, new_pos);
glm_vec3_copy (new_pos, game_state.camera.position);
camera_get_direction (dir);
glm_vec3_scale (dir, delta_time * 5, change);
glm_vec3_add (camera_position, change, new_pos);
glm_vec3_copy (new_pos, camera_position);
}
if (game_flags.moving_backward)
if (flags_get ("moving_backward"))
{
vec3 dir, change, new_pos;
Camera_get_direction (&game_state.camera, dir);
glm_vec3_scale (dir, game_state.delta_time * 5, change);
glm_vec3_sub (game_state.camera.position, change, new_pos);
glm_vec3_copy (new_pos, game_state.camera.position);
camera_get_direction (dir);
glm_vec3_scale (dir, delta_time * 5, change);
glm_vec3_sub (camera_position, change, new_pos);
glm_vec3_copy (new_pos, camera_position);
}
if (game_flags.moving_right)
if (flags_get ("moving_right"))
{
vec3 right, change, new_pos;
Camera_get_right (&game_state.camera, right);
glm_vec3_scale (right, game_state.delta_time * 5, change);
glm_vec3_add (game_state.camera.position, change, new_pos);
glm_vec3_copy (new_pos, game_state.camera.position);
camera_get_right (right);
glm_vec3_scale (right, delta_time * 5, change);
glm_vec3_add (camera_position, change, new_pos);
glm_vec3_copy (new_pos, camera_position);
}
if (game_flags.moving_left)
if (flags_get ("moving_left"))
{
vec3 right, change, new_pos;
Camera_get_right (&game_state.camera, right);
glm_vec3_scale (right, game_state.delta_time * 5, change);
glm_vec3_sub (game_state.camera.position, change, new_pos);
glm_vec3_copy (new_pos, game_state.camera.position);
camera_get_right (right);
glm_vec3_scale (right, delta_time * 5, change);
glm_vec3_sub (camera_position, change, new_pos);
glm_vec3_copy (new_pos, camera_position);
}
}
+2 -10
View File
@@ -3,13 +3,5 @@
#include "camera.h"
#include "flags.h"
typedef struct GameState
{
int last_time;
float delta_time;
Camera camera;
} GameState;
void GameState_init ();
void GameState_tick ();
void game_state_init (int ticks);
void game_state_tick (int ticks);