commit eb14d3882d3db43f762989e0f8225415b4cdda1c
parent cff1ee0c2406cfd95201db625be7560c69d9038a
Author: William Casarin <jb55@jb55.com>
Date: Tue, 13 Nov 2018 12:07:06 -0800
input edge states, free camera
Diffstat:
13 files changed, 200 insertions(+), 92 deletions(-)
diff --git a/Makefile b/Makefile
@@ -17,7 +17,6 @@ OBJS += $(SRC)/camera.o
OBJS += $(SRC)/debug.o
OBJS += $(SRC)/delaunay.o
OBJS += $(SRC)/entity.o
-OBJS += $(SRC)/event.o
OBJS += $(SRC)/fbo.o
OBJS += $(SRC)/file.o
OBJS += $(SRC)/game.o
diff --git a/src/entity.h b/src/entity.h
@@ -26,6 +26,7 @@ struct entity_id {
};
struct entity *init_entity(struct entity *);
+struct entity *delete_entities();
void init_entity_system();
struct entity *get_entity(struct entity_id *);
struct entity *get_all_entities(u32 *count, struct entity_id **ids);
diff --git a/src/event.c b/src/event.c
@@ -4,55 +4,3 @@
#include "input.h"
#include "game.h"
-void process_events(struct game *game, float *camera) {
- SDL_Event event;
- int mdx = 0;
- int mdy = 0;
-
- struct input *input = &game->input;
-
- input->last_mx = game->input.mx;
- input->last_my = game->input.my;
-
- input_reset(&game->input);
-
- while (SDL_PollEvent(&event)) {
- switch (event.type) {
- case SDL_MOUSEWHEEL:
- input->wheel_x = event.wheel.x;
- input->wheel_y = event.wheel.y;
- break;
- case SDL_KEYDOWN:
- case SDL_KEYUP:
- handle_key(input, event.key);
- break;
- case SDL_MOUSEBUTTONDOWN:
- if (event.button.button <= MOUSE_BUTTONS)
- input->mbuttons[event.button.button-1] = 1;
-
- break;
- case SDL_MOUSEBUTTONUP:
- if (event.button.button <= MOUSE_BUTTONS)
- input->mbuttons[event.button.button-1] = 0;
- break;
- case SDL_MOUSEMOTION:
- input->mx = event.motion.x;
- input->my = event.motion.y;
- input->mdx += event.motion.xrel;
- input->mdy += event.motion.yrel;
- break;
- case SDL_WINDOWEVENT:
- switch (event.window.event) {
- case SDL_WINDOWEVENT_RESIZED:
- handle_resize(game, event.window.data1, event.window.data2);
- break;
- }
- break;
- case SDL_QUIT:
- SDL_Quit();
- exit(0);
- }
-
- }
-
-}
diff --git a/src/event.h b/src/event.h
@@ -6,6 +6,4 @@
#include "input.h"
#include "game.h"
-void process_events(struct game *game, float *camera);
-
#endif /* PA_EVENT_H */
diff --git a/src/game.c b/src/game.c
@@ -20,6 +20,10 @@ mat4 *cam_init = (float[16]){
-71.766136, -47.881512, -44.216671, 1.000000
};
+int was_key_pressed_this_frame(struct game *game, int scancode) {
+ return is_key_down_on_frame(&game->input, scancode, game->frame);
+}
+
static void camera_update(struct node *node) {
mat4 *persp = (float*)node->custom_update_data;
mat4 *mat = (float*)node->mat;
@@ -34,6 +38,12 @@ struct entity *get_player(struct resources *res) {
return player;
}
+struct entity *get_terrain_entity(struct terrain *t) {
+ struct entity *ent = get_entity(&t->entity_id);
+ assert(ent);
+ return ent;
+}
+
static void init_user_settings(struct user_settings *settings) {
SDL_SetRelativeMouseMode(SDL_TRUE);
settings->mouse_sens = 0.1;
@@ -48,7 +58,6 @@ void game_init(struct game *game, int width, int height) {
struct resources *res = &game->test_resources;
mat4 *mvp = res->test_mvp;
struct node *root = &res->root;
- struct node *camera = &res->camera.node;
struct node *sun_camera = &res->sun_camera;
struct terrain *terrain = &game->terrain;
struct entity *player;
@@ -56,6 +65,8 @@ void game_init(struct game *game, int width, int height) {
mat4 *light_dir = res->light_dir;
int ok = 0;
+ game->frame = 0;
+
const double size = 10000.0;
terrain->settings = (struct perlin_settings){
@@ -104,22 +115,25 @@ void game_init(struct game *game, int width, int height) {
node_init(root);
node_init(sun_camera);
- init_orbit(&res->camera);
+ init_orbit(&res->orbit_camera);
+
// ENTITIES
// player entity
player = new_entity(&res->player_id);
+ assert(res->player_id.index == 1);
ok = load_model(&player->model, "pirate-officer");
assert(ok);
player->node.label = "player";
node_attach(&player->node, root);
- /* node_attach(&res->camera.node, &player->node); */
node_translate(&player->node, V3(terrain->size/2.,terrain->size/2.,0.0));
- res->camera.coords.azimuth = -quat_yaw(player->node.orientation) - RAD(90.0);
- res->camera.coords.inclination = RAD(60);
- res->camera.coords.radius = 5.0;
+ res->orbit_camera.coords.azimuth = -quat_yaw(player->node.orientation) - RAD(90.0);
+ res->orbit_camera.coords.inclination = RAD(60);
+ res->orbit_camera.coords.radius = 5.0;
+
+ res->camera_node = &res->orbit_camera.node;
struct entity *tower = new_entity(NULL);
ok = load_model(&tower->model, "tower");
@@ -137,10 +151,18 @@ void game_init(struct game *game, int width, int height) {
// player init
root->label = "root";
- camera->label = "camera";
input_init(&game->input);
+ // free camera
+ node_init(&res->free_camera);
+ res->free_camera.label = "free_camera";
+ node_attach(&res->free_camera, &player->node);
+ quat_axis_angle(V3(1,0,0), -45, res->free_camera.orientation);
+ node_rotate(&res->free_camera, V3(100, 0, 0));
+ node_translate(&res->free_camera, V3(0,-40,20));
+
+
// FBO STUFF
init_fbo(&res->shadow_buffer);
resize_fbos(player, &res->shadow_buffer, res->proj_ortho, width, height);
diff --git a/src/game.h b/src/game.h
@@ -60,7 +60,9 @@ struct resources {
struct node root;
struct entity_id player_id;
- struct orbit camera;
+ struct orbit orbit_camera;
+ struct node free_camera;
+ const struct node *camera_node;
struct node sun_camera;
u32 test_cubemap;
@@ -84,6 +86,7 @@ struct game {
int counter;
int seed;
float dt;
+ u64 frame;
struct user_settings user_settings;
struct ui ui;
struct resources test_resources;
@@ -92,7 +95,10 @@ struct game {
};
struct entity *get_player(struct resources *);
+struct entity *get_terrain_entity(struct terrain *);
void game_init(struct game *game, int width, int height);
void should_update(struct game *game);
+int was_key_pressed_this_frame(struct game *game, int scancode);
+int is_free_camera(struct game *game);
#endif /* PA_GAME_H */
diff --git a/src/input.c b/src/input.c
@@ -3,9 +3,95 @@
#include "util.h"
#include "common.h"
+static void key_down(struct input *input, int scancode, u64 current_frame) {
+ input->modifiers = SDL_GetModState();
+
+ struct key_edge *edge = &input->key_edge_states[scancode];
+
+ if (edge->is_down)
+ return;
+
+ edge->down_frame = current_frame;
+ edge->is_down = 1;
+
+ // might be useful to know when it was last up
+ /* edge->up_frame = 0; */
+}
+
+static void key_up(struct input *input, int scancode, u64 current_frame) {
+ struct key_edge *edge = &input->key_edge_states[scancode];
+
+ edge->up_frame = current_frame;
+ edge->is_down = 0;
+}
+
+
+void process_events(struct input *input, u64 current_frame) {
+ SDL_Event event;
+
+ input->last_mx = input->mx;
+ input->last_my = input->my;
+
+ input_reset(input);
+
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_MOUSEWHEEL:
+ input->wheel_x = event.wheel.x;
+ input->wheel_y = event.wheel.y;
+ break;
+ case SDL_KEYDOWN:
+ key_down(input, event.key.keysym.scancode, current_frame);
+ break;
+ case SDL_KEYUP:
+ key_up(input, event.key.keysym.scancode, current_frame);
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ if (event.button.button <= MOUSE_BUTTONS)
+ input->mbuttons[event.button.button-1] = 1;
+
+ break;
+ case SDL_MOUSEBUTTONUP:
+ if (event.button.button <= MOUSE_BUTTONS)
+ input->mbuttons[event.button.button-1] = 0;
+ break;
+ case SDL_MOUSEMOTION:
+ input->mx = event.motion.x;
+ input->my = event.motion.y;
+ input->mdx += event.motion.xrel;
+ input->mdy += event.motion.yrel;
+ break;
+ case SDL_WINDOWEVENT:
+ switch (event.window.event) {
+ case SDL_WINDOWEVENT_RESIZED:
+ if (!event.window.data1)
+ continue;
+ printf("resizing %d %d\n", event.window.data1, event.window.data2);
+ input->resized_width = event.window.data1;
+ input->resized_height = event.window.data2;
+ assert(input->resized_width);
+ assert(input->resized_height);
+ break;
+ }
+ break;
+ case SDL_QUIT:
+ SDL_Quit();
+ exit(0);
+ }
+
+ }
+
+ if (input->resized_width)
+ printf("checking resize %d %d\n", input->resized_width,
+ input->resized_height);
+
+}
+
void input_init(struct input *input) {
/* memset(input->keys, 0, sizeof(input->keys[0]) * ARRAY_SIZE(input->keys)); */
input->keystates = SDL_GetKeyboardState(NULL);
+ assert(sizeof(input->key_edge_states) == SDL_NUM_SCANCODES * sizeof(input->key_edge_states[0]));
+ memset(input->key_edge_states, 0, sizeof(input->key_edge_states));
input->mx = 0;
input->my = 0;
input->mdx = 0;
@@ -14,11 +100,16 @@ void input_init(struct input *input) {
input->wheel_y = 0;
input->last_mx = 0;
input->last_my = 0;
+ input->resized_height = 0;
+ input->resized_width = 0;
assert(input->keystates);
}
-void handle_key(struct input *input, SDL_KeyboardEvent key) {
- input->modifiers = SDL_GetModState();
+int is_key_down_on_frame(struct input *input, u8 scancode, u64 frame) {
+ struct key_edge *edge = &input->key_edge_states[scancode];
+
+ // is_down is implied, but do it for good measure
+ return edge->down_frame == frame && edge->is_down;
}
@@ -27,6 +118,8 @@ void input_reset(struct input *input) {
input->mdy = 0;
input->wheel_x = 0;
input->wheel_y = 0;
+ input->resized_height = 0;
+ input->resized_width = 0;
}
int input_is_dragging(struct input *input, int mouse_button) {
diff --git a/src/input.h b/src/input.h
@@ -14,6 +14,22 @@
#define MOUSE_BUTTONS 5
+/* #define KEY_BUFFER_SIZE 32 */
+
+#define FLAG_KEY_DOWN (1<<0)
+#define FLAG_KEY_UP (1<<1)
+
+enum key_edge_state {
+ EDGE_KEY_DOWN = 1 << 0,
+ EDGE_KEY_UP = 1 << 1,
+};
+
+struct key_edge {
+ int is_down;
+ u64 down_frame;
+ u64 up_frame;
+};
+
struct input {
/* enum key_state keys[0x7F-0x1F]; */
u8 const *keystates;
@@ -22,14 +38,27 @@ struct input {
int mdx, mdy;
float wheel_x, wheel_y;
int mbuttons[MOUSE_BUTTONS];
+ int n_frame_down_keys;
+ int n_frame_up_keys;
+ int resized_width;
+ int resized_height;
+ /* u64 down_key_frames[KEY_BUFFER_SIZE]; */
+ /* u64 up_key_frames[KEY_BUFFER_SIZE]; */
+ /* u8 frame_down_keys[KEY_BUFFER_SIZE]; */
+ /* u8 frame_up_keys[KEY_BUFFER_SIZE]; */
+ struct key_edge key_edge_states[SDL_NUM_SCANCODES];
};
int input_is_dragging(struct input *input, int mouse_button);
+int is_key_down_on_frame(struct input *input, u8 scancode, u64 frame);
+
void input_init(struct input *input);
void input_reset(struct input *input);
void handle_key(struct input *input, SDL_KeyboardEvent);
+void process_events(struct input *input, u64 current_frame);
+
#endif /* POLYADVENT_INPUT_H */
diff --git a/src/main.c b/src/main.c
@@ -73,13 +73,20 @@ int main(void)
struct render_config default_config = {
.draw_ui = 0,
.is_depth_pass = 0,
- .camera = game.test_resources.camera.node.mat,
+ .camera = game.test_resources.camera_node->mat,
.projection = game.test_resources.proj_persp,
.depth_vp = depth_vp
};
while (1) {
- process_events(&game, game.test_resources.proj_persp);
+ game.frame++;
+ process_events(&game.input, game.frame);
+ if (game.input.resized_height) {
+ printf("handling resize %d %d\n", game.input.resized_width,
+ game.input.resized_height);
+ handle_resize(&game, game.input.resized_width, game.input.resized_height);
+ }
+ default_config.camera = game.test_resources.camera_node->mat;
double new_time = hires_time_in_seconds();
double frame_time = new_time - last;
game.dt = frame_time;
diff --git a/src/orbit.c b/src/orbit.c
@@ -73,6 +73,7 @@ static void orbit_node_update(struct node *node) {
void init_orbit(struct orbit *orbit) {
node_init(&orbit->node);
+ orbit->node.label = "orbit_camera";
/* orbit->node.custom_update = orbit_node_update; */
/* orbit->node.custom_update_data = orbit; */
}
diff --git a/src/render.c b/src/render.c
@@ -260,7 +260,7 @@ void render (struct game *game, struct render_config *config) {
mat4 *projection = config->projection;
mat4 *light = res->light_dir;
- float *camera = config->camera;
+ const mat4 *camera = config->camera;
u32 num_entities;
struct entity *entities =
@@ -276,7 +276,7 @@ void render (struct game *game, struct render_config *config) {
/* mat4_multiply(view_proj, res->skybox.node.mat, mvp); */
- mat4_inverse(camera, view);
+ mat4_inverse((float*)camera, view);
mat4_multiply(projection, view, view_proj);
if (config->is_depth_pass) {
@@ -287,7 +287,7 @@ void render (struct game *game, struct render_config *config) {
glCullFace(GL_BACK);
}
- mat4_inverse(camera, view);
+ mat4_inverse((float *)camera, view);
mat4_multiply(projection, view, view_proj);
glBindTexture(GL_TEXTURE_CUBE_MAP, res->skybox.model.texture);
@@ -351,7 +351,7 @@ void render (struct game *game, struct render_config *config) {
}
if (!config->is_depth_pass) {
- mat4_inverse(camera, view);
+ mat4_inverse((float*)camera, view);
mat4_remove_translations(view);
mat4_multiply(projection, view, view_proj);
diff --git a/src/render.h b/src/render.h
@@ -8,7 +8,7 @@ struct game;
struct render_config {
int draw_ui;
int is_depth_pass;
- float *camera;
+ const float *camera;
float *projection;
float *depth_vp;
};
diff --git a/src/update.c b/src/update.c
@@ -8,6 +8,7 @@
#include "camera.h"
#include "poisson.h"
#include "uniform.h"
+#include "game.h"
#include "mat_util.h"
#include "shader.h"
#include "file.h"
@@ -55,7 +56,7 @@ static void movement(struct game *game, struct node *node, float speed_mult) {
/* if (game->input.keystates[SDL_SCANCODE_DOWN]) */
/* node_translate(node, V3(0, 0, -amt)); */
- if (game->input.keystates[SDL_SCANCODE_P]) {
+ if (was_key_pressed_this_frame(game, SDL_SCANCODE_P)) {
printf("%f %f %f\n",
node->pos[0],
node->pos[1],
@@ -312,15 +313,14 @@ void orbit_update_from_mouse(struct orbit *camera, struct input *input,
}
-static void orbit_keep_above_ground(struct game *game) {
- struct resources *res = &game->test_resources;
-
- if (!(get_entity(&game->terrain.entity_id)->flags & ENT_INVISIBLE)) {
- float *camera_world = node_world(&res->camera.node);
+static void camera_keep_above_ground(struct terrain *terrain,
+ const struct node *camera) {
+ if (!(get_entity(&terrain->entity_id)->flags & ENT_INVISIBLE)) {
+ float *camera_world = node_world((struct node*)camera);
/* float *target = node_world(&get_player(res)->node); */
/* spherical_pos(&res->camera.coords, target, camera_world); */
float cam_terrain_z =
- game->terrain.fn(&game->terrain, camera_world[0], camera_world[1]);
+ terrain->fn(terrain, camera_world[0], camera_world[1]);
const float bias = 2.0;
@@ -331,18 +331,17 @@ static void orbit_keep_above_ground(struct game *game) {
static void player_update(struct game *game, struct entity *player) {
- struct orbit *camera = &game->test_resources.camera;
+ struct resources *res = &game->test_resources;
+ struct orbit *camera = &res->orbit_camera;
+
orbit_update_from_mouse(camera, &game->input, game->user_settings.mouse_sens,
player, game->dt);
- orbit_keep_above_ground(game);
-
- /* look_at(node_world(&camera->node), node_world(&player->node), UP_VEC, */
- /* camera->node.mat); */
+ camera_keep_above_ground(&game->terrain, res->camera_node);
// move player camera toward camera orientation
if (input_is_dragging(&game->input, SDL_BUTTON_RIGHT)) {
- float yaw = game->test_resources.camera.coords.azimuth;
+ float yaw = game->test_resources.orbit_camera.coords.azimuth;
quat_axis_angle(V3(0.0, 0.0, 1.0), -yaw - RAD(90), player->node.orientation);
}
player_terrain_collision(&game->terrain, player);
@@ -372,25 +371,30 @@ void update (struct game *game) {
/* vec3_scale(camera_dir, -1, camera_dir); */
if (game->input.modifiers & KMOD_LALT) {
- movement(game, &res->camera.node, 1.0);
+ if (res->camera_node == &res->free_camera)
+ movement(game, &res->free_camera, 1.0);
}
else {
player_movement(game, player);
}
player_update(game, player);
-
-#ifdef DEBUG
- if (game->input.keystates[SDL_SCANCODE_R])
+ if (was_key_pressed_this_frame(game, SDL_SCANCODE_R))
try_reload_shaders(res);
-#endif
- if (game->input.keystates[SDL_SCANCODE_C])
+ if (was_key_pressed_this_frame(game, SDL_SCANCODE_C))
printf("light_dir %f %f %f\n", light[0], light[1], light[2]);
- if (game->input.keystates[SDL_SCANCODE_F])
+ if (was_key_pressed_this_frame(game, SDL_SCANCODE_F))
toggle_fog = 1;
+ if (was_key_pressed_this_frame(game, SDL_SCANCODE_EQUALS)) {
+ if (res->camera_node != &res->free_camera)
+ res->camera_node = &res->free_camera;
+ else
+ res->camera_node = &res->orbit_camera.node;
+ }
+
if (toggle_fog) {
res->fog_on = !res->fog_on;
toggle_fog = 0;