commit 1a35612b18f3291266b0c4e84095c7e98d503cc9
parent 240e9581a202f39037bc124f0bf4457ee110974c
Author: William Casarin <jb55@jb55.com>
Date: Thu, 23 Sep 2021 20:14:24 -0700
split test game out of game engine
Diffstat:
28 files changed, 1132 insertions(+), 1077 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -13,3 +13,5 @@ polyadvent
/test/test_dae
/data/models/*.mdl
data/models/third-party-src/
+/.build-result
+/.buildcmd
diff --git a/main.c b/main.c
@@ -20,6 +20,8 @@
#include "util.h"
#include "window.h"
+#include "test_game.h"
+
#include <stdio.h>
@@ -37,77 +39,47 @@ int main(void)
printf("seed %d\n", seed);
srand(seed);
- struct game game;
- game.seed = seed;
+ struct game engine;
+ struct test_game test_game;
+
+ engine.seed = seed;
/* SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); */
int width = 640;
int hello;
int height = 480;
- game_init(&game, width, height);
- default_scene(&game);
+ game_init(&engine, width, height);
+
+ init_test_game(&test_game, &engine.gpu, width, height);
+
+ //reset_scene(&engine);
+ default_scene(&test_game);
+ //pbr_scene(&test_game);
//chess_scene(&game);
check_gl();
double last = hires_time_in_seconds();
- static float depth_vp[MAT4_ELEMS];
- mat4_id(depth_vp);
-
- struct render_config fbo_render_config = {
- .draw_ui = 1,
- .is_depth_pass = 1,
- .camera = game.test_resources.sun_camera_id,
- .projection = game.test_resources.proj_ortho,
- .depth_vp = depth_vp
- };
-
- struct render_config default_config = {
- .draw_ui = 1,
- .is_depth_pass = 0,
- .camera = game.test_resources.camera_node_id,
- .projection = game.test_resources.proj_persp,
- .depth_vp = depth_vp
- };
-
-
- while (!game.quit) {
- game.input.keystates = SDL_GetKeyboardState(NULL);
- 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);
+
+ while (!engine.quit) {
+ engine.input.keystates = SDL_GetKeyboardState(NULL);
+ engine.frame++;
+ process_events(&engine.input, engine.frame);
+ if (engine.input.resized_height) {
+ printf("handling resize %d %d\n", engine.input.resized_width,
+ engine.input.resized_height);
+ handle_resize(&engine, engine.input.resized_width, engine.input.resized_height);
}
- //default_config.camera = game.test_resources.camera_node->mat;
+ //default_config.camera = engine.test_resources.camera_node->mat;
double new_time = hires_time_in_seconds();
double frame_time = new_time - last;
- game.dt = frame_time;
- if (game.frame % 60 == 0)
- printf("%f fps\n", 1000.0 / (frame_time*1000) );
-
- update(&game);
-
- /* while (accumulator >= dt) { */
- /* t += dt; */
- /* accumulator -= dt; */
- /* } */
-
- default_config.camera = game.test_resources.camera_node_id;
-
+ engine.dt = frame_time;
last = new_time;
- struct fbo *fbo = &game.test_resources.shadow_buffer;
- check_fbo(fbo);
- bind_fbo(fbo);
- /* glDrawBuffer(GL_NONE); */
-
- render(&game, &fbo_render_config);
- unbind_fbo(&game.test_resources.shadow_buffer);
- render(&game, &default_config);
+ // render our game frame here
+ test_game_frame(&engine, &test_game);
/* Swap front and back buffers */
- SDL_GL_SwapWindow(game.window);
+ SDL_GL_SwapWindow(engine.window);
}
/* free(slab_buffer); */
diff --git a/src/camera.c b/src/camera.c
@@ -1,5 +1,6 @@
#include "camera.h"
+#include "input.h"
#include "mat_util.h"
// should probably be a scene node
diff --git a/src/camera.h b/src/camera.h
@@ -7,11 +7,10 @@
#include "node.h"
struct camera {
- float frustum[16];
- node_id node_id;
+ float frustum[16];
+ node_id node_id;
};
-void
-camera_follow(vec3 *cam_pos, vec3 *target, mat4 *cam);
+void camera_follow(vec3 *cam_pos, vec3 *target, mat4 *cam);
#endif /* POLYADVENT_CAMERA_H */
diff --git a/src/chess.c b/src/chess.c
@@ -1,6 +1,5 @@
#include "chess.h"
-
#include "node.h"
// v1------v0
@@ -179,11 +178,11 @@ static void setup_pieces(node_id *chessboard) {
}
-void chess_scene(struct game *game)
+void chess_scene(struct test_game *game)
{
struct entity *ent = new_entity(NULL);
struct node *node = get_node(&ent->node_id); assert(node);
- struct entity *player = get_player(&game->test_resources);
+ struct entity *player = get_entity(&game->player_id);
ent->model_id = get_model_by_name("icosphere", NULL);
node_set_label(node, "sphere");
@@ -207,7 +206,7 @@ void chess_scene(struct game *game)
//
// setup camera
//
- struct spherical *coords = &game->test_resources.orbit_camera.coords;
+ struct spherical *coords = &game->orbit_camera.coords;
coords->radius = 72.0;
coords->inclination = 0.5;
coords->azimuth = -7.86;
@@ -217,7 +216,7 @@ void chess_scene(struct game *game)
pnode->orientation[2] = -0.005;
pnode->orientation[3] = -1.0;
- node_id *cam_id = &game->test_resources.orbit_camera.node_id;
+ node_id *cam_id = &game->orbit_camera.node_id;
struct node *cam_node = get_node(cam_id); assert(cam_node);
setup_pieces(&player->node_id);
diff --git a/src/chess.h b/src/chess.h
@@ -2,8 +2,8 @@
#ifndef POLYADVENT_CHESS_H
#define POLYADVENT_CHESS_H
-#include "game.h"
+#include "test_game.h"
-void chess_scene(struct game *game);
+void chess_scene(struct test_game *game);
#endif /* POLYADVENT_CHESS_H */
diff --git a/src/game.c b/src/game.c
@@ -35,19 +35,6 @@ bool was_button_pressed_this_frame(struct game *game, int button)
return is_button_down_on_frame(&game->input, button, game->frame);
}
-struct entity *get_player(struct resources *res) {
- struct entity *player = get_entity(&res->player_id);
- assert(player);
- 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;
@@ -72,127 +59,14 @@ void quit_game(struct game *game)
}
// TODO: cleanup
-void init_misc(struct game *game, int width, int height) {
- struct resources *res = &game->test_resources;
- mat4 *mvp = res->test_mvp;
-
- init_id(&res->root_id);
- init_id(&res->sun_camera_id);
- init_id(&res->free_camera_id);
-
- struct node *root = new_node(&res->root_id);
- struct node *sun_camera = new_node(&res->sun_camera_id);
-
- struct terrain *terrain = &game->terrain;
- struct entity *player;
-
- assert(root->parent_id.generation == 0);
- assert(root);
- assert(sun_camera);
-
- mat4 *light_dir = res->light_dir;
-
+void init_misc(struct game *game) {
game->quit = 0;
game->frame = 0;
+ game->gpu.num_programs = 0;
- const double size = 4000.0;
- //double scale = 0.03;
- double scale = 0.03;
-
- terrain->settings = (struct perlin_settings){
- .depth = 1,
- .freq = scale * 0.08,
- .o1 = 2.0, .o1s = 0.5,
- .o2 = 4.0, .o2s = 0.25,
- .amplitude = 70.0,
- .ox = 0,
- .oy = 0,
- .exp = 5.3,
- .scale = scale
- };
-
- debug("creating ui...\n");
- create_ui(&game->ui, width, height, &res->programs[UI_PROGRAM]);
- check_gl();
-
- init_terrain(terrain, size);
- /* terrain->samples = load_samples(&seed, &terrain->n_samples); */
- terrain->n_samples = 0;
- //create_terrain(terrain, size, game->seed);
- load_terrain(terrain);
- /* update_terrain(terrain, terrain->cell_size); */
- /* get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE; */
-
- debug("creating skybox...\n");
- create_skybox(&res->skybox, &res->programs[SKYBOX_PROGRAM]); /* node_translate(&res->skybox.node, V3(-100.0, -100.0, 0.0)); */
- /* node_scale(&res->skybox.node, size/4.0); */
-
- mat4_id(mvp);
-
- res->time = 0;
- res->light_intensity = 0.8;
-
- light_dir[0] = 0.8;
- light_dir[1] = 0.8;
- light_dir[2] = 0.8;
-
- res->piece_color[0] = 1.0;
- res->piece_color[1] = 1.0;
- res->piece_color[2] = 1.0;
-
- res->sun_color[0] = 0.5;
- res->sun_color[1] = 0.6;
- res->sun_color[2] = 0.7;
-
- game->test_resources.fog_on = 0;
- game->test_resources.diffuse_on = 0;
-
- node_init(root);
- node_init(sun_camera);
- new_orbit(&res->orbit_camera);
-
- node_set_label(root, "root");
-
- // ENTITIES
-
- // player entity
- init_id(&res->player_id);
- player = new_entity(&res->player_id);
- player->flags |= ENT_CASTS_SHADOWS;
- struct node *pnode = get_node(&player->node_id);
- assert(pnode);
-
- player->model_id = get_model_by_name("pirate_officer", NULL);
- assert(!is_null_id(&player->model_id.id));
-
- node_set_label(pnode, "player");
- /* node_rotate(pnode, V3(-5.0,0,0)); */
- node_attach(&player->node_id, &res->root_id);
- assert(ideq(&pnode->parent_id, &res->root_id));
-
- node_translate(pnode, V3(terrain->size/2.,terrain->size/2.,0.0));
-
- // orbit camera
- res->orbit_camera.coords.azimuth = -quat_yaw(pnode->orientation) - RAD(90.0);
- res->orbit_camera.coords.inclination = RAD(60);
- res->orbit_camera.coords.radius = 5.0;
- res->camera_node_id = res->orbit_camera.node_id;
-
- // free camera
- struct node *freecam = new_node(&res->free_camera_id);
- node_set_label(freecam, "freecam");
- node_attach(&res->free_camera_id, &player->node_id);
- quat_axis_angle(V3(1,0,0), -45, freecam->orientation);
- node_rotate(freecam, V3(100, 0, 0));
- node_translate(freecam, V3(0,-40,20));
-
- // FBO STUFF
- init_fbo(&res->shadow_buffer);
- resize_fbos(player, &res->shadow_buffer, res->proj_ortho, width, height);
- // FBO STUFF END
-
- // TEXTURES
- // END TEXTURES
+//debug("creating ui...\n");
+ //create_ui(&game->ui, width, height, &res->programs[UI_PROGRAM]);
+ //check_gl();
}
/*
@@ -219,17 +93,14 @@ void init_controller(struct input *input) {
}
*/
-void init_resources(struct resources *res)
-{
- memset(res, 0, sizeof(*res));
-}
void game_init(struct game *game, int width, int height) {
- init_resources(&game->test_resources);
+ game->width = width;
+ game->height = height;
debug("init sdl...\n");
init_sdl(&game->window, width, height);
debug("init gl...\n");
- init_gl(&game->test_resources, width, height);
+ init_gl();
debug("init entities...\n");
init_entity_system();
debug("init geom...\n");
@@ -249,5 +120,6 @@ void game_init(struct game *game, int width, int height) {
init_input(&game->input);
//init_controller(&game->input);
debug("init misc...\n");
- init_misc(game, width, height);
+ init_misc(game);
+
}
diff --git a/src/game.h b/src/game.h
@@ -14,44 +14,16 @@
#include "terrain.h"
#include "texture.h"
#include "ui.h"
+#include "gpu.h"
#include <stdio.h>
#define PLAYER_HEIGHT 1.73
-#define MAX_PROGRAMS 12
-
/*
* Global data used by our render callback:
* NOTE: just for testing right now
*/
-struct resources {
- struct vbo vertex_buffer, element_buffer, normal_buffer;
- struct fbo shadow_buffer;
-
- struct gpu_program programs[MAX_PROGRAMS];
-
- node_id root_id;
- entity_id player_id;
- struct geometry qh_test;
- struct orbit orbit_camera;
- node_id free_camera_id;
- node_id camera_node_id;
- node_id sun_camera_id;
-
- u32 test_cubemap;
- float time;
- bool fog_on, diffuse_on;
-
- struct skybox skybox;
- float sun_color[3];
- float piece_color[3];
- float test_mvp[MAT4_ELEMS];
- float light_dir[3];
- float light_intensity;
- float proj_persp[MAT4_ELEMS];
- float proj_ortho[MAT4_ELEMS];
-};
struct user_settings {
float mouse_sens;
@@ -63,17 +35,15 @@ struct game {
int seed;
int quit;
int wireframe;
+ int width, height;
float dt;
u64 frame;
struct user_settings user_settings;
struct ui ui;
- struct resources test_resources;
struct input input;
- struct terrain terrain;
+ struct gpu gpu;
};
-struct entity *get_player(struct resources *);
-struct entity *get_terrain_entity(struct terrain *);
void game_init(struct game *game, int width, int height);
void quit_game(struct game *game);
void should_update(struct game *game);
diff --git a/src/gpu.c b/src/gpu.c
@@ -0,0 +1,23 @@
+
+#include "gpu.h"
+#include <stdio.h>
+
+int try_reload_shaders(struct gpu *gpu) {
+ int ret = 0;
+ for (int i = 0; i < gpu->num_programs; ++i) {
+ struct gpu_program *program = &gpu->programs[i];
+ ret = reload_program(program, gpu->programs);
+
+ if (ret == 2) {}
+ else if (ret == 1)
+ printf("reload %s success.\n", program->shaders[0].filename);
+ else
+ printf("reload %s failed.\n", program->shaders[0].filename);
+
+ // failure ok, clear any errors
+ glGetError();
+ }
+
+ return ret;
+}
+
diff --git a/src/gpu.h b/src/gpu.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "shader.h"
+
+#define MAX_GPU_PROGRAMS 12
+
+struct gpu {
+ struct gpu_program programs[MAX_GPU_PROGRAMS];
+ int num_programs;
+};
+
+int try_reload_shaders(struct gpu *gpu);
diff --git a/src/movement.c b/src/movement.c
@@ -0,0 +1,89 @@
+
+#include "game.h"
+
+void movement(struct game *engine, struct node *node, float speed_mult)
+{
+ float amt = 3.0 * engine->dt;
+ float turn = 1.0 * engine->dt;
+
+ float x_axis = (float)engine->input.axis[0] / (float)MAX_AXIS_VALUE;
+ float y_axis = (float)engine->input.axis[1] / (float)MAX_AXIS_VALUE;
+
+ amt *= speed_mult;
+
+ if ((engine->input.modifiers & KMOD_SHIFT) /*||
+ is_button_down(&engine->input, SDL_CONTROLLER_BUTTON_LEFTSTICK)*/) {
+ amt *= 20;
+ }
+
+ // joystick movement
+ node_forward(node, V3(0,amt*y_axis, 0));
+ node_forward(node, V3(amt*x_axis, 0, 0));
+
+ if (engine->input.keystates[SDL_SCANCODE_A])
+ node_forward(node, V3(-amt,0,0));
+
+ if (engine->input.keystates[SDL_SCANCODE_UP])
+ node_forward(node, V3(0,0,amt));
+
+ if (engine->input.keystates[SDL_SCANCODE_DOWN])
+ node_forward(node, V3(0,0,-amt));
+
+ if (engine->input.keystates[SDL_SCANCODE_D])
+ node_forward(node, V3(amt,0,0));
+
+ if (engine->input.keystates[SDL_SCANCODE_W])
+ node_forward(node, V3(0,amt,0));
+
+ if (engine->input.keystates[SDL_SCANCODE_S])
+ node_forward(node, V3(0,-amt,0));
+
+ if (engine->input.keystates[SDL_SCANCODE_K])
+ node_forward(node, V3(0, 0,amt));
+
+ if (engine->input.keystates[SDL_SCANCODE_J])
+ node_forward(node, V3(0, 0,-amt));
+
+ if (engine->input.keystates[SDL_SCANCODE_E])
+ node_rotate(node, V3(0, 0, turn));
+
+ if (engine->input.keystates[SDL_SCANCODE_Q])
+ node_rotate(node, V3(0, 0, -turn));
+
+ /* if (engine->input.keystates[SDL_SCANCODE_DOWN]) */
+ /* node_translate(node, V3(0, 0, -amt)); */
+
+ if (was_key_pressed_this_frame(engine, SDL_SCANCODE_P)) {
+ debug("player %f %f %f quat %f %f %f %f\n",
+ node->pos[0],
+ node->pos[1],
+ node->pos[2],
+ node->orientation[0],
+ node->orientation[1],
+ node->orientation[2],
+ node->orientation[3]
+ );
+ }
+}
+
+
+void entity_jump(struct entity *ent, float amount)
+{
+ float dir[3];
+ vec3_normalize(ent->velocity, dir);
+ vec3_add(dir, V3(0, 0, amount), dir);
+ vec3_add(ent->velocity, dir, ent->velocity);
+}
+
+
+void gravity(struct entity *ent, float dt) {
+ if (ent->flags & ENT_ON_GROUND)
+ return;
+
+ struct node *pnode = get_node(&ent->node_id);
+ assert(pnode);
+
+ static const float g = -1.0;
+ vec3_add(ent->velocity, V3(0.0, 0.0, g * dt), ent->velocity);
+}
+
diff --git a/src/movement.h b/src/movement.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "game.h"
+
+void movement(struct game *game, struct node *node, float speed_mult);
+void entity_jump(struct entity *ent, float amount);
+void gravity(struct entity *ent, float dt);
diff --git a/src/orbit_util.c b/src/orbit_util.c
@@ -0,0 +1,59 @@
+
+#include "orbit.h"
+#include "input.h"
+#include "entity.h"
+
+void orbit_update_from_mouse(struct orbit *camera, struct input *input,
+ float mouse_sens, struct entity *player,
+ float dt)
+{
+ float target[3];
+ struct node *target_node = get_node(&player->node_id);
+ struct node *cam_node = get_node(&camera->node_id);
+ struct model *pmodel = get_model(&player->model_id); assert(pmodel);
+ struct geometry *player_geom = get_geometry(&pmodel->geom_id); assert(player_geom);
+
+ assert(target_node);
+ assert(cam_node);
+
+ node_recalc(target_node);
+ vec3_copy(node_world(target_node), target);
+ assert(player_geom->max[2] != 0);
+ vec3_add(target, V3(0.0, 0.0, player_geom->max[2]), target);
+ /* vec3_add(target, V3(0.0, 0.0, 10.0), target); */
+
+ float mx = 0.0, my = 0.0;
+ if (input_is_dragging(input, SDL_BUTTON_LEFT) ||
+ input_is_dragging(input, SDL_BUTTON_RIGHT)) {
+ mx = -input->mdx * mouse_sens * dt;
+ my = -input->mdy * mouse_sens * dt;
+ }
+
+ // zoom
+ if (input->keystates[SDL_SCANCODE_V]) {
+ if (input->modifiers & KMOD_SHIFT)
+ camera->coords.radius += dt * 100.0;
+ else
+ camera->coords.radius -= dt * 100.0;
+
+ }
+ else if (input->wheel_y) {
+ camera->coords.radius += input->wheel_y * dt * 100.0;
+ }
+
+ camera->coords.radius = max(1.0, camera->coords.radius);
+
+ camera->coords.azimuth += mx;
+ camera->coords.inclination += my;
+
+ /*
+ printf("coords azimuth %f inclination %f radius %f\n",
+ camera->coords.azimuth,
+ camera->coords.inclination,
+ camera->coords.radius);
+ */
+
+ spherical_look_at(&camera->coords, target, cam_node->mat);
+
+}
+
diff --git a/src/orbit_util.h b/src/orbit_util.h
@@ -0,0 +1,5 @@
+#pragma once
+
+void orbit_update_from_mouse(struct orbit *camera, struct input *input,
+ float mouse_sens, struct entity *player,
+ float dt);
diff --git a/src/quat.c b/src/quat.c
@@ -75,10 +75,6 @@ void quat_to_mat3(quat *quat, float *dest) {
}
-float quat_yaw(quat *q) {
- return atan2(q[2],q[3])*2.0;
-}
-
void quat_multiply_vec3(quat *quat, float *vec, float *dest) {
float x = vec[0], y = vec[1], z = vec[2];
float qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3];
diff --git a/src/quat.h b/src/quat.h
@@ -3,6 +3,8 @@
#ifndef POLYADVENT_QUAT4_
#define POLYADVENT_QUAT4_
+#include <math.h>
+
typedef float quat;
#define QUAT(x,y,z,w) ((quat[4]){x,y,z,w})
@@ -11,8 +13,11 @@ void quat_multiply(quat *a, quat *b, quat *dest);
void quat_axis_angle(float *axis, float angle, quat *dest);
void quat_from_axes(float yaw, float pitch, float roll);
void quat_to_mat3(quat *quat, float *dest);
-float quat_yaw(quat *quat);
void quat_multiply_vec3(quat *quat, float *vec, float *dest);
quat *quat_inverse(quat *q, quat *dest);
+static inline float quat_yaw(quat *q) {
+ return atan2(q[2],q[3])*2.0;
+}
+
#endif /* POLYADVENT_QUAT4_ */
diff --git a/src/render.c b/src/render.c
@@ -54,78 +54,23 @@ static const GLushort cube_indices[] = {
20,21,22, 20,22,23
};
-static const float bias_matrix[] = {
- 0.5, 0.0, 0.0, 0.0,
- 0.0, 0.5, 0.0, 0.0,
- 0.0, 0.0, 0.5, 0.0,
- 0.5, 0.5, 0.5, 1.0
-};
-
-void init_gl(struct resources *resources, int width, int height) {
- struct shader vertex, terrain_vertex, chess_piece_vertex, terrain_geom, fragment, fragment_smooth;
- struct shader terrain_teval, terrain_tc;
- float tmp_matrix[16];
- int ok = 0;
-
+void init_gl()
+{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_MULTISAMPLE);
check_gl();
-
- // Shaders
- ok = make_shader(GL_VERTEX_SHADER, SHADER("vertex-color.glsl"),
- &vertex);
- rtassert(ok, "vertex-color shader");
-
- ok = make_shader(GL_VERTEX_SHADER, SHADER("terrain.v.glsl"), &terrain_vertex);
- rtassert(ok, "terrain vertex shader");
- check_gl();
-
- ok = make_shader(GL_VERTEX_SHADER, SHADER("chess-piece.v.glsl"), &chess_piece_vertex);
- rtassert(ok, "chess-piece vertex shader");
- check_gl();
-
- ok = make_shader(GL_FRAGMENT_SHADER, SHADER("main.f.glsl"), &fragment);
- rtassert(ok, "default fragment shader");
- check_gl();
-
- // camera
- mat4_perspective(90 /* fov */,
- (float)width / height,
- 1,
- 5000,
- resources->proj_persp);
-
- struct gpu_program *programs = resources->programs;
- struct gpu_program *program;
-
- ok = make_program("terrain", &terrain_vertex, &fragment,
- &programs[TERRAIN_PROGRAM]);
- // TODO: replace rtassert with error reporting/handling
- rtassert(ok, "terrain program");
- check_gl();
-
- ok = make_program("vertex-color", &vertex, &fragment, &programs[DEFAULT_PROGRAM]);
- rtassert(ok, "vertex-color program");
- check_gl();
-
-
- program = &programs[CHESS_PIECE_PROGRAM];
- ok = make_program("chess-piece", &chess_piece_vertex, &fragment, program);
- rtassert(ok, "chess-piece program");
-
- find_uniforms(programs);
}
-static void
-recalc_normals(GLint nm_uniform, mat4 *model_view, mat4 *normal) {
- mat4_inverse(model_view, normal);
- mat4_transpose(normal, normal);
- /* mat4_copy(model_view, normal); */
- glUniformMatrix4fv(nm_uniform, 1, 0, normal);
+void recalc_normals(GLint nm_uniform, mat4 *model_view, mat4 *normal)
+{
+ mat4_inverse(model_view, normal);
+ mat4_transpose(normal, normal);
+ /* mat4_copy(model_view, normal); */
+ glUniformMatrix4fv(nm_uniform, 1, 0, normal);
}
static void gamma_correct(float *c, float *d) {
@@ -135,171 +80,3 @@ static void gamma_correct(float *c, float *d) {
d[2] = powf(c[2], gamma);
}
-static inline void uniform_3f(struct gpu_program *program,
- enum uniform_id id, const float *v3)
-{
- glUniform3f(program->uniforms[id].location, v3[0], v3[1], v3[2]);
- check_gl();
-}
-
-static inline void uniform_1i(struct gpu_program *program,
- enum uniform_id id, int i)
-{
- glUniform1i(program->uniforms[id].location, i);
- check_gl();
-}
-
-static inline void uniform_m4f(struct gpu_program *program,
- enum uniform_id id, float *m)
-{
- glUniformMatrix4fv(program->uniforms[id].location, 1, 0, m);
- check_gl();
-}
-
-static inline void uniform_1f(struct gpu_program *program,
- enum uniform_id id, float f)
-{
- glUniform1f(program->uniforms[id].location, f);
- check_gl();
-}
-
-void render (struct game *game, struct render_config *config) {
- float gtmp[3];
- struct resources *res = &game->test_resources;
-
- glEnable(GL_DEPTH_TEST);
-
- float sky_intensity = clamp(res->light_intensity, 0.2, 1.0);
- vec3_scale(res->sun_color, sky_intensity, gtmp);
-
- glClearColor( gtmp[0], gtmp[1], gtmp[2], 1.0 ); //clear background screen to black
- /* glClearColor( 0.5294f * adjust, 0.8078f * adjust, 0.9216f * adjust, 1.0f ); //clear background screen to black */
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
- check_gl();
-
- static float id[MAT4_ELEMS] = { 0 };
- static float view[MAT4_ELEMS] = { 0 };
- static float view_proj[MAT4_ELEMS] = { 0 };
- static float normal_matrix[MAT4_ELEMS] = { 0 };
- static float model_view[MAT4_ELEMS] = { 0 };
- static float depth_mvp[MAT4_ELEMS] = { 0 };
- mat4_id(id);
- mat4_id(model_view);
-
- mat4 *mvp = res->test_mvp;
- mat4 *projection = config->projection;
- mat4 *light = res->light_dir;
-
- struct node *camera_node = get_node(&config->camera);
- assert(camera_node);
-
- const mat4 *camera = camera_node->mat;
- u32 num_entities;
-
- struct entity *entities =
- get_all_entities(&num_entities, NULL);
-
- struct gpu_program *program = NULL;
-
- mat4_inverse((float*)camera, view);
- mat4_multiply(projection, view, view_proj);
-
- if (config->is_depth_pass) {
- glDisable(GL_CULL_FACE);
- mat4_multiply(bias_matrix, view_proj, config->depth_vp);
- }
- else {
- glCullFace(GL_BACK);
- }
-
- mat4_inverse((float *)camera, view);
- mat4_multiply(projection, view, view_proj);
-
- struct model *skybox_model = get_model(&res->skybox.model_id);
- assert(skybox_model);
-
- glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_model->texture);
- check_gl();
-
- for (u32 i = 0; i < num_entities; ++i) {
- struct entity *entity = &entities[i];
- struct model *model = get_model(&entity->model_id);
- assert(model);
- struct node *node = get_node(&entity->node_id);
- assert(node);
-
- if (entity->flags & ENT_INVISIBLE)
- continue;
-
- if (config->is_depth_pass && !(entity->flags & ENT_CASTS_SHADOWS))
- continue;
-
- program = &game->test_resources.programs[model->shader];
-
- glUseProgram(program->handle);
- check_gl();
-
- uniform_3f(program, UNIFORM_CAMERA_POSITION, &camera[M_X]);
-
- if (model->shader == CHESS_PIECE_PROGRAM) {
- uniform_1i(program, UNIFORM_IS_WHITE,
- (entity->flags & ENT_IS_WHITE) == ENT_IS_WHITE);
- }
-
- uniform_1i(program, UNIFORM_FOG_ON, res->fog_on);
- uniform_3f(program, UNIFORM_LIGHT_DIR, light);
- uniform_1f(program, UNIFORM_LIGHT_INTENSITY, res->light_intensity);
- uniform_1f(program, UNIFORM_SKY_INTENSITY, sky_intensity);
- uniform_3f(program, UNIFORM_SUN_COLOR, res->sun_color);
-
- mat4_multiply(view_proj, node->mat, mvp);
- mat4_copy(node->mat, model_view);
- mat4_multiply(config->depth_vp, model_view, depth_mvp);
- uniform_m4f(program, UNIFORM_DEPTH_MVP, depth_mvp);
- uniform_m4f(program, UNIFORM_MVP, mvp);
- uniform_m4f(program, UNIFORM_MODEL, node->mat);
-
- recalc_normals(program->uniforms[UNIFORM_NORMAL_MATRIX].location,
- model_view, normal_matrix);
- check_gl();
-
- struct geometry *geo = get_geometry(&model->geom_id);
- /* debug("geo node %s\n", node->label); */
- assert(geo);
- render_geometry(geo, program->vertex_attrs, program);
- check_gl();
- }
-
- if (game->wireframe) {
- glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- }
- else {
- glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
- }
-
- if (!config->is_depth_pass) {
- mat4_inverse((float*)camera, view);
- mat4_remove_translations(view);
- mat4_multiply(projection, view, view_proj);
-
- render_skybox(&res->skybox, view_proj);
- }
-
- if (config->draw_ui)
- render_ui(&game->ui, view);
-
- //player
- // y tho
-
- // terrain
-
- /* glUniformMatrix4fv(res->uniforms.mvp, 1, 0, mvp); */
- /* glUniformMatrix4fv(res->uniforms.model_view, 1, 0, id); */
- /* glUniformMatrix4fv(res->uniforms.world, 1, 0, id); */
- /* glUniformMatrix4fv(res->uniforms.normal_matrix, 1, 0, id); */
- /* recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix); */
- /* render_geom(res, geom, GL_TRIANGLES); */
- /* glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); */
- /* render_geom(res, geom, GL_TRIANGLES); */
-}
diff --git a/src/render.h b/src/render.h
@@ -3,8 +3,8 @@
#include "geometry.h"
#include "node.h"
-
-struct game;
+#include "mat4.h"
+#include "util.h"
struct render_config {
int draw_ui;
@@ -14,10 +14,38 @@ struct render_config {
float* depth_vp;
};
-void init_gl(struct resources *resources, int width, int height);
-void render (struct game *game, struct render_config *config);
+void init_gl();
+void recalc_normals(GLint nm_uniform, mat4 *model_view, mat4 *normal);
void wireframe_mode_on();
void wireframe_mode_off();
+static inline void uniform_3f(struct gpu_program *program,
+ enum uniform_id id, const float *v3)
+{
+ glUniform3f(program->uniforms[id].location, v3[0], v3[1], v3[2]);
+ check_gl();
+}
+
+static inline void uniform_1i(struct gpu_program *program,
+ enum uniform_id id, int i)
+{
+ glUniform1i(program->uniforms[id].location, i);
+ check_gl();
+}
+
+static inline void uniform_m4f(struct gpu_program *program,
+ enum uniform_id id, float *m)
+{
+ glUniformMatrix4fv(program->uniforms[id].location, 1, 0, m);
+ check_gl();
+}
+
+static inline void uniform_1f(struct gpu_program *program,
+ enum uniform_id id, float f)
+{
+ glUniform1f(program->uniforms[id].location, f);
+ check_gl();
+}
+
#endif /* POLYADVENT_RENDER_H */
diff --git a/src/scene.c b/src/scene.c
@@ -1,91 +1 @@
-
-#include "game.h"
-#include "model.h"
-#include "procmesh.h"
-#include "debug.h"
-#include "vec3.h"
-#include <assert.h>
-
-void reset_scene(struct game *game) {
- struct entity *terrain_ent = get_terrain_entity(&game->terrain);
- struct entity *player_ent = get_player(&game->test_resources);
-
- destroy_entities();
-
- // hide terrain and player by default
- terrain_ent->flags |= ENT_INVISIBLE;
- player_ent->flags |= ENT_INVISIBLE;
-}
-
-void default_scene(struct game *game) {
- struct terrain *terrain = &game->terrain;
- struct entity *terrain_ent = get_terrain_entity(terrain);
- struct entity *player = get_player(&game->test_resources);
-
- // show terrain
- terrain_ent->flags &= ~ENT_INVISIBLE;
-
- // show player
- player->flags &= ~ENT_INVISIBLE;
-
- struct entity *tower = new_entity(NULL);
- struct node *tnode = get_node(&tower->node_id);
-
- assert(tnode);
- tower->model_id = get_model_by_name("tower", NULL);
- node_set_label(tnode, "tower");
- //node_attach(&tower->node_id, &player->node_id);
- node_translate(tnode, V3(0.0, 50.0, 0.0));
- node_recalc(tnode);
- float z = terrain->fn(terrain, tnode->mat[M_X], tnode->mat[M_Y]);
- /* node_detach(tnode, pnode); */
- tnode->mat[M_Z] = z;
- // END ENTITIES
-
-
-}
-
-
-
-void entity_test_scene(struct game *game)
-{
- struct terrain *terrain = &game->terrain;
-
- struct model_id rock_model;
- init_id(&rock_model.id);
-
- /* model_id rock_model = get_static_model(model_tower, NULL); */
- struct model *pmodel = new_model(&rock_model); assert(pmodel);
- struct geometry *geom = get_geometry(&pmodel->geom_id); assert(geom);
- proc_sphere(geom);
-
- for (int i = 0; i < 200; i++) {
- struct entity *ent = new_entity(NULL);
- struct node *node = get_node(&ent->node_id);
-
- ent->model_id = rock_model;
-
- double x = rand_0to1() * terrain->size;
- double y = rand_0to1() * terrain->size;
- double z = terrain->fn(terrain, x, y);
-
- node_scale(node, pow(15.0, rand_0to1()));
- node_rotate(node, V3(rand_0to1(),rand_0to1(),rand_0to1()));
- node_translate(node, V3(x, y, z));
- node_set_label(node, "rock");
-
- node_recalc(node);
- }
-
-}
-
-void pbr_scene(struct game *game)
-{
- struct entity *ent = new_entity(NULL);
- struct node *node = get_node(&ent->node_id); assert(node);
- struct entity *player = get_player(&game->test_resources);
-
- ent->model_id = get_model_by_name("icosphere", NULL);
- node_set_label(node, "sphere");
-}
diff --git a/src/scene.h b/src/scene.h
@@ -4,10 +4,4 @@
#include "game.h"
-void default_scene(struct game *);
-void reset_scene(struct game *);
-void entity_test_scene(struct game *);
-void pbr_scene(struct game *);
-void chess_scene(struct game *);
-
#endif /* SCENE_H */
diff --git a/src/shader.c b/src/shader.c
@@ -247,7 +247,7 @@ int reload_program(struct gpu_program *program,
time_t new_mtime = file_mtime(shader->includes[j]);
changed |= include_mtime != new_mtime;
}
-
+
changes[i] = changed;
if (changed) {
@@ -336,4 +336,3 @@ int make_program_from_shaders(const char *name, struct shader **shaders,
return 1;
}
-
diff --git a/src/test_game.c b/src/test_game.c
@@ -0,0 +1,779 @@
+#include "debug.h"
+#include "test_game.h"
+#include "camera.h"
+#include "entity.h"
+#include "orbit_util.h"
+#include "game.h"
+#include "node.h"
+#include "render.h"
+#include "quat.h"
+#include "movement.h"
+#include "gpu.h"
+#include "terrain_collision.h"
+#include "orbit_util.h"
+#include "mat_util.h"
+#include "procmesh.h"
+
+static const float bias_matrix[] = {
+ 0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0,
+ 0.5, 0.5, 0.5, 1.0
+};
+
+static void resize_fbos(struct entity *player, struct fbo *shadow_buffer,
+ float *m4_ortho, int width, int height)
+{
+ if (shadow_buffer->handle) {
+ // TODO: remove once delete_fbo deletes attachments
+ glDeleteTextures(1, &shadow_buffer->attachments[1]);
+ glDeleteRenderbuffers(1, &shadow_buffer->attachments[0]);
+ delete_fbo(shadow_buffer);
+ }
+
+ // TODO: compute better bounds based
+ const float factor = 40.5;
+
+ struct model *model = get_model(&player->model_id); assert(model);
+ struct geometry *geom = get_geometry(&model->geom_id); assert(geom);
+
+ float left = geom->min[0] - factor;
+ float right = geom->max[0] + factor;
+ float bottom = geom->min[1] - factor;
+ float top = geom->max[1] + factor;
+
+ /* float left = -factor; */
+ /* float right = factor; */
+ /* float bottom = factor; */
+ /* float top = -factor; */
+
+ const float near = -50.0;
+ const float far = 50.0;
+
+ // default ortho screenspace projection
+ mat4_ortho(left, right, bottom, top, near, far, m4_ortho);
+
+ create_fbo(shadow_buffer, width, height );
+ /* fbo_attach_renderbuffer(&res->shadow_buffer, GL_DEPTH24_STENCIL8, */
+ /* GL_DEPTH_STENCIL_ATTACHMENT); */
+
+ /* fbo_attach_color_texture(&res->shadow_buffer); */
+ fbo_attach_depth_texture(shadow_buffer);
+
+ check_fbo(shadow_buffer);
+
+ /* fbo_attach_texture(&res->shadow_buffer, GL_DEPTH_COMPONENT16, */
+ /* GL_DEPTH_COMPONENT, GL_DEPTH_ATTACHMENT); */
+}
+
+
+static struct entity *get_player(struct test_game *res) {
+ struct entity *player = get_entity(&res->player_id);
+ assert(player);
+ return player;
+}
+
+static struct entity *get_terrain_entity(struct terrain *t) {
+ struct entity *ent = get_entity(&t->entity_id);
+ assert(ent);
+ return ent;
+}
+
+static void player_movement(struct game *engine, struct entity *player) {
+ /* if (player->flags & ENT_ON_GROUND) */
+ /* entity_movement(game, player); */
+ struct node *node = get_node(&player->node_id);
+ movement(engine, node, 2.0);
+}
+
+static void camera_keep_above_ground(struct terrain *terrain,
+ struct node *camera) {
+ if (get_entity(&terrain->entity_id)->flags & ENT_INVISIBLE)
+ return;
+ float move[3];
+ float *camworld = node_world(camera);
+ float pen = 0.0;
+ static const float penlim = 1.0;
+ struct tri *tri = collide_terrain(terrain, camworld, move, &pen);
+
+ if (!tri)
+ return;
+
+ if (pen < penlim) {
+ float dir[3], above[3];
+ vec3_normalize(move, dir);
+ vec3_scale(dir, pen < 0 ? penlim : -penlim, above);
+ vec3_add(camworld, move, camworld);
+ vec3_add(camworld, above, camworld);
+ /* vec3_add(move, above, move); */
+ /* vec3_add(camworld, move, camworld); */
+ }
+}
+
+static void entity_movement(struct game *game, struct entity *ent)
+{
+ static const float move_accel = 1.0f;
+ static const float max_speed = 10.0f;
+ struct node *node = get_node(&ent->node_id);
+
+ float vel[3];
+
+ float amt = 10.0 * game->dt;
+
+ if (game->input.keystates[SDL_SCANCODE_W]) {
+ vec3_forward(ent->velocity, node->orientation, V3(0,amt,0), vel);
+ if (vec3_lengthsq(vel) <= max_speed*max_speed)
+ vec3_copy(vel, ent->velocity);
+ }
+}
+
+
+static void player_terrain_collision(struct terrain *terrain, struct node *node) {
+ // player movement
+ static vec3 last_pos[3] = {0};
+
+ if (!vec3_approxeq(node->pos, last_pos)) {
+ float player_z = node->pos[2];
+
+ float terrain_z =
+ terrain->fn(terrain, node->pos[0], node->pos[1]);
+
+ float inset =
+ min(0.0, player_z - terrain_z);
+
+ if (inset <= 0)
+ node_translate(node, V3(0.0, 0.0, -inset));
+ }
+
+}
+
+// TODO: match based on some real concept of time
+static void day_night_cycle(float time, struct test_game *res) {
+ float val = time * 0.0001;
+ float intensity = 1.0;//max(0.0, vec3_dot(res->light_dir, V3(0.0, 0.0, 1.0))); */
+ struct entity *player = get_player(res);
+ struct node *pnode = get_node(&player->node_id);
+ assert(pnode);
+ struct node *suncam = get_node(&res->sun_camera_id);
+ assert(suncam);
+
+ float light_pos[3];
+
+ float g = 0.6;
+ float b = 0.4;
+ res->sun_color[0] = 1.0;
+ res->sun_color[1] = g+intensity*(1.0-g);
+ res->sun_color[2] = b+intensity*(1.0-b);
+
+ /* res->sun_color[0] = 1.0; */
+ /* res->sun_color[1] = 1.0; */
+ /* res->sun_color[2] = 1.0; */
+
+ /* vec3_scale(res->sun_color, res->light_intensity, gtmp); */
+
+ /* float intensity = angle <= 0.5 */
+ /* ? clamp(roots, darkest, 1.0) */
+ /* : clamp(-roots * 0.4, darkest, 0.5); */
+
+ res->light_intensity = intensity;
+
+ /* 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) + 1.0; */
+ res->light_dir[1] = 0.8;
+ res->light_dir[2] = 0.8;
+
+ vec3_normalize(res->light_dir, res->light_dir);
+
+ /* printf("intensity %f(%f) n %f light_dir %f %f\n", roots, intensity, */
+ /* n, res->light_dir[1], res->light_dir[2]); */
+
+ vec3_add(pnode->pos, res->light_dir, light_pos);
+
+ /* float target[3]; */
+ /* float hh = player->model.geom.max[2] / 2.0; */
+ /* vec3_copy(player->node.pos, target); */
+ /* target[2] += 2.0; */
+
+ look_at(light_pos, pnode->pos, V3(0, 0, 1.0), suncam->mat);
+ /* look_at(light_pos, player->node.pos, V3(0, 0, 1.0), res->sun_camera.mat); */
+}
+
+static void player_update(struct game *engine, struct test_game *game, struct entity *player)
+{
+ struct orbit *camera = &game->orbit_camera;
+ struct node *node = get_node(&player->node_id);
+ struct node *cam_node = get_node(&game->camera_node_id);
+ assert(node);
+ assert(cam_node);
+
+ orbit_update_from_mouse(camera, &engine->input,engine->user_settings.mouse_sens,
+ player, engine->dt);
+
+ camera_keep_above_ground(&game->terrain, cam_node);
+
+ // move player camera toward camera orientation
+ if (input_is_dragging(&engine->input, SDL_BUTTON_RIGHT)) {
+ float yaw = game->orbit_camera.coords.azimuth;
+ quat_axis_angle(V3(0.0, 0.0, 1.0), -yaw - RAD(90), node->orientation);
+ }
+
+ struct terrain *terrain = &game->terrain;
+
+ player_terrain_collision(terrain, node);
+
+ float move[3];
+ float pos[3];
+ float pen = 0.0;
+ vec3_copy(node_world(node), pos);
+ /* debug("node_world(player) %f %f %f\n", pos[0], pos[1], pos[2]); */
+ struct tri *tri = collide_terrain(terrain, pos, move, &pen);
+ //struct tri *tri = NULL;
+ /* node_translate(node, move); */
+
+ if (tri) {
+ if (vec3_eq(move, V3(0,0,0), 0.1)) {
+ player->flags |= ENT_ON_GROUND;
+ }
+ else if (pen < 0) {
+ node_translate(node, move);
+ /* vec3_all(player->velocity, 0); */
+ vec3_scale(player->velocity, 0.1, player->velocity);
+ }
+ else {
+ player->flags &= ~ENT_ON_GROUND;
+ }
+ }
+ else {
+ static int tric = 0;
+ /* debug("%d no tri\n", tric++); */
+ }
+
+ if (player->flags & ENT_ON_GROUND &&
+ (was_key_pressed_this_frame(engine, SDL_SCANCODE_SPACE) /*||
+ was_button_pressed_this_frame(engine, SDL_CONTROLLER_BUTTON_X)*/)) {
+ entity_jump(player, 2.0);
+ }
+
+ /* debug("player velocity %f %f %f\n", */
+ /* player->velocity[0], */
+ /* player->velocity[1], */
+ /* player->velocity[2]); */
+
+// if (player->flags & ENT_AT_REST)
+// vec3_scale(player->velocity, 0.00001, player->velocity);
+
+ node_translate(node, player->velocity);
+ node_recalc(node);
+}
+
+
+void init_test_gl(struct test_game *game, struct gpu *gpu, int width, int height)
+{
+ struct shader vertex, terrain_vertex, chess_piece_vertex, terrain_geom, fragment, fragment_smooth;
+ struct shader terrain_teval, terrain_tc;
+ float tmp_matrix[16];
+ int ok = 0;
+
+
+ // Shaders
+ ok = make_shader(GL_VERTEX_SHADER, SHADER("vertex-color.glsl"),
+ &vertex);
+ rtassert(ok, "vertex-color shader");
+
+ ok = make_shader(GL_VERTEX_SHADER, SHADER("terrain.v.glsl"), &terrain_vertex);
+ rtassert(ok, "terrain vertex shader");
+ check_gl();
+
+ ok = make_shader(GL_VERTEX_SHADER, SHADER("chess-piece.v.glsl"), &chess_piece_vertex);
+ rtassert(ok, "chess-piece vertex shader");
+ check_gl();
+
+ ok = make_shader(GL_FRAGMENT_SHADER, SHADER("main.f.glsl"), &fragment);
+ rtassert(ok, "default fragment shader");
+ check_gl();
+
+ // camera
+ mat4_perspective(90 /* fov */,
+ (float)width / height,
+ 1,
+ 5000,
+ game->proj_persp);
+
+ struct gpu_program *programs = gpu->programs;
+ struct gpu_program *program;
+
+ ok = make_program("terrain", &terrain_vertex, &fragment,
+ &programs[TERRAIN_PROGRAM]);
+ // TODO: replace rtassert with error reporting/handling
+ rtassert(ok, "terrain program");
+ check_gl();
+
+ ok = make_program("vertex-color", &vertex, &fragment, &programs[DEFAULT_PROGRAM]);
+ rtassert(ok, "vertex-color program");
+ check_gl();
+
+ program = &programs[CHESS_PIECE_PROGRAM];
+ ok = make_program("chess-piece", &chess_piece_vertex, &fragment, program);
+ rtassert(ok, "chess-piece program");
+
+ find_uniforms(programs);
+}
+
+
+void init_gpu_programs(struct gpu *gpu)
+{
+}
+
+
+void render_test_game(struct game *game, struct test_game *res, struct render_config *config) {
+ float gtmp[3];
+
+ glEnable(GL_DEPTH_TEST);
+
+ float sky_intensity = clamp(res->light_intensity, 0.2, 1.0);
+ vec3_scale(res->sun_color, sky_intensity, gtmp);
+
+ glClearColor( gtmp[0], gtmp[1], gtmp[2], 1.0 ); //clear background screen to black
+ /* glClearColor( 0.5294f * adjust, 0.8078f * adjust, 0.9216f * adjust, 1.0f ); //clear background screen to black */
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ check_gl();
+
+ static float id[MAT4_ELEMS] = { 0 };
+ static float view[MAT4_ELEMS] = { 0 };
+ static float view_proj[MAT4_ELEMS] = { 0 };
+ static float normal_matrix[MAT4_ELEMS] = { 0 };
+ static float model_view[MAT4_ELEMS] = { 0 };
+ static float depth_mvp[MAT4_ELEMS] = { 0 };
+ mat4_id(id);
+ mat4_id(model_view);
+
+ mat4 *mvp = res->test_mvp;
+ mat4 *projection = config->projection;
+ mat4 *light = res->light_dir;
+
+ struct node *camera_node = get_node(&config->camera);
+ assert(camera_node);
+
+ const mat4 *camera = camera_node->mat;
+ u32 num_entities;
+
+ struct entity *entities =
+ get_all_entities(&num_entities, NULL);
+
+ struct gpu_program *program = NULL;
+
+ mat4_inverse((float*)camera, view);
+ mat4_multiply(projection, view, view_proj);
+
+ if (config->is_depth_pass) {
+ glDisable(GL_CULL_FACE);
+ mat4_multiply(bias_matrix, view_proj, config->depth_vp);
+ }
+ else {
+ glCullFace(GL_BACK);
+ }
+
+ mat4_inverse((float *)camera, view);
+ mat4_multiply(projection, view, view_proj);
+
+ struct model *skybox_model = get_model(&res->skybox.model_id);
+ assert(skybox_model);
+
+ glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_model->texture);
+ check_gl();
+
+ for (u32 i = 0; i < num_entities; ++i) {
+ struct entity *entity = &entities[i];
+ struct model *model = get_model(&entity->model_id);
+ assert(model);
+ struct node *node = get_node(&entity->node_id);
+ assert(node);
+
+ if (entity->flags & ENT_INVISIBLE)
+ continue;
+
+ if (config->is_depth_pass && !(entity->flags & ENT_CASTS_SHADOWS))
+ continue;
+
+ program = &game->gpu.programs[model->shader];
+
+ glUseProgram(program->handle);
+ check_gl();
+
+ uniform_3f(program, UNIFORM_CAMERA_POSITION, &camera[M_X]);
+
+ if (model->shader == CHESS_PIECE_PROGRAM) {
+ uniform_1i(program, UNIFORM_IS_WHITE,
+ (entity->flags & ENT_IS_WHITE) == ENT_IS_WHITE);
+ }
+
+ uniform_1i(program, UNIFORM_FOG_ON, res->fog_on);
+ uniform_3f(program, UNIFORM_LIGHT_DIR, light);
+ uniform_1f(program, UNIFORM_LIGHT_INTENSITY, res->light_intensity);
+ uniform_1f(program, UNIFORM_SKY_INTENSITY, sky_intensity);
+ uniform_3f(program, UNIFORM_SUN_COLOR, res->sun_color);
+
+ mat4_multiply(view_proj, node->mat, mvp);
+ mat4_copy(node->mat, model_view);
+ mat4_multiply(config->depth_vp, model_view, depth_mvp);
+ uniform_m4f(program, UNIFORM_DEPTH_MVP, depth_mvp);
+ uniform_m4f(program, UNIFORM_MVP, mvp);
+ uniform_m4f(program, UNIFORM_MODEL, node->mat);
+
+ recalc_normals(program->uniforms[UNIFORM_NORMAL_MATRIX].location,
+ model_view, normal_matrix);
+ check_gl();
+
+ struct geometry *geo = get_geometry(&model->geom_id);
+ /* debug("geo node %s\n", node->label); */
+ assert(geo);
+ render_geometry(geo, program->vertex_attrs, program);
+ check_gl();
+ }
+
+ if (game->wireframe) {
+ glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+ }
+ else {
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+ }
+
+ if (!config->is_depth_pass) {
+ mat4_inverse((float*)camera, view);
+ mat4_remove_translations(view);
+ mat4_multiply(projection, view, view_proj);
+
+ render_skybox(&res->skybox, view_proj);
+ }
+
+ if (config->draw_ui)
+ render_ui(&game->ui, view);
+
+ //player
+ // y tho
+
+ // terrain
+
+ /* glUniformMatrix4fv(res->uniforms.mvp, 1, 0, mvp); */
+ /* glUniformMatrix4fv(res->uniforms.model_view, 1, 0, id); */
+ /* glUniformMatrix4fv(res->uniforms.world, 1, 0, id); */
+ /* glUniformMatrix4fv(res->uniforms.normal_matrix, 1, 0, id); */
+ /* recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix); */
+ /* render_geom(res, geom, GL_TRIANGLES); */
+ /* glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); */
+ /* render_geom(res, geom, GL_TRIANGLES); */
+}
+
+
+void update_test_game (struct game *engine, struct test_game *game) {
+ static int toggle_fog = 0;
+ static int needs_terrain_update = 0;
+ //struct terrain *terrain = &game->terrain;
+ struct node *root = get_node(&game->root_id);
+ struct entity *player = get_player(game);
+ struct node *pnode = get_node(&player->node_id);
+ struct node *cam_node = get_node(&game->camera_node_id);
+
+ assert(pnode);
+ assert(cam_node);
+
+ float *time = &game->time;
+ float *light = game->light_dir;
+
+ gravity(player, engine->dt);
+
+ if (needs_terrain_update) {
+ /* update_terrain(terrain); */
+ needs_terrain_update = 0;
+ }
+
+ /* spherical_dir(game->test_resources.camera.coords, camera_dir); */
+ /* vec3_scale(camera_dir, -1, camera_dir); */
+
+ if (engine->input.modifiers & KMOD_ALT &&
+ ideq(&game->camera_node_id, &game->free_camera_id))
+ {
+ struct node *freecam_node = get_node(&game->free_camera_id);
+ assert(freecam_node);
+ assert(streq(freecam_node->label, "freecam"));
+ movement(engine, freecam_node, 1.0);
+ } else {
+ player_movement(engine, player);
+ }
+
+ assert(root->parent_id.generation == 0);
+
+ player_update(engine, game, player);
+
+#ifdef DEBUG
+ if (was_key_pressed_this_frame(engine, SDL_SCANCODE_R))
+ try_reload_shaders(&engine->gpu);
+#endif
+
+ if (was_key_pressed_this_frame(engine, SDL_SCANCODE_F5)) {
+ engine->wireframe ^= 1;
+ }
+
+ if (was_key_pressed_this_frame(engine, SDL_SCANCODE_C)) {
+ printf("light_dir %f %f %f\n", light[0], light[1], light[2]);
+ }
+
+ if (was_key_pressed_this_frame(engine, SDL_SCANCODE_F)) {
+ toggle_fog = 1;
+ }
+
+ if (was_key_pressed_this_frame(engine, SDL_SCANCODE_EQUALS)) {
+ if (!ideq(&game->camera_node_id, &game->free_camera_id)) {
+ debug("switching to freecam\n");
+ game->camera_node_id = game->free_camera_id;
+ }
+ else {
+ debug("switching to orbitcam\n");
+ game->camera_node_id = game->orbit_camera.node_id;
+ }
+ }
+
+ if (toggle_fog) {
+ game->fog_on = !game->fog_on;
+ toggle_fog = 0;
+ }
+
+ *time = SDL_GetTicks();
+
+ day_night_cycle(*time, game);
+
+ node_recalc(root);
+}
+
+void test_game_frame(struct game *engine, struct test_game *game)
+{
+ static float depth_vp[MAT4_ELEMS];
+ mat4_id(depth_vp);
+
+ struct render_config fbo_render_config = {
+ .draw_ui = 0,
+ .is_depth_pass = 1,
+ .camera = game->sun_camera_id,
+ .projection = game->proj_ortho,
+ .depth_vp = depth_vp
+ };
+
+ struct render_config default_config = {
+ .draw_ui = 0,
+ .is_depth_pass = 0,
+ .camera = game->camera_node_id,
+ .projection = game->proj_persp,
+ .depth_vp = depth_vp
+ };
+
+ struct entity *player = get_entity(&game->player_id);
+ if (engine->input.resized_height) {
+ mat4_perspective(60 /* fov */,
+ (float)engine->width / (float)engine->height, 0.1,
+ 10000.0, game->proj_persp);
+
+ resize_fbos(player, &game->shadow_buffer, game->proj_ortho,
+ engine->width, engine->height);
+ }
+
+ update_test_game(engine, game);
+
+ struct fbo *fbo = &game->shadow_buffer;
+ check_fbo(fbo);
+ bind_fbo(fbo);
+ /* glDrawBuffer(GL_NONE); */
+
+ render_test_game(engine, game, &fbo_render_config);
+ unbind_fbo(&game->shadow_buffer);
+ render_test_game(engine, game, &default_config);
+}
+
+void init_test_game(struct test_game *game, struct gpu *gpu, int width, int height)
+{
+ memset(game, 0, sizeof(*game));
+ struct terrain *terrain = &game->terrain;
+ struct entity *player;
+
+ init_test_gl(game, gpu, width, height);
+
+ mat4 *mvp = game->test_mvp;
+ mat4 *light_dir = game->light_dir;
+
+ init_id(&game->root_id);
+ init_id(&game->sun_camera_id);
+ init_id(&game->free_camera_id);
+
+ struct node *root = new_node(&game->root_id);
+ struct node *sun_camera = new_node(&game->sun_camera_id);
+
+ assert(root->parent_id.generation == 0);
+ assert(root);
+ assert(sun_camera);
+
+ const double size = 4000.0;
+ //double scale = 0.03;
+ double scale = 0.03;
+
+ create_skybox(&game->skybox, &gpu->programs[SKYBOX_PROGRAM]);
+
+ terrain->settings = (struct perlin_settings){
+ .depth = 1,
+ .freq = scale * 0.08,
+ .o1 = 2.0, .o1s = 0.5,
+ .o2 = 4.0, .o2s = 0.25,
+ .amplitude = 70.0,
+ .ox = 0,
+ .oy = 0,
+ .exp = 5.3,
+ .scale = scale
+ };
+
+ init_terrain(terrain, size);
+
+ /* terrain->samples = load_samples(&seed, &terrain->n_samples); */
+ terrain->n_samples = 0;
+ //create_terrain(terrain, size, game->seed);
+ load_terrain(terrain);
+ /* update_terrain(terrain, terrain->cell_size); */
+ /* get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE; */
+
+ /* node_scale(&game->skybox.node, size/4.0); */
+
+ mat4_id(mvp);
+
+ game->time = 0;
+ game->light_intensity = 0.8;
+
+ light_dir[0] = 0.8;
+ light_dir[1] = 0.8;
+ light_dir[2] = 0.8;
+
+ game->piece_color[0] = 1.0;
+ game->piece_color[1] = 1.0;
+ game->piece_color[2] = 1.0;
+
+ game->sun_color[0] = 0.5;
+ game->sun_color[1] = 0.6;
+ game->sun_color[2] = 0.7;
+
+ game->fog_on = 0;
+ game->diffuse_on = 0;
+
+ node_init(root);
+ node_init(sun_camera);
+ new_orbit(&game->orbit_camera);
+
+ node_set_label(root, "root");
+
+ // ENTITIES
+
+ // player entity
+ init_id(&game->player_id);
+ player = new_entity(&game->player_id);
+ player->flags |= ENT_CASTS_SHADOWS;
+ struct node *pnode = get_node(&player->node_id);
+ assert(pnode);
+
+ player->model_id = get_model_by_name("pirate_officer", NULL);
+ assert(!is_null_id(&player->model_id.id));
+
+ node_set_label(pnode, "player");
+ /* node_rotate(pnode, V3(-5.0,0,0)); */
+ node_attach(&player->node_id, &game->root_id);
+ assert(ideq(&pnode->parent_id, &game->root_id));
+
+ node_translate(pnode, V3(terrain->size/2.,terrain->size/2.,0.0));
+
+ // orbit camera
+ game->orbit_camera.coords.azimuth = -quat_yaw(pnode->orientation) - RAD(90.0);
+ game->orbit_camera.coords.inclination = RAD(60);
+ game->orbit_camera.coords.radius = 5.0;
+ game->camera_node_id = game->orbit_camera.node_id;
+
+ // free camera
+ struct node *freecam = new_node(&game->free_camera_id);
+ node_set_label(freecam, "freecam");
+ node_attach(&game->free_camera_id, &player->node_id);
+ quat_axis_angle(V3(1,0,0), -45, freecam->orientation);
+ node_rotate(freecam, V3(100, 0, 0));
+ node_translate(freecam, V3(0,-40,20));
+
+ // FBO STUFF
+ init_fbo(&game->shadow_buffer);
+ resize_fbos(player, &game->shadow_buffer, game->proj_ortho, width, height);
+ // FBO STUFF END
+
+ // TEXTURES
+ // END TEXTURES
+}
+
+void default_scene(struct test_game *game) {
+ struct terrain *terrain = &game->terrain;
+ struct entity *terrain_ent = get_terrain_entity(terrain);
+ struct entity *player = get_player(game);
+
+ // show terrain
+ terrain_ent->flags &= ~ENT_INVISIBLE;
+
+ // show player
+ player->flags &= ~ENT_INVISIBLE;
+
+ struct entity *tower = new_entity(NULL);
+ struct node *tnode = get_node(&tower->node_id);
+
+ assert(tnode);
+ tower->model_id = get_model_by_name("tower", NULL);
+ node_set_label(tnode, "tower");
+ //node_attach(&tower->node_id, &player->node_id);
+ node_translate(tnode, V3(0.0, 50.0, 0.0));
+ node_recalc(tnode);
+ float z = terrain->fn(terrain, tnode->mat[M_X], tnode->mat[M_Y]);
+ /* node_detach(tnode, pnode); */
+ tnode->mat[M_Z] = z;
+}
+
+
+
+void entity_test_scene(struct terrain *terrain)
+{
+ struct model_id rock_model;
+ init_id(&rock_model.id);
+
+ /* model_id rock_model = get_static_model(model_tower, NULL); */
+ struct model *pmodel = new_model(&rock_model); assert(pmodel);
+ struct geometry *geom = get_geometry(&pmodel->geom_id); assert(geom);
+ proc_sphere(geom);
+
+ for (int i = 0; i < 200; i++) {
+ struct entity *ent = new_entity(NULL);
+ struct node *node = get_node(&ent->node_id);
+
+ ent->model_id = rock_model;
+
+ double x = rand_0to1() * terrain->size;
+ double y = rand_0to1() * terrain->size;
+ double z = terrain->fn(terrain, x, y);
+
+ node_scale(node, pow(15.0, rand_0to1()));
+ node_rotate(node, V3(rand_0to1(),rand_0to1(),rand_0to1()));
+ node_translate(node, V3(x, y, z));
+ node_set_label(node, "rock");
+
+ node_recalc(node);
+ }
+
+}
+
+void pbr_scene(struct test_game *game)
+{
+ struct entity *ent = new_entity(NULL);
+ struct node *node = get_node(&ent->node_id); assert(node);
+ struct entity *player = get_player(game);
+
+ ent->model_id = get_model_by_name("icosphere", NULL);
+ node_set_label(node, "sphere");
+}
diff --git a/src/test_game.h b/src/test_game.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "render.h"
+#include "terrain.h"
+#include "vbo.h"
+#include "fbo.h"
+#include "geometry.h"
+#include "skybox.h"
+#include "orbit.h"
+#include "gpu.h"
+#include "game.h"
+
+struct test_game {
+ struct terrain terrain;
+ struct vbo vertex_buffer, element_buffer, normal_buffer;
+ struct fbo shadow_buffer;
+
+ node_id root_id;
+ entity_id player_id;
+ struct geometry qh_test;
+ struct orbit orbit_camera;
+ node_id free_camera_id;
+ node_id camera_node_id;
+ node_id sun_camera_id;
+
+ u32 test_cubemap;
+ float time;
+ bool fog_on, diffuse_on;
+
+ struct skybox skybox;
+ float sun_color[3];
+ float piece_color[3];
+ float test_mvp[MAT4_ELEMS];
+ float light_dir[3];
+ float light_intensity;
+ float proj_persp[MAT4_ELEMS];
+ float proj_ortho[MAT4_ELEMS];
+};
+
+
+void init_test_gl(struct test_game *game, struct gpu *gpu, int width, int height);
+void render_test_game(struct game *engine, struct test_game *game, struct render_config *config);
+void init_test_game(struct test_game *game, struct gpu *gpu, int width, int height);
+void test_game_frame(struct game *engine, struct test_game *game);
+
+void default_scene(struct test_game *);
+void entity_test_scene(struct terrain *);
+void pbr_scene(struct test_game *);
+void chess_scene(struct test_game *);
+
diff --git a/src/update.c b/src/update.c
@@ -17,93 +17,6 @@
#include <math.h>
-static void entity_movement(struct game *game, struct entity *ent)
-{
- static const float move_accel = 1.0f;
- static const float max_speed = 10.0f;
- struct node *node = get_node(&ent->node_id);
-
- float vel[3];
-
- float amt = 10.0 * game->dt;
-
- if (game->input.keystates[SDL_SCANCODE_W]) {
- vec3_forward(ent->velocity, node->orientation, V3(0,amt,0), vel);
- if (vec3_lengthsq(vel) <= max_speed*max_speed)
- vec3_copy(vel, ent->velocity);
- }
-}
-
-static void movement(struct game *game, struct node *node, float speed_mult)
-{
- float amt = 3.0 * game->dt;
- float turn = 1.0 * game->dt;
-
- float x_axis = (float)game->input.axis[0] / (float)MAX_AXIS_VALUE;
- float y_axis = (float)game->input.axis[1] / (float)MAX_AXIS_VALUE;
-
- amt *= speed_mult;
-
- if ((game->input.modifiers & KMOD_SHIFT) /*||
- is_button_down(&game->input, SDL_CONTROLLER_BUTTON_LEFTSTICK)*/)
- {
- amt *= 20;
- }
-
- // joystick movement
- node_forward(node, V3(0,amt*y_axis, 0));
- node_forward(node, V3(amt*x_axis, 0, 0));
-
-
- if (game->input.keystates[SDL_SCANCODE_A])
- node_forward(node, V3(-amt,0,0));
-
- if (game->input.keystates[SDL_SCANCODE_UP])
- node_forward(node, V3(0,0,amt));
-
- if (game->input.keystates[SDL_SCANCODE_DOWN])
- node_forward(node, V3(0,0,-amt));
-
- if (game->input.keystates[SDL_SCANCODE_D])
- node_forward(node, V3(amt,0,0));
-
- if (game->input.keystates[SDL_SCANCODE_W])
- node_forward(node, V3(0,amt,0));
-
- if (game->input.keystates[SDL_SCANCODE_S])
- node_forward(node, V3(0,-amt,0));
-
- if (game->input.keystates[SDL_SCANCODE_K])
- node_forward(node, V3(0, 0,amt));
-
- if (game->input.keystates[SDL_SCANCODE_J])
- node_forward(node, V3(0, 0,-amt));
-
- if (game->input.keystates[SDL_SCANCODE_E])
- node_rotate(node, V3(0, 0, turn));
-
- if (game->input.keystates[SDL_SCANCODE_Q])
- node_rotate(node, V3(0, 0, -turn));
-
- /* if (game->input.keystates[SDL_SCANCODE_DOWN]) */
- /* node_translate(node, V3(0, 0, -amt)); */
-
- if (was_key_pressed_this_frame(game, SDL_SCANCODE_P)) {
- debug("player %f %f %f quat %f %f %f %f\n",
- node->pos[0],
- node->pos[1],
- node->pos[2],
- node->orientation[0],
- node->orientation[1],
- node->orientation[2],
- node->orientation[3]
- );
- struct spherical *cam = &game->test_resources.orbit_camera.coords;
- debug("camera settings radius %f inc %f azimuth %f\n",
- cam->radius, cam->inclination, cam->azimuth);
- }
-}
-
static void remap_samples(struct point *points, int n_samples,
double size)
{
@@ -125,408 +38,3 @@ static void remap_samples(struct point *points, int n_samples,
}
}
-static void player_terrain_collision(struct terrain *terrain, struct node *node) {
- // player movement
- static vec3 last_pos[3] = {0};
-
- if (!vec3_approxeq(node->pos, last_pos)) {
- float player_z = node->pos[2];
-
- float terrain_z =
- terrain->fn(terrain, node->pos[0], node->pos[1]);
-
- float inset =
- min(0.0, player_z - terrain_z);
-
- if (inset <= 0)
- node_translate(node, V3(0.0, 0.0, -inset));
- }
-
-}
-
-static void player_movement(struct game *game, struct entity *player) {
- /* if (player->flags & ENT_ON_GROUND) */
- /* entity_movement(game, player); */
- struct node *node = get_node(&player->node_id);
- movement(game, node, 2.0);
-}
-
-
-#ifdef DEBUG
-static int try_reload_shaders(struct resources *res) {
- int ret;
- for (int i = 0; i < NUM_PROGRAMS; ++i) {
- struct gpu_program *program = &res->programs[i];
- ret = reload_program(program, res->programs);
-
- if (ret == 2) {}
- else if (ret == 1)
- printf("reload %s success.\n", program->shaders[0].filename);
- else
- printf("reload %s failed.\n", program->shaders[0].filename);
-
- // failure ok, clear any errors
- glGetError();
- }
-
-
-
-
- return ret;
-}
-#endif
-
-void resize_fbos(struct entity *player, struct fbo *shadow_buffer,
- float *m4_ortho, int width, int height)
-{
- if (shadow_buffer->handle) {
- // TODO: remove once delete_fbo deletes attachments
- glDeleteTextures(1, &shadow_buffer->attachments[1]);
- glDeleteRenderbuffers(1, &shadow_buffer->attachments[0]);
- delete_fbo(shadow_buffer);
- }
-
- // TODO: compute better bounds based
- const float factor = 40.5;
-
- struct model *model = get_model(&player->model_id); assert(model);
- struct geometry *geom = get_geometry(&model->geom_id); assert(geom);
-
- float left = geom->min[0] - factor;
- float right = geom->max[0] + factor;
- float bottom = geom->min[1] - factor;
- float top = geom->max[1] + factor;
-
- /* float left = -factor; */
- /* float right = factor; */
- /* float bottom = factor; */
- /* float top = -factor; */
-
- const float near = -50.0;
- const float far = 50.0;
-
- // default ortho screenspace projection
- mat4_ortho(left, right, bottom, top, near, far, m4_ortho);
-
- create_fbo(shadow_buffer, width, height );
- /* fbo_attach_renderbuffer(&res->shadow_buffer, GL_DEPTH24_STENCIL8, */
- /* GL_DEPTH_STENCIL_ATTACHMENT); */
-
- /* fbo_attach_color_texture(&res->shadow_buffer); */
- fbo_attach_depth_texture(shadow_buffer);
-
- check_fbo(shadow_buffer);
-
- /* fbo_attach_texture(&res->shadow_buffer, GL_DEPTH_COMPONENT16, */
- /* GL_DEPTH_COMPONENT, GL_DEPTH_ATTACHMENT); */
-
-}
-
-// TODO: match based on some real concept of time
-static void day_night_cycle(float time, struct resources *res) {
- float val = time * 0.0001;
- float intensity = 1.0;//max(0.0, vec3_dot(res->light_dir, V3(0.0, 0.0, 1.0))); */
- struct entity *player = get_player(res);
- struct node *pnode = get_node(&player->node_id);
- assert(pnode);
- struct node *suncam = get_node(&res->sun_camera_id);
- assert(suncam);
-
- float light_pos[3];
-
- float g = 0.6;
- float b = 0.4;
- res->sun_color[0] = 1.0;
- res->sun_color[1] = g+intensity*(1.0-g);
- res->sun_color[2] = b+intensity*(1.0-b);
-
- /* res->sun_color[0] = 1.0; */
- /* res->sun_color[1] = 1.0; */
- /* res->sun_color[2] = 1.0; */
-
- /* vec3_scale(res->sun_color, res->light_intensity, gtmp); */
-
- /* float intensity = angle <= 0.5 */
- /* ? clamp(roots, darkest, 1.0) */
- /* : clamp(-roots * 0.4, darkest, 0.5); */
-
- res->light_intensity = intensity;
-
- /* 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) + 1.0; */
- res->light_dir[1] = 0.8;
- res->light_dir[2] = 0.8;
-
- vec3_normalize(res->light_dir, res->light_dir);
-
- /* printf("intensity %f(%f) n %f light_dir %f %f\n", roots, intensity, */
- /* n, res->light_dir[1], res->light_dir[2]); */
-
- vec3_add(pnode->pos, res->light_dir, light_pos);
-
- /* float target[3]; */
- /* float hh = player->model.geom.max[2] / 2.0; */
- /* vec3_copy(player->node.pos, target); */
- /* target[2] += 2.0; */
-
- look_at(light_pos, pnode->pos, V3(0, 0, 1.0), suncam->mat);
- /* look_at(light_pos, player->node.pos, V3(0, 0, 1.0), res->sun_camera.mat); */
-}
-
-static void gravity(struct game *game) {
- struct entity *player = get_player(&game->test_resources);
-
- if (player->flags & ENT_ON_GROUND)
- return;
-
- struct node *pnode = get_node(&player->node_id);
- assert(pnode);
-
- static const float g = -1.0;
- vec3_add(player->velocity, V3(0.0, 0.0, g * game->dt), player->velocity);
-}
-
-void orbit_update_from_mouse(struct orbit *camera, struct input *input,
- float mouse_sens, struct entity *player,
- float dt)
-{
- float target[3];
- struct node *target_node = get_node(&player->node_id);
- struct node *cam_node = get_node(&camera->node_id);
- struct model *pmodel = get_model(&player->model_id); assert(pmodel);
- struct geometry *player_geom = get_geometry(&pmodel->geom_id); assert(player_geom);
-
- assert(target_node);
- assert(cam_node);
-
- node_recalc(target_node);
- vec3_copy(node_world(target_node), target);
- assert(player_geom->max[2] != 0);
- vec3_add(target, V3(0.0, 0.0, player_geom->max[2]), target);
- /* vec3_add(target, V3(0.0, 0.0, 10.0), target); */
-
- float mx = 0.0, my = 0.0;
- if (input_is_dragging(input, SDL_BUTTON_LEFT) ||
- input_is_dragging(input, SDL_BUTTON_RIGHT)) {
- mx = -input->mdx * mouse_sens * dt;
- my = -input->mdy * mouse_sens * dt;
- }
-
- // zoom
- if (input->keystates[SDL_SCANCODE_V]) {
- if (input->modifiers & KMOD_SHIFT)
- camera->coords.radius += dt * 100.0;
- else
- camera->coords.radius -= dt * 100.0;
-
- }
- else if (input->wheel_y) {
- camera->coords.radius += input->wheel_y * dt * 100.0;
- }
-
- camera->coords.radius = max(1.0, camera->coords.radius);
-
- camera->coords.azimuth += mx;
- camera->coords.inclination += my;
-
- /*
- printf("coords azimuth %f inclination %f radius %f\n",
- camera->coords.azimuth,
- camera->coords.inclination,
- camera->coords.radius);
- */
-
- spherical_look_at(&camera->coords, target, cam_node->mat);
-
-}
-
-static void camera_keep_above_ground(struct terrain *terrain,
- struct node *camera) {
- if (get_entity(&terrain->entity_id)->flags & ENT_INVISIBLE)
- return;
- float move[3];
- float *camworld = node_world(camera);
- float pen = 0.0;
- static const float penlim = 1.0;
- struct tri *tri = collide_terrain(terrain, camworld, move, &pen);
-
- if (!tri)
- return;
-
- if (pen < penlim) {
- float dir[3], above[3];
- vec3_normalize(move, dir);
- vec3_scale(dir, pen < 0 ? penlim : -penlim, above);
- vec3_add(camworld, move, camworld);
- vec3_add(camworld, above, camworld);
- /* vec3_add(move, above, move); */
- /* vec3_add(camworld, move, camworld); */
- }
-}
-
-static void entity_jump(struct entity *ent, float amount)
-{
- float dir[3];
- debug("jumping\n");
- vec3_normalize(ent->velocity, dir);
- vec3_add(dir, V3(0, 0, amount), dir);
- vec3_add(ent->velocity, dir, ent->velocity);
-}
-
-static void player_update(struct game *game, struct entity *player)
-{
-
- struct resources *res = &game->test_resources;
- struct orbit *camera = &res->orbit_camera;
- struct node *node = get_node(&player->node_id);
- struct node *cam_node = get_node(&res->camera_node_id);
- assert(node);
- assert(cam_node);
-
- orbit_update_from_mouse(camera, &game->input, game->user_settings.mouse_sens,
- player, game->dt);
-
- //camera_keep_above_ground(&game->terrain, cam_node);
-
- // move player camera toward camera orientation
- if (input_is_dragging(&game->input, SDL_BUTTON_RIGHT)) {
- float yaw = game->test_resources.orbit_camera.coords.azimuth;
- quat_axis_angle(V3(0.0, 0.0, 1.0), -yaw - RAD(90), node->orientation);
- }
-
- struct terrain *terrain = &game->terrain;
-
- /* player_terrain_collision(terrain, node); */
-
- float move[3];
- float pos[3];
- float pen = 0.0;
- vec3_copy(node_world(node), pos);
- /* debug("node_world(player) %f %f %f\n", pos[0], pos[1], pos[2]); */
- //struct tri *tri = collide_terrain(terrain, pos, move, &pen);
- struct tri *tri = NULL;
- /* node_translate(node, move); */
-
- if (tri) {
- if (vec3_eq(move, V3(0,0,0), 0.1)) {
- player->flags |= ENT_ON_GROUND;
- }
- else if (pen < 0) {
- node_translate(node, move);
- /* vec3_all(player->velocity, 0); */
- //vec3_scale(player->velocity, 0.1, player->velocity);
- }
- else {
- player->flags &= ~ENT_ON_GROUND;
- }
- }
- else {
- static int tric = 0;
- /* debug("%d no tri\n", tric++); */
- }
-
- if (player->flags & ENT_ON_GROUND &&
- (was_key_pressed_this_frame(game, SDL_SCANCODE_SPACE) /*||
- was_button_pressed_this_frame(game, SDL_CONTROLLER_BUTTON_X)*/)) {
- entity_jump(player, 2.0);
- }
-
- /* debug("player velocity %f %f %f\n", */
- /* player->velocity[0], */
- /* player->velocity[1], */
- /* player->velocity[2]); */
-
-// if (player->flags & ENT_AT_REST)
-// vec3_scale(player->velocity, 0.00001, player->velocity);
-
- node_translate(node, player->velocity);
- node_recalc(node);
-}
-
-
-
-void update (struct game *game) {
- static int toggle_fog = 0;
- static int needs_terrain_update = 0;
- struct resources *res = &game->test_resources;
- /* struct terrain *terrain = &game->terrain; */
- struct node *root = get_node(&game->test_resources.root_id);
- struct entity *player = get_player(res);
- struct node *pnode = get_node(&player->node_id);
- struct node *cam_node = get_node(&res->camera_node_id);
-
- assert(pnode);
- assert(cam_node);
-
- float *time = &res->time;
- float *light = res->light_dir;
-
- //gravity(game);
-
- if (needs_terrain_update) {
- /* update_terrain(terrain); */
- needs_terrain_update = 0;
- }
-
- /* spherical_dir(game->test_resources.camera.coords, camera_dir); */
- /* vec3_scale(camera_dir, -1, camera_dir); */
-
- if (game->input.modifiers & KMOD_ALT &&
- ideq(&res->camera_node_id, &res->free_camera_id))
- {
- struct node *freecam_node = get_node(&res->free_camera_id);
- assert(freecam_node);
- assert(streq(freecam_node->label, "freecam"));
- movement(game, freecam_node, 1.0);
- }
- else {
- player_movement(game, player);
- }
-
- assert(root->parent_id.generation == 0);
-
- player_update(game, player);
-
-#ifdef DEBUG
- if (was_key_pressed_this_frame(game, SDL_SCANCODE_R))
- try_reload_shaders(res);
-#endif
-
- if (was_key_pressed_this_frame(game, SDL_SCANCODE_F5)) {
- game->wireframe ^= 1;
- }
-
- if (was_key_pressed_this_frame(game, SDL_SCANCODE_C)) {
- printf("light_dir %f %f %f\n", light[0], light[1], light[2]);
- }
-
- if (was_key_pressed_this_frame(game, SDL_SCANCODE_F))
- toggle_fog = 1;
-
- if (was_key_pressed_this_frame(game, SDL_SCANCODE_EQUALS)) {
- if (!ideq(&res->camera_node_id, &res->free_camera_id)) {
- debug("switching to freecam\n");
- res->camera_node_id = res->free_camera_id;
- }
- else {
- debug("switching to orbitcam\n");
- res->camera_node_id = res->orbit_camera.node_id;
- }
- }
-
- if (toggle_fog) {
- res->fog_on = !res->fog_on;
- toggle_fog = 0;
- }
-
- /* for (int i = 0; i < ) */
-
- *time = SDL_GetTicks();
-
- day_night_cycle(*time, res);
-
- node_recalc(root);
-}
diff --git a/src/update.h b/src/update.h
@@ -5,7 +5,10 @@
#include "game.h"
void update(struct game * game);
+void gravity(struct entity *ent, float dt);
void resize_fbos(struct entity *player, struct fbo *shadow_buffer,
float *mat4_ortho, int width, int height);
+void entity_jump(struct entity *ent, float amount);
+
#endif /* PA_UPDATE_H */
diff --git a/src/util.h b/src/util.h
@@ -7,6 +7,7 @@
#include "mat4.h"
#include <assert.h>
#include <string.h>
+#include <stdio.h>
#define check_gl() { \
unsigned int e = glGetError(); \
diff --git a/src/window.c b/src/window.c
@@ -7,17 +7,11 @@
#include "update.h"
-void
-handle_resize(struct game *game, int width, int height) {
+void handle_resize(struct game *game, int width, int height) {
/* printf("resizing %d %d\n", width, height); */
glViewport( 0, 0, width, height );
- mat4_perspective(60 /* fov */, (float)width / height, 0.1, 10000.0,
- game->test_resources.proj_persp);
-
- resize_fbos(get_entity(&game->test_resources.player_id),
- &game->test_resources.shadow_buffer,
- game->test_resources.proj_ortho,
- width, height);
+ game->width = width;
+ game->height = height;
/* glMatrixMode( GL_PROJECTION ); //Switch to setting the camera perspective */
/* Set the camera perspective */
diff --git a/test/test_scene.c b/test/test_scene.c
@@ -63,7 +63,8 @@ int scene_tests(struct game *game) {
t_assert(node_count(root) == initial_node_count,
"scene: node count doesn't match initial after reset_scene");
- entity_test_scene(game);
+ struct terrain *terrain = NULL;
+ entity_test_scene(game, terrain);
get_all_entities(&ent_count, NULL);
/* assert(ent_count == 102); */