From c05ab2d3ae9fa65b51b7d65b28182fe30f76e707 Mon Sep 17 00:00:00 2001 From: Emil Kosz Date: Fri, 6 Jun 2025 13:51:44 +0200 Subject: [PATCH] Super optimizing, gprof is no longer my friend --- game/Makefile | 6 +- game/cputest.sh | 2 +- game/res/textures/font.png | Bin 1845 -> 1850 bytes game/res/textures/font.xcf | Bin 36621 -> 36651 bytes game/shell.nix | 2 + game/src/chunk/chunkman.c | 110 +++++++++++++++++++++++------------- game/src/chunk/chunkman.h | 10 +++- game/src/entity/entity.h | 3 + game/src/entity/entman.c | 73 ++++++++++++------------ game/src/entity/entman.h | 4 +- game/src/entity/templates.c | 2 + game/src/graphics.c | 11 +++- game/src/graphics.h | 2 + game/src/main.c | 2 +- game/src/state.c | 18 +++--- game/src/ui/uielement.c | 6 +- game/src/ui/uielement.h | 2 +- game/src/ui/uiman.c | 17 +++++- 18 files changed, 166 insertions(+), 104 deletions(-) diff --git a/game/Makefile b/game/Makefile index b4d592c..4a9893c 100644 --- a/game/Makefile +++ b/game/Makefile @@ -5,8 +5,8 @@ SRC=src/main.c src/gl/program.c src/resources.c src/camera.c src/chunk/chunk.c \ src/ui/uiman.c OBJ=$(SRC:.c=.o) -CFLAGS=-g -pg -Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image cglm gl glib-2.0` -LDFLAGS=-g -pg -lm `pkg-config --libs sdl3 sdl3-image cglm gl glib-2.0` +CFLAGS=-g -Werror -Wextra -Wall `pkg-config --cflags sdl3 sdl3-image cglm gl glib-2.0` +LDFLAGS=-g -lm `pkg-config --libs sdl3 sdl3-image cglm gl glib-2.0` TARGET=wschod CC=gcc LD=gcc @@ -22,4 +22,4 @@ $(TARGET): $(OBJ) $(CC) -c $^ -o $@ $(CFLAGS) clean: - $(RM) gmon.out $(TARGET) $(OBJ) + $(RM) perf.data* $(TARGET) $(OBJ) diff --git a/game/cputest.sh b/game/cputest.sh index 0eb86ac..659c6e1 100755 --- a/game/cputest.sh +++ b/game/cputest.sh @@ -1,2 +1,2 @@ #!/usr/bin/env bash -cpulimit -l 20 -- ./wschod +cpulimit -l $1 -- ./wschod diff --git a/game/res/textures/font.png b/game/res/textures/font.png index 538cdf5dc2533941d872dc1cf6b53f1d8ad38511..6f413497e0e34f79a0e5f872155d055f62dceee4 100644 GIT binary patch delta 1761 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 diff --git a/game/res/textures/font.xcf b/game/res/textures/font.xcf index 32430c67ffcab5b310a65f451d9f28b8f9ba3cef..675334b6f6bd3c1feb46988e95b468b21e1e739a 100644 GIT binary patch delta 563 zcmeC3$FzDL6K{HEZh=BYa+*S!fuZR{UPbN-1_p)+j0_A64U7}@I~gZz+?mY5Y0m%# z-ODzsa`G`U`b{?BQsyiIi!pT1nw-ETF1ZN8)4c+ry(d8E-1(a)a4lwIX8O-P*+5#I zm4$)vKiA}Ss*21^|G6fwk(Op%r4_@) z%*w#L`J@RiCo1Em+g2u3RtCoZB4AS)|8p`h{ugFo`Y*)5^dIC&5FaEbH2J-W>EwhK&mj8^Ka%M?Q)-BN6 ze4;IaaZ(4{E`=AdQ1R$YMJu@ delta 518 zcmZ2IkEwSa6K{HEZh=BYa+*S!fuZ3diI$y=O&bpruK=&pg#V6uUMfdPaW7#O%_fJGQ|cR^_HA_$$^xOo=WVz$YGf?BLB z4FCUgPd=ck$o&65&*TY$(u^XTHwbR$Bv(>~d9s4$Q)b5hypuV!beaGE=bdb!rO3+8 z@c%#Gw=%iPFfjgSVPO2v$-wwu7>t?F_>BMA z7#RPvGcf)aW%&P}mx1v=Gnmi(pOJwXEXKE)(W{SxlbM0#KO+Onf2Pfh(Fu6DiHw_1 zr+Be*$}uqiX9D5Payhf4IRF1=X88S|f#Lt=gKf2ptRU|H$)^fsHz#zoFf%ete%ig8 uaq{GaJ<68bAz|Ck2%*6wC>}tVfq|jtIaq|D=R1V%Wrxz@oB#IcF#!OFWR24R diff --git a/game/shell.nix b/game/shell.nix index cb16345..a9dd998 100644 --- a/game/shell.nix +++ b/game/shell.nix @@ -16,5 +16,7 @@ pkgs.mkShellNoCC { pkg-config valgrind gdb + cpulimit + linuxKernel.packages.linux_6_12.perf ]; } diff --git a/game/src/chunk/chunkman.c b/game/src/chunk/chunkman.c index 20e8de6..a67fe09 100644 --- a/game/src/chunk/chunkman.c +++ b/game/src/chunk/chunkman.c @@ -1,8 +1,5 @@ #include "chunkman.h" -/* TODO: perhaps render the chunks in a circle, not a square, around - the player? */ - int n_frame_chunks; static GHashTable *chunks; @@ -24,17 +21,14 @@ chunkman_ivec2_hash (gconstpointer key) gboolean chunkman_ivec2_equal (gconstpointer a, gconstpointer b) { - /* Much faster than comparing the integer values. */ return memcmp (a, b, sizeof (int) * 2) == 0; } ivec2 * chunkman_make_key(int x, int z) { - ivec2 *key = malloc(sizeof(ivec2)); - (*key)[0] = x; - (*key)[1] = z; - return key; + ivec2 key = { x, z }; + return g_memdup2 (&key, sizeof (ivec2)); } void @@ -107,43 +101,63 @@ chunkman_init () chunk_meshes = g_hash_table_new_full (chunkman_ivec2_hash, chunkman_ivec2_equal, free, (GDestroyNotify) Chunk_free); } -/* TODO: Update the chunks only if the player has moved into another - chunk, to save frame time. */ - void -chunkman_update (vec3 position) +chunkman_tick (vec3 position) { int cx, cz; chunkman_world_to_chunk (position[0], position[2], &cx, &cz); + unsigned int frame_time = SDL_GetTicks (); + for (int z = cz - RENDER_DISTANCE - 1; z <= cz + RENDER_DISTANCE + 1; ++z) { for (int x = cx - RENDER_DISTANCE - 1; x <= cx + RENDER_DISTANCE + 1; ++x) - { - if (chunkman_get_Chunk_at (x, z) == NULL) - { - chunkman_generate_Chunk_at (x, z); - } - } + { + if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= (RENDER_DISTANCE + 1) * (RENDER_DISTANCE + 1)) + { + if (chunkman_get_Chunk_at (x, z) == NULL) + { + chunkman_generate_Chunk_at (x, z); + } + + if (SDL_GetTicks () - frame_time > FRAME_BUDGET) + { + return; + } + } + } } for (int z = cz - RENDER_DISTANCE; z <= cz + RENDER_DISTANCE; ++z) { for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x) - { - if (chunkman_get_ChunkMesh_at (x, z) == NULL) - { - chunkman_generate_ChunkMesh_at (x, z); - } - } + { + if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= RENDER_SQR) + { + if (chunkman_get_ChunkMesh_at (x, z) == NULL) + { + chunkman_generate_ChunkMesh_at (x, z); + } + + if (SDL_GetTicks () - frame_time > FRAME_BUDGET) + { + return; + } + } + } } } void -chunkman_render (vec3 position) +chunkman_render (vec3 position, vec4 planes[6]) { +#if !FRUSTUM_CULL + UNUSED (planes); +#endif + int cx = 0, cz = 0; chunkman_world_to_chunk (position[0], position[2], &cx, &cz); + program_use (RESPRG ("chunk")); glActiveTexture (GL_TEXTURE0); @@ -163,18 +177,35 @@ chunkman_render (vec3 position) { for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x) { - ChunkMesh *mesh = chunkman_get_ChunkMesh_at (x, z); - if (mesh != NULL) + if ((x - cx) * (x - cx) + (z - cz) * (z - cz) <= RENDER_SQR) { - if (!bound) + ChunkMesh *mesh = chunkman_get_ChunkMesh_at (x, z); + if (mesh != NULL) { - ChunkMesh_bind (mesh); - bound = true; - } + /* This, compared to the entity AABB, seems to work + completely fine. */ +#if FRUSTUM_CULL + vec3 aabb[2] = { + { x * CHUNK_DIM, 0.0, z * CHUNK_DIM }, + { (x + 1) * CHUNK_DIM, TERRAIN_HEIGHT, (z + 1) * CHUNK_DIM } + }; + + if (!glm_aabb_frustum (aabb, planes)) + { + continue; + } +#endif + + if (!bound) + { + ChunkMesh_bind (mesh); + bound = true; + } - program_set_vec3_ind (RESPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM); - ChunkMesh_render (mesh); - n_frame_chunks++; + program_set_vec3_ind (RESPRG ("chunk"), "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM); + ChunkMesh_render (mesh); + n_frame_chunks++; + } } } } @@ -185,7 +216,8 @@ chunkman_render (vec3 position) Chunk * chunkman_get_Chunk_at (int x, int z) { - return (Chunk *) g_hash_table_lookup (chunks, (ivec2) { x, z }); + ivec2 key = { x, z }; + return (Chunk *) g_hash_table_lookup (chunks, &key); } void @@ -205,12 +237,13 @@ chunkman_generate_Chunk_at (int cx, int cz) { for (int x = 0; x < CHUNK_DIM; ++x) { + chunk->heightmap[INDEX (x, z)] = (glm_perlin_vec2 - ((vec2) { (x + xoffset + 0.5) / 10.0, (z + zoffset + 0.5) / 10.0 }) + 0.6) * 2; + ((vec2) { (x + xoffset + 0.333) / 10.0, (z + zoffset + 0.333) / 10.0 }) + 0.6) * 2; chunk->materialmap[INDEX (x, z)] = (int) - (glm_perlin_vec2 ((vec2) { (x + xoffset + 0.5) / 20.0, (z + zoffset + 0.5) / 20.0 }) + 0.6 * 5) % 5; + (glm_perlin_vec2 ((vec2) { (x + xoffset + 0.333) / 20.0, (z + zoffset + 0.333) / 20.0 }) + 0.6 * 5) % 5; if (rand() % 100 < 2) { @@ -250,7 +283,8 @@ chunkman_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **n ChunkMesh * chunkman_get_ChunkMesh_at (int x, int z) { - return (ChunkMesh *) g_hash_table_lookup (chunk_meshes, (ivec2) { x, z }); + ivec2 key = { x, z }; + return (ChunkMesh *) g_hash_table_lookup (chunk_meshes, key); } void diff --git a/game/src/chunk/chunkman.h b/game/src/chunk/chunkman.h index 1fcb6c3..491ef16 100644 --- a/game/src/chunk/chunkman.h +++ b/game/src/chunk/chunkman.h @@ -8,12 +8,16 @@ #include "../gl/program.h" #include "../entity/entman.h" #include "../entity/templates.h" +#include "../graphics.h" -#define RENDER_DISTANCE 3 +#define RENDER_DISTANCE 5 +#define RENDER_SQR (RENDER_DISTANCE*RENDER_DISTANCE) +#define TERRAIN_HEIGHT 8.0 +#define FRAME_BUDGET 3 void chunkman_init (); -void chunkman_update (vec3 position); -void chunkman_render (vec3 position); +void chunkman_tick (vec3 position); +void chunkman_render (vec3 position, vec4 planes[6]); float chunkman_get_height_at (float x, float z); diff --git a/game/src/entity/entity.h b/game/src/entity/entity.h index f77e5b9..b9f7d8e 100644 --- a/game/src/entity/entity.h +++ b/game/src/entity/entity.h @@ -12,6 +12,9 @@ typedef struct Entity enum { RENDER_NORMAL, RENDER_BILLBOARD_Y, RENDER_BILLBOARD } render_type; bool visible; bool dont_cull; + float cull_distance; /* 1 means as far as the terrain goes, + less than 1, for example 0.5, means + half as far as the terrain goes. */ bool wavy; void *userdata; diff --git a/game/src/entity/entman.c b/game/src/entity/entman.c index 7b94851..301caec 100644 --- a/game/src/entity/entman.c +++ b/game/src/entity/entman.c @@ -1,6 +1,8 @@ #include "entman.h" -/* TODO: Put uniforms into vertex attributes for pseudoinstancing. */ +/* TODO: What COULD be done, but not necessarily SHOULD be done, is to + generate a mesh for say, 16 entities at once, then, the number of + drawcalls would drop substantially. */ /* TODO: Instead of having a huge far plane, render the clouds seperately somehow. */ @@ -9,7 +11,9 @@ extern vec3 camera_position; Entity *player_entity, *sky_entity; int n_frame_ents; -static GSequence *entities; +/* 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 unsigned int last_program = -1; static unsigned int last_type = -1; @@ -24,7 +28,7 @@ character_on_tick (Entity *entity) void entman_init () { - entities = g_sequence_new (NULL); + entities = g_array_new (false, false, sizeof (Entity *)); mesh_quad1 = SimpleMesh_make_quad1 (); mesh_quad2 = SimpleMesh_make_quad2 (); mesh_quad_x = SimpleMesh_make_quad_x (); @@ -57,28 +61,22 @@ entman_init () } void -entman_tick_internal (gpointer data, gpointer userdata) +entman_tick () { - UNUSED (userdata); - Entity *entity = data; - - if (entity->on_tick) + for (guint i = 0; i < entities->len; ++i) { - entity->on_tick (entity); + Entity *e = g_array_index (entities, Entity*, i); + + if (e->on_tick) + { + e->on_tick (e); + } } } void -entman_tick () +entman_render_entity (Entity *entity, void *userdata) { - g_sequence_foreach (entities, entman_tick_internal, NULL); -} - -void -entman_render_internal (gpointer data, gpointer userdata) -{ - Entity *entity = data; - struct { mat4 *view; #ifdef FRUSTUM_CULL @@ -91,8 +89,8 @@ entman_render_internal (gpointer data, gpointer userdata) return; } - if (glm_vec3_distance (camera_position, entity->position) > ENTITY_RENDER_DISTANCE - && !entity->dont_cull) + if (glm_vec3_distance (camera_position, entity->position) + > entity->cull_distance * RENDER_DISTANCE * CHUNK_DIM && !entity->dont_cull) { return; } @@ -203,36 +201,41 @@ entman_render_internal (gpointer data, gpointer userdata) } void -entman_render (mat4 *view, mat4 *proj) +entman_render (mat4 *view, vec4 planes[6]) { +#if !FRUSTUM_CULL + UNUSED (planes); +#endif + last_program = -1; last_texture = -1; last_type = -1; n_frame_ents = 0; - -#ifdef FRUSTUM_CULL - vec4 planes[6]; - mat4 view_proj; - glm_mat4_mul (*proj, *view, view_proj); - glm_frustum_planes (view_proj, planes); -#endif struct { mat4 *view; -#ifdef FRUSTUM_CULL +#if FRUSTUM_CULL vec4 *frustum_planes; #endif - } data = { view, planes }; - - g_sequence_foreach (entities, entman_render_internal, &data); + } data = { + view +#if FRUSTUM_CULL + ,planes +#endif + }; + + for (guint i = 0; i < entities->len; ++i) + { + Entity *e = g_array_index (entities, Entity*, i); + entman_render_entity (e, &data); + } } static inline int -entman_compare (gconstpointer a, gconstpointer b, gpointer userdata) +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. */ { - UNUSED (userdata); const Entity *entity1 = a; const Entity *entity2 = b; @@ -242,5 +245,5 @@ entman_compare (gconstpointer a, gconstpointer b, gpointer userdata) void entman_add_entity (Entity *entity) { - g_sequence_insert_sorted (entities, entity, entman_compare, NULL); + g_array_append_val (entities, entity); } diff --git a/game/src/entity/entman.h b/game/src/entity/entman.h index 2bd1d98..d04e9c7 100644 --- a/game/src/entity/entman.h +++ b/game/src/entity/entman.h @@ -9,9 +9,7 @@ #include "../resources.h" #include "../state.h" #include "../chunk/chunkman.h" - -#define ENTITY_RENDER_DISTANCE (RENDER_DISTANCE*CHUNK_DIM) -#define FRUSTUM_CULL 1 +#include "../graphics.h" #define ENTADD(entity) (entman_add_entity (entity)) diff --git a/game/src/entity/templates.c b/game/src/entity/templates.c index ceec908..c23fc15 100644 --- a/game/src/entity/templates.c +++ b/game/src/entity/templates.c @@ -23,6 +23,7 @@ ent_templates_init () *tree = (Entity) { .mesh_type = MESH_QUAD_X, .visible = true, + .cull_distance = 0.7, .wavy = true, .origin = ORIGIN_BOTTOM, .position = { 0.0 }, @@ -39,6 +40,7 @@ ent_templates_init () .mesh_type = MESH_QUAD1, .render_type = RENDER_BILLBOARD_Y, .visible = true, + .cull_distance = 0.2, .wavy = true, .origin = ORIGIN_BOTTOM, .position = { 0.0 }, diff --git a/game/src/graphics.c b/game/src/graphics.c index 1a06827..a1eedd3 100644 --- a/game/src/graphics.c +++ b/game/src/graphics.c @@ -69,8 +69,15 @@ graphics_render () resources_programs_set_mat4 ("view", &view); resources_programs_set_float ("time", last_time); - chunkman_render (camera_position); - entman_render (view, projection); + vec4 planes[6]; +#if FRUSTUM_CULL + mat4 view_proj; + glm_mat4_mul (projection, view, view_proj); + glm_frustum_planes (view_proj, planes); +#endif + + chunkman_render (camera_position, planes); + entman_render (view, planes); /* We don't care about blending elsewhere for now. */ glEnable (GL_BLEND); diff --git a/game/src/graphics.h b/game/src/graphics.h index 40c61b2..a7443c1 100644 --- a/game/src/graphics.h +++ b/game/src/graphics.h @@ -10,6 +10,8 @@ #include "resources.h" #include "util.h" +#define FRUSTUM_CULL 1 + void graphics_init (); void graphics_render (); void graphics_free (); diff --git a/game/src/main.c b/game/src/main.c index e4aecfb..bef1ab0 100644 --- a/game/src/main.c +++ b/game/src/main.c @@ -54,7 +54,7 @@ SDL_AppIterate (void *appstate) game_state_tick (SDL_GetTicks ()); entman_tick (); - chunkman_update (camera_position); + chunkman_tick (camera_position); graphics_render (); return SDL_APP_CONTINUE; diff --git a/game/src/state.c b/game/src/state.c index dc49185..f1f0437 100644 --- a/game/src/state.c +++ b/game/src/state.c @@ -3,7 +3,7 @@ extern vec3 camera_position; extern vec3 camera_rotation; extern Entity *player_entity, *sky_entity; -extern UIElement *player_pos, *n_ents, *n_chunks; +extern UIElement *player_pos, *n_ents, *n_chunks, *frame_time; extern int n_frame_ents, n_frame_chunks; float delta_time; @@ -33,16 +33,12 @@ game_state_tick (int ticks) sky_entity->position[0] = camera_position[0]; sky_entity->position[2] = camera_position[2]; - /* Put the player position into the UI. */ - player_pos->text = malloc (sizeof (char) * 32); - snprintf (player_pos->text, 32, "position X:%2.1f Y:%2.1f Z:%2.1f", player_entity->position[0], - player_entity->position[1], player_entity->position[2]); - /* Put the amount of entities rendered into the UI. */ - n_ents->text = malloc (sizeof (char) * 32); - snprintf (n_ents->text, 32, "entities rendered: %d", n_frame_ents); - /* Put the amount of chunks rendered into the UI. */ - n_chunks->text = malloc (sizeof (char) * 32); - snprintf (n_chunks->text, 32, "chunks rendered: %d", n_frame_chunks); + g_string_printf (player_pos->text, "Position (X:%2.1f, Y:%2.1f, Z:%2.1f)", + player_entity->position[0], player_entity->position[1], + player_entity->position[2]); + g_string_printf (n_ents->text, "Entities rendered: %d", n_frame_ents); + g_string_printf (n_chunks->text, "Chunks rendered: %d", n_frame_chunks); + g_string_printf (frame_time->text, "Frame time: %.3f", delta_time); if (flags_get ("moving_forward")) { diff --git a/game/src/ui/uielement.c b/game/src/ui/uielement.c index 18ce98b..24f4623 100644 --- a/game/src/ui/uielement.c +++ b/game/src/ui/uielement.c @@ -45,8 +45,6 @@ UIElement_render (UIElement *element) glm_scale (model, element->scale); program_set_mat4 (RESPRG ("uielement"), "model", model); - /* TODO: rename this function to vec3_individual or - something. */ program_set_vec3 (RESPRG ("uielement"), "color", element->background_color); SimpleMesh_render (&quad); @@ -56,7 +54,7 @@ UIElement_render (UIElement *element) glBindTexture (GL_TEXTURE_2D, RESTEX ("font0")); program_set_vec3 (RESPRG ("uielement"), "color", element->text_color); - for (size_t i = 0; i < strlen (element->text); ++i) + for (size_t i = 0; i < element->text->len; ++i) { vec3 pos; float x = -element->scale[0] + (element->scale[1] / 2) + (element->scale[1] * i); @@ -67,7 +65,7 @@ UIElement_render (UIElement *element) glm_scale (model, (vec3) { element->scale[1] / 2, element->scale[1], 1.0 }); program_set_mat4 (RESPRG ("uielement"), "model", model); - program_set_float (RESPRG ("uielement"), "character", element->text[i]); + program_set_float (RESPRG ("uielement"), "character", element->text->str[i]); SimpleMesh_render (&quad); } } diff --git a/game/src/ui/uielement.h b/game/src/ui/uielement.h index 9d20106..6f8efcf 100644 --- a/game/src/ui/uielement.h +++ b/game/src/ui/uielement.h @@ -26,7 +26,7 @@ typedef struct UIElement vec3 position; vec3 scale; - char *text; /* Maybe switch to GString? */ + GString *text; } UIElement; void ui_element_mesh_init (); diff --git a/game/src/ui/uiman.c b/game/src/ui/uiman.c index ea839d3..e64e2a0 100644 --- a/game/src/ui/uiman.c +++ b/game/src/ui/uiman.c @@ -1,11 +1,11 @@ #include "uiman.h" -UIElement *player_pos, *n_ents, *n_chunks; +UIElement *player_pos, *n_ents, *n_chunks, *frame_time; static UIElement ui_root; #define UINEWROOT() ((UIElement) { .parent = NULL, .children = g_sequence_new (NULL), .visible = false }) -#define UINEW(pare) ((UIElement) { .parent = pare, .text_color = { 1.0, 1.0, 1.0 }, .visible = true }) +#define UINEW(pare) ((UIElement) { .parent = pare, .text_color = { 1.0, 1.0, 1.0 }, .visible = true, .text = g_string_new (NULL) }) #define UIADD(pare, child) (UIElement_add_child (pare, child)) void @@ -32,6 +32,19 @@ uiman_init () glm_vec3_copy ((vec3) { -0.65, 0.70, 0.0 }, n_chunks->position); glm_vec3_copy ((vec3) { 0.3, 0.03, 1.0 }, n_chunks->scale); UIADD (&ui_root, n_chunks); + + frame_time = malloc (sizeof (UIElement)); + *frame_time = UINEW (&ui_root); + glm_vec3_copy ((vec3) { -0.65, 0.59, 0.0 }, frame_time->position); + glm_vec3_copy ((vec3) { 0.3, 0.03, 1.0 }, frame_time->scale); + UIADD (&ui_root, frame_time); + +} + +void +uiman_tick () +{ + } void