polyadvent

A game engine from scratch in C
git clone git://jb55.com/polyadvent
Log | Files | Refs | README

commit c9cfe15a1bb2f8531901768fb943578b104853c9
parent 4059ffe5baaa19c32f0ef6fea644a6cde673affd
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 31 Oct 2018 03:16:13 -0700

more work on cameras an entities

Diffstat:
MMakefile | 2++
Metc/shaders/terrain.glsl | 1+
Msrc/common.h | 6+++---
Msrc/entity.c | 24++++++++++++++++++++++++
Msrc/entity.h | 13+++++++++++++
Msrc/event.c | 20++++++++++++++++++++
Msrc/game.c | 10++++------
Msrc/game.h | 3+++
Asrc/hires.c | 10++++++++++
Asrc/hires.h | 7+++++++
Msrc/input.c | 11+++++++++++
Msrc/input.h | 12++++++++++--
Msrc/main.c | 16++++++++++++----
Asrc/orbit.c | 25+++++++++++++++++++++++++
Asrc/orbit.h | 18++++++++++++++++++
Asrc/physics.c | 3+++
Msrc/update.c | 52+++++++++++++++++++++++++++++-----------------------
Msrc/update.h | 2+-
Msrc/util.h | 5+++++
19 files changed, 201 insertions(+), 39 deletions(-)

diff --git a/Makefile b/Makefile @@ -28,6 +28,7 @@ OBJS += $(SRC)/mat4.o OBJS += $(SRC)/mat_util.o OBJS += $(SRC)/model.o OBJS += $(SRC)/node.o +OBJS += $(SRC)/orbit.o OBJS += $(SRC)/perlin.o OBJS += $(SRC)/ply.o OBJS += $(SRC)/poisson.o @@ -40,6 +41,7 @@ OBJS += $(SRC)/uniform.o OBJS += $(SRC)/update.o OBJS += $(SRC)/util.o OBJS += $(SRC)/vec3.o +OBJS += $(SRC)/hires.o SRCS=$(OBJS:.o=.c) diff --git a/etc/shaders/terrain.glsl b/etc/shaders/terrain.glsl @@ -31,6 +31,7 @@ const vec4 land[nlands] = vec4[]( vec4(1.0, 1.0, 1.0, 380.0) // 5 - snow ); + void main() { vec3 color = land[0].xyz; diff --git a/src/common.h b/src/common.h @@ -10,9 +10,6 @@ #define SLAB(f) "etc/slab/" f #define RESOURCE(f) "etc/shaders/" f -#define PI 3.14159265f -#define TAU 6.2831853f - typedef unsigned char u8; typedef signed char s8; @@ -22,6 +19,9 @@ typedef signed short s16; typedef unsigned int u32; typedef signed int s32; +typedef unsigned long long u64; +typedef signed long long s64; + struct point { double x, y; }; diff --git a/src/entity.c b/src/entity.c @@ -2,9 +2,33 @@ #include "entity.h" #include "node.h" #include "model.h" +#include <assert.h> +#define DEF_NUM_ENTITIES 1024 + +struct entity_id { + u32 index; + u32 generation; +}; void init_entity(struct entity *ent) { node_init(&ent->node); ent->casts_shadows = 0; } + +struct entity *get_entity(struct entity_system *system, struct entity_id id) { + assert(id.generation <= system->generation); + if (id.generation < system->generation) + return NULL; + return &system->entities[id.index]; +} + +void init_entity_system(struct entity_system *system) { + system->generation = 0; + system->entities = calloc(DEF_NUM_ENTITIES, sizeof(*system->entities)); + + system->handles = + calloc(DEF_NUM_ENTITIES, sizeof(*system->handles)); +} + + diff --git a/src/entity.h b/src/entity.h @@ -8,10 +8,23 @@ struct entity { struct node node; struct model model; + float velocity[3]; + float accel[3]; int casts_shadows; }; +struct entity_id; + +struct entity_system { + struct entity *entities; + struct entity_id *handles; + int entity_count; + u32 generation; +}; + void init_entity(struct entity *); +void init_entity_system(struct entity_system *); +struct entity *get_entity(struct entity_system *, struct entity_id); #endif /* ENTITY_H */ diff --git a/src/event.c b/src/event.c @@ -6,6 +6,10 @@ void process_events(struct game *game, float *camera) { SDL_Event event; + int mdx = 0; + int mdy = 0; + + input_reset(&game->input); while (SDL_PollEvent(&event)) { switch (event.type) { @@ -13,6 +17,18 @@ void process_events(struct game *game, float *camera) { case SDL_KEYUP: handle_key(&game->input, event.key); break; + case SDL_MOUSEMOTION: + if (event.button.button) { + if (event.button.button <= MOUSE_BUTTONS) + game->input.mbuttons[event.button.button-1] = 1; + game->input.is_dragging = 1; + mdx += event.motion.xrel; + mdy += event.motion.yrel; + /* printf("drag... %d %d\n", event.motion.xrel, event.motion.yrel); */ + game->input.mx = event.motion.x; + game->input.my = event.motion.y; + } + break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: @@ -24,5 +40,9 @@ void process_events(struct game *game, float *camera) { SDL_Quit(); exit(0); } + } + + game->input.mdx = mdx; + game->input.mdy = mdy; } diff --git a/src/game.c b/src/game.c @@ -104,6 +104,10 @@ void game_init(struct game *game, int width, int height) { game->test_resources.fog_on = 1; game->test_resources.diffuse_on = 0; + res->orbit_camera.azimuth = RAD(90.0); + res->orbit_camera.inclination = RAD(180.0); + res->orbit_camera.radius = RAD(180.0); + node_init(root); node_init(camera); node_init(sun_camera); @@ -125,19 +129,13 @@ void game_init(struct game *game, int width, int height) { node_attach(&player->node, root); node_attach(camera, &player->node); - /* node_attach(sun_camera, root); */ quat_axis_angle(V3(1,0,0), -45, camera->orientation); - /* quat_axis_angle(V3(1,0,0), -90, camera->orientation); */ - /* node_rotate(sun_camera, V3(-7.5, 0, 0)); */ - /* node_translate(sun_camera, V3(width/shadowmap_scale, 2000, 0)); */ node_translate(&player->node, V3(terrain->size/2.,terrain->size/2.,0.0)); - /* vec3_scale(player->node.scale, 10.0, player->node.scale); */ node_rotate(camera, V3(100, 0, 0)); node_translate(camera, V3(0,-40,20)); - /* node_recalc(camera); */ terrain->entity.node.pos[2] = 20.0; diff --git a/src/game.h b/src/game.h @@ -11,6 +11,7 @@ #include "terrain.h" #include "ui.h" #include "fbo.h" +#include "orbit.h" #define PLAYER_HEIGHT 1.73 @@ -55,6 +56,7 @@ struct resources { struct node root; struct entity player; + struct orbit orbit_camera; struct node camera; struct node sun_camera; @@ -72,6 +74,7 @@ struct resources { struct game { int counter; int seed; + float dt; struct ui ui; struct resources test_resources; struct input input; diff --git a/src/hires.c b/src/hires.c @@ -0,0 +1,10 @@ + +#include <time.h> +#include "common.h" +#include <SDL2/SDL.h> + +double hires_time_in_seconds() { + double ticks_per_sec = (double)SDL_GetPerformanceFrequency(); + double ticks = (double)SDL_GetPerformanceCounter(); + return ticks / ticks_per_sec; +} diff --git a/src/hires.h b/src/hires.h @@ -0,0 +1,7 @@ + +#ifndef HIRES_H +#define HIRES_H + +double hires_time_in_seconds(); + +#endif /* HIRES_H */ diff --git a/src/input.c b/src/input.c @@ -6,9 +6,20 @@ void input_init(struct input *input) { /* memset(input->keys, 0, sizeof(input->keys[0]) * ARRAY_SIZE(input->keys)); */ input->keystates = SDL_GetKeyboardState(NULL); + input->is_dragging = 0; + input->mdx = 0; + input->mdy = 0; assert(input->keystates); } void handle_key(struct input *input, SDL_KeyboardEvent key) { input->modifiers = SDL_GetModState(); } + + +void input_reset(struct input *input) { + input->is_dragging = 0; + + for (int i = 0; i < MOUSE_BUTTONS; ++i) + input->mbuttons[i] = 0; +} diff --git a/src/input.h b/src/input.h @@ -12,14 +12,22 @@ /* KEY_UP */ /* }; */ +#define MOUSE_BUTTONS 5 + struct input { /* enum key_state keys[0x7F-0x1F]; */ - u8 const *keystates; - SDL_Keymod modifiers; + u8 const *keystates; + SDL_Keymod modifiers; + int mdx, mdy; + int mx, my; + int is_dragging; + int mbuttons[MOUSE_BUTTONS]; }; void input_init(struct input *input); +void input_reset(struct input *input); + void handle_key(struct input *input, SDL_KeyboardEvent ke); #endif /* POLYADVENT_INPUT_H */ diff --git a/src/main.c b/src/main.c @@ -18,6 +18,7 @@ #include "uniform.h" #include "ply.h" #include "fbo.h" +#include "hires.h" int main(void) @@ -42,7 +43,7 @@ int main(void) game_init(&game, width, height); check_gl(); - u32 last = SDL_GetTicks(); + double last = hires_time_in_seconds(); static float depth_mvp[MAT4_ELEMS]; mat4_id(depth_mvp); @@ -64,10 +65,17 @@ int main(void) while (1) { process_events(&game, game.test_resources.proj_persp); - u32 ticks = SDL_GetTicks(); - update(&game, ticks-last); + double new_time = hires_time_in_seconds(); + double frame_time = new_time - last; + game.dt = frame_time; + update(&game); - last = ticks; + /* while (accumulator >= dt) { */ + /* t += dt; */ + /* accumulator -= dt; */ + /* } */ + + last = new_time; GLuint texture = game.test_resources.shadow_buffer.attachments[0]; struct fbo *fbo = &game.test_resources.shadow_buffer; diff --git a/src/orbit.c b/src/orbit.c @@ -0,0 +1,25 @@ + +#include "orbit.h" +#include "node.h" +#include <math.h> + +void orbit_to_quat(struct orbit *orbit, float *quat) +{ + float phi = orbit->azimuth; + float theta = orbit->inclination; + + // vector + quat[0] = cos(phi/2.0)*cos(theta/2.0); // scalar quaternion components + quat[1] = -sin(phi/2.0)*sin(theta/2.0); // x quaternion components + quat[2] = cos(phi/2.0)*sin(theta/2.0); // y quaternion components + quat[3] = sin(phi/2.0)*cos(theta/2.0); // z quaternion components +} + +/* static void orbit_update_node(struct node *node) { */ +/* } */ + +void orbit_to_node(struct orbit *orbit, struct node *node) { + orbit_to_quat(orbit, node->orientation); + node_mark_for_recalc(node); +} + diff --git a/src/orbit.h b/src/orbit.h @@ -0,0 +1,18 @@ + +#ifndef ORBIT_H +#define ORBIT_H + +struct node; + +struct orbit { + float radius; + float inclination; + float azimuth; +}; + + +void orbit_to_node(struct orbit *orbit, struct node *node); +void orbit_to_quat(struct orbit *, float *a); + + +#endif /* ORBIT_H */ diff --git a/src/physics.c b/src/physics.c @@ -0,0 +1,3 @@ + +void simulate(struct entity_system *entity_system) { +} diff --git a/src/update.c b/src/update.c @@ -136,7 +136,7 @@ void update_terrain(struct game *game) { /* struct point *samples = */ /* uniform_samples(n_samples, game->terrain.size); */ - static const double pdist = 42.0; + static const double pdist = 24.0; struct point *samples = poisson_disk_samples(pdist, game->terrain.size, 30, &n_samples); @@ -153,22 +153,21 @@ void update_terrain(struct game *game) { terrain_create(&game->terrain); } -static void player_terrain_collision(struct game *game) { - struct node *player = &game->test_resources.player.node; +static void player_terrain_collision(struct terrain *terrain, struct entity *player) { // player movement static vec3 last_pos[3] = {0}; - if (!vec3_eq(player->pos, last_pos, 0.0001)) { - float player_z = player->pos[2]; + if (!vec3_eq(player->node.pos, last_pos, 0.0001)) { + float player_z = player->node.pos[2]; float terrain_z = - game->terrain.fn(&game->terrain, player->pos[0], player->pos[1]) + 5.0; + terrain->fn(terrain, player->node.pos[0], player->node.pos[1]) + 5.0; float inset = min(0.0, player_z - terrain_z); if (inset <= 0) - node_translate(player, V3(0.0, 0.0, -inset)); + node_translate(&player->node, V3(0.0, 0.0, -inset)); } } @@ -177,13 +176,12 @@ static void player_movement(struct game *game) { struct resources *res = &game->test_resources; movement(game, &res->player.node, 2.0); - node_recalc(&res->camera); - vec3 *camera_world = node_world(&res->camera); - float cam_terrain_z = - game->terrain.fn(&game->terrain, camera_world[0], camera_world[1]); + /* vec3 *camera_world = node_world(&res->camera); */ + /* float cam_terrain_z = */ + /* game->terrain.fn(&game->terrain, camera_world[0], camera_world[1]); */ - if (camera_world[2] < cam_terrain_z) - camera_world[2] = cam_terrain_z + 20.0; + /* if (camera_world[2] < cam_terrain_z) */ + /* camera_world[2] = cam_terrain_z + 20.0; */ } @@ -241,7 +239,7 @@ void resize_fbos(struct game *game, int width, int height) { // TODO: match based on some real concept of time static void day_night_cycle(float time, struct resources *res) { - float val = time * 50.0; + float val = time; float intensity = vec3_dot(res->light_dir, V3(0.0, 0.0, 1.0)); intensity = clamp(intensity, 0.0, 0.8); float light_pos[3]; @@ -265,8 +263,8 @@ static void day_night_cycle(float time, struct resources *res) { /* vec3_normalize(res->light_intensity, res->light_intensity); */ res->light_dir[0] = 0.0; - res->light_dir[1] = -sin(val); - res->light_dir[2] = -cos(val); + res->light_dir[1] = sin(val); + res->light_dir[2] = cos(val) + 1.0; vec3_normalize(res->light_dir, res->light_dir); @@ -278,19 +276,26 @@ static void day_night_cycle(float time, struct resources *res) { look_at(light_pos, res->player.node.pos, V3(0, 0, 1.0), res->sun_camera.mat); } -void gravity(struct game *game) { +static void gravity(struct game *game) { struct entity *player = &game->test_resources.player; node_translate(&player->node, V3(0.0, 0.0, -1.0)); } -void update (struct game *game, u32 dt) { - static double last_ox, last_oy, last_oz; +static void player_update(struct game *game, struct entity *player) { + struct orbit *orbit_camera = &game->test_resources.orbit_camera; + /* orbit_camera->radius += game->dt * 4.0; */ + /* orbit_camera->inclination += game->dt * 2.0; */ + /* orbit_camera->azimuth += game->dt * 2.0; */ + /* orbit_to_node(orbit_camera, &game->test_resources.camera); */ + + player_terrain_collision(&game->terrain, player); +} + +void update (struct game *game) { static int toggle_fog = 0; - static float n = 1.0; static int first = 1; struct resources *res = &game->test_resources; - struct perlin_settings *ts = &game->terrain.settings; struct node *tnode = &game->terrain.entity.node; struct node *root = &game->test_resources.root; float *time = &res->time; @@ -303,6 +308,8 @@ void update (struct game *game, u32 dt) { first = 0; } + player_update(game, &res->player); + if (game->input.modifiers & KMOD_LALT) { movement(game, &res->camera, 1.0); } @@ -313,7 +320,6 @@ void update (struct game *game, u32 dt) { player_movement(game); } - player_terrain_collision(game); #ifdef DEBUG if (game->input.keystates[SDL_SCANCODE_R]) @@ -333,7 +339,7 @@ void update (struct game *game, u32 dt) { day_night_cycle(*time, res); - *time += dt * 0.00001f; + *time += game->dt * 0.00001f; node_recalc(root); diff --git a/src/update.h b/src/update.h @@ -4,7 +4,7 @@ #include "game.h" -void update(struct game * game, u32 dt); +void update(struct game * game); void resize_fbos(struct game * game, int width, int height); #endif /* PA_UPDATE_H */ diff --git a/src/util.h b/src/util.h @@ -16,6 +16,11 @@ } \ } +#define PI 3.14159265 +#define TAU 6.2831853 + +#define RAD(x) ((x)*TAU/360.0) + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) void look_at(vec3 *eye, vec3 *target, vec3 *up, mat4 *dest);