polyadvent

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

test_game.c (21338B)


      1 #include "debug.h"
      2 #include "test_game.h"
      3 #include "camera.h"
      4 #include "entity.h"
      5 #include "orbit_util.h"
      6 #include "engine.h"
      7 #include "node.h"
      8 #include "render.h"
      9 #include "shader.h"
     10 #include "quat.h"
     11 #include "movement.h"
     12 #include "gpu.h"
     13 #include "util.h"
     14 #include "terrain_collision.h"
     15 #include "orbit_util.h"
     16 #include "mat_util.h"
     17 #include "procmesh.h"
     18 
     19 static const float bias_matrix[] = {
     20   0.5, 0.0, 0.0, 0.0,
     21   0.0, 0.5, 0.0, 0.0,
     22   0.0, 0.0, 0.5, 0.0,
     23   0.5, 0.5, 0.5, 1.0
     24 };
     25 
     26 #define CU_LENS(field, typ) { #field, offsetof(struct common_uniforms, field), DATA_ID_##typ }
     27 static struct lens common_lenses[] = {
     28 	CU_LENS(fog_on, INT),
     29 	CU_LENS(sky_intensity, FLOAT),
     30 	CU_LENS(light_intensity, FLOAT),
     31 	CU_LENS(depth_mvp, MAT4),
     32 	CU_LENS(mvp, MAT4),
     33 	CU_LENS(model_view, MAT4),
     34 	CU_LENS(normal_matrix, MAT4),
     35 	CU_LENS(sun_color, VEC3),
     36 	CU_LENS(camera_position, VEC3P),
     37 	CU_LENS(light_dir, VEC3),
     38 };
     39 #undef CU_LENS
     40 
     41 struct lens *get_common_lenses()
     42 {
     43 	return common_lenses;
     44 }
     45 
     46 int get_common_lenses_length()
     47 {
     48 	return ARRAY_SIZE(common_lenses);
     49 }
     50 
     51 static void resize_fbos(struct entity *player, struct fbo *shadow_buffer,
     52 				 float *m4_ortho, int width, int height)
     53 {
     54 	if (shadow_buffer->handle) {
     55 		// TODO: remove once delete_fbo deletes attachments
     56 		glDeleteTextures(1, &shadow_buffer->attachments[1]);
     57 		glDeleteRenderbuffers(1, &shadow_buffer->attachments[0]);
     58 		delete_fbo(shadow_buffer);
     59 	}
     60 
     61 	// TODO: compute better bounds based
     62 	const float factor = 60.5;
     63 
     64 	struct model *model   = get_model(&player->model_id); assert(model);
     65 	struct geometry *geom = get_geometry(&model->geom_id); assert(geom);
     66 
     67 	float left	 = geom->min[0] - factor;
     68 	float right  = geom->max[0] + factor;
     69 	float bottom = geom->min[1] - factor;
     70 	float top	 = geom->max[1] + factor;
     71 
     72 	/* float left	= -factor; */
     73 	/* float right	= factor; */
     74 	/* float bottom = factor; */
     75 	/* float top	= -factor; */
     76 
     77 	const float near = -50.0;
     78 	const float far = 50.0;
     79 
     80 	// default ortho screenspace projection
     81 	//mat4_ortho(left, right, bottom, top, near, far, m4_ortho);
     82 
     83 	create_fbo(shadow_buffer, width, height );
     84 	//fbo_attach_renderbuffer(shadow_buffer, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT);
     85 
     86 	//fbo_attach_color_texture(shadow_buffer);
     87 	fbo_attach_depth_texture(shadow_buffer);
     88 
     89 	check_fbo(shadow_buffer);
     90 
     91 	/* fbo_attach_texture(&res->shadow_buffer, GL_DEPTH_COMPONENT16, */
     92 	/*					  GL_DEPTH_COMPONENT, GL_DEPTH_ATTACHMENT); */
     93 }
     94 
     95 
     96 static struct entity *get_player(struct test_game *res) {
     97 	struct entity *player = get_entity(&res->player_id);
     98 	assert(player);
     99 	return player;
    100 }
    101 
    102 static struct entity *get_terrain_entity(struct terrain *t) {
    103 	struct entity *ent = get_entity(&t->entity_id);
    104 	assert(ent);
    105 	return ent;
    106 }
    107 
    108 static void player_movement(struct engine *engine, struct entity *player) {
    109 	/* if (player->flags & ENT_ON_GROUND) */
    110 	/*	   entity_movement(game, player); */
    111 	struct node *node = get_node(&player->node_id);
    112 	movement(engine, node, 2.0);
    113 }
    114 
    115 static void camera_keep_above_ground(struct terrain *terrain,
    116 				     struct node *camera) {
    117 	if (get_entity(&terrain->entity_id)->flags & ENT_INVISIBLE)
    118 		return;
    119 	float move[3];
    120 	float *camworld = node_world(camera);
    121 	float pen = 0.0;
    122 	static const float penlim = 1.0;
    123 	struct tri *tri = collide_terrain(terrain, camworld, move, &pen);
    124 
    125 	if (!tri)
    126 		return;
    127 
    128 	if (pen < penlim) {
    129 		float dir[3], above[3];
    130 		vec3_normalize(move, dir);
    131 		vec3_scale(dir, pen < 0 ? penlim : -penlim, above);
    132 		vec3_add(camworld, move, camworld);
    133 		vec3_add(camworld, above, camworld);
    134 		/* vec3_add(move, above, move); */
    135 		/* vec3_add(camworld, move, camworld); */
    136 	}
    137 }
    138 
    139 static void entity_movement(struct engine *engine, struct entity *ent)
    140 {
    141 	static const float move_accel = 1.0f;
    142 	static const float max_speed = 10.0f;
    143 	struct node *node = get_node(&ent->node_id);
    144 
    145 	float vel[3];
    146 
    147 	float amt = 10.0 * engine->dt;
    148 
    149 	if (engine->input.keystates[SDL_SCANCODE_W]) {
    150 		vec3_forward(ent->velocity, node->orientation, V3(0,amt,0), vel);
    151 		if (vec3_lengthsq(vel) <= max_speed*max_speed)
    152 			vec3_copy(vel, ent->velocity);
    153 	}
    154 }
    155 
    156 
    157 static void player_terrain_collision(struct terrain *terrain, struct node *node) {
    158 	// player movement
    159 	static vec3 last_pos[3] = {0};
    160 
    161 	if (!vec3_approxeq(node->pos, last_pos)) {
    162 		float player_z = node->pos[2];
    163 
    164 		float terrain_z =
    165 			terrain->fn(terrain, node->pos[0], node->pos[1]);
    166 
    167 		float inset =
    168 			min(0.0, player_z - terrain_z);
    169 
    170 		if (inset <= 0)
    171 			node_translate(node, V3(0.0, 0.0, -inset));
    172 	}
    173 
    174 }
    175 
    176 // TODO: match based on some real concept of time
    177 static void day_night_cycle(float time, struct test_game *res) {
    178 	float val = time * 0.0001;
    179 	float intensity = 1.0;//max(0.0, vec3_dot(res->light_dir, V3(0.0, 0.0, 1.0))); */
    180 	struct entity *player = get_player(res);
    181 	struct node *pnode = get_node(&player->node_id);
    182 	assert(pnode);
    183 	struct node *suncam = get_node(&res->sun_camera_id);
    184 	assert(suncam);
    185 	struct common_uniforms *cvars = &res->common_vars;
    186 
    187 	float light_pos[3];
    188 
    189 	float g = 0.6;
    190 	float b = 0.4;
    191 	cvars->sun_color[0] = 1.0;
    192 	cvars->sun_color[1] = g+intensity*(1.0-g);
    193 	cvars->sun_color[2] = b+intensity*(1.0-b);
    194 
    195 	/* res->sun_color[0] = 1.0; */
    196 	/* res->sun_color[1] = 1.0; */
    197 	/* res->sun_color[2] = 1.0; */
    198 
    199 	/* vec3_scale(res->sun_color, res->light_intensity, gtmp); */
    200 
    201 	/* float intensity = angle <= 0.5 */
    202 	/*	   ? clamp(roots, darkest, 1.0) */
    203 	/*	   : clamp(-roots * 0.4, darkest, 0.5); */
    204 
    205 	cvars->light_intensity = intensity;
    206 
    207 	/* vec3_normalize(res->light_intensity, res->light_intensity); */
    208 
    209 	cvars->light_dir[0] = 0.0;
    210 	/* res->light_dir[1] = sin(val); */
    211 	/* res->light_dir[2] = cos(val) + 1.0; */
    212 	cvars->light_dir[1] = 0.8;
    213 	cvars->light_dir[2] = 0.8;
    214 
    215 	vec3_normalize(cvars->light_dir, cvars->light_dir);
    216 
    217 	/* printf("intensity %f(%f) n %f light_dir %f %f\n", roots, intensity, */
    218 	/*		  n, res->light_dir[1], res->light_dir[2]); */
    219 
    220 	vec3_add(pnode->pos, cvars->light_dir, light_pos);
    221 
    222 	/* float target[3]; */
    223 	/* float hh = player->model.geom.max[2] / 2.0; */
    224 	/* vec3_copy(player->node.pos, target); */
    225 	/* target[2] += 2.0; */
    226 
    227 	look_at(light_pos, pnode->pos, V3(0, 0, 1.0), suncam->mat);
    228 	/* look_at(light_pos, player->node.pos, V3(0, 0, 1.0), res->sun_camera.mat); */
    229 }
    230 
    231 static void player_update(struct engine *engine, struct test_game *game, struct entity *player)
    232 {
    233 	struct orbit *camera = &game->orbit_camera;
    234 	struct node *node = get_node(&player->node_id);
    235 	struct node *cam_node = get_node(&game->camera_node_id);
    236 	assert(node);
    237 	assert(cam_node);
    238 
    239 	orbit_update_from_mouse(camera, &engine->input,
    240 		engine->user_settings.mouse_sens,
    241 		player, NULL, engine->dt);
    242 
    243 	camera_keep_above_ground(&game->terrain, cam_node);
    244 
    245 	// move player camera toward camera orientation
    246 	if (input_is_dragging(&engine->input, SDL_BUTTON_RIGHT)) {
    247 		float yaw = game->orbit_camera.coords.azimuth;
    248 		quat_axis_angle(V3(0.0, 0.0, 1.0), -yaw - RAD(90), node->orientation);
    249 	}
    250 
    251 	struct terrain *terrain = &game->terrain;
    252 
    253 	player_terrain_collision(terrain, node);
    254 
    255 	float move[3];
    256 	float pos[3];
    257 	float pen = 0.0;
    258 	vec3_copy(node_world(node), pos);
    259 	/* debug("node_world(player) %f %f %f\n", pos[0], pos[1], pos[2]); */
    260 	struct tri *tri = collide_terrain(terrain, pos, move, &pen);
    261 	//struct tri *tri = NULL;
    262 	/* node_translate(node, move); */
    263 
    264 	if (tri) {
    265 		if (vec3_eq(move, V3(0,0,0), 0.1)) {
    266 			player->flags |= ENT_ON_GROUND;
    267 		}
    268 		else if (pen < 0) {
    269 			node_translate(node, move);
    270 			/* vec3_all(player->velocity, 0); */
    271 			vec3_scale(player->velocity, 0.1, player->velocity);
    272 		}
    273 		else {
    274 			player->flags &= ~ENT_ON_GROUND;
    275 		}
    276 	}
    277 	else {
    278 		static int tric = 0;
    279 		/* debug("%d no tri\n", tric++); */
    280 	}
    281 
    282 	if (player->flags & ENT_ON_GROUND &&
    283 		(was_key_pressed_this_frame(engine, SDL_SCANCODE_SPACE) /*||
    284 		 was_button_pressed_this_frame(engine, SDL_CONTROLLER_BUTTON_X)*/)) {
    285 		entity_jump(player, 2.0);
    286 	}
    287 
    288 	/* debug("player velocity %f %f %f\n", */
    289 	/*		 player->velocity[0], */
    290 	/*		 player->velocity[1], */
    291 	/*		 player->velocity[2]); */
    292 
    293 //	  if (player->flags & ENT_AT_REST)
    294 //	vec3_scale(player->velocity, 0.00001, player->velocity);
    295 
    296 	node_translate(node, player->velocity);
    297 	node_recalc(node);
    298 }
    299 
    300 enum binding_structs {
    301 	COMMON_UNIFORMS,
    302 	CHESS_PIECE_UNIFORMS,
    303 };
    304 
    305 static struct structure_binding uniform_bindings[] = {
    306 	[COMMON_UNIFORMS] =
    307 		{ common_lenses, ARRAY_SIZE(common_lenses) },
    308 };
    309 
    310 void init_test_gl(struct test_game *game, struct gpu *gpu, int width, int height)
    311 {
    312 	struct shader vertex, terrain_vertex, terrain_geom, fragment, fragment_smooth;
    313 	struct shader terrain_teval, terrain_tc;
    314 	float tmp_matrix[16];
    315 	int ok = 0;
    316 
    317 	gpu->num_programs = NUM_TEST_GAME_PROGRAMS;
    318 
    319 	// Shaders
    320 	ok = make_shader(GL_VERTEX_SHADER, SHADER("vertex-color.glsl"),
    321 					 &vertex);
    322 	rtassert(ok, "vertex-color shader");
    323 
    324 	ok = make_shader(GL_VERTEX_SHADER, SHADER("terrain.v.glsl"), &terrain_vertex);
    325 	rtassert(ok, "terrain vertex shader");
    326 	check_gl();
    327 
    328 	ok = make_shader(GL_FRAGMENT_SHADER, SHADER("main.f.glsl"), &fragment);
    329 	rtassert(ok, "default fragment shader");
    330 	check_gl();
    331 
    332 	// camera
    333 	mat4_perspective(90 /* fov */,
    334 			 (float)width / height,
    335 			 1,
    336 			 5000,
    337 			 game->proj_persp);
    338 
    339 	struct gpu_program *programs = gpu->programs;
    340 
    341 	ok = make_program("terrain", &terrain_vertex, &fragment,
    342 			  &programs[TERRAIN_PROGRAM],
    343 			  uniform_bindings,
    344 			  ARRAY_SIZE(uniform_bindings));
    345 	rtassert(ok, "terrain program");
    346 	check_gl();
    347 
    348 	ok = make_program("vertex-color", &vertex, &fragment,
    349 			  &programs[DEFAULT_PROGRAM],
    350 			  uniform_bindings,
    351 			  ARRAY_SIZE(uniform_bindings));
    352 	rtassert(ok, "vertex-color program");
    353 	check_gl();
    354 }
    355 
    356 
    357 // TODO: add uniforms automatically?
    358 
    359 static void render_test_game(struct gpu *gpu, struct test_game *game, struct render_config *config) {
    360 	float gtmp[3];
    361 	u32 num_entities;
    362 
    363 	struct common_uniforms *cvars = &game->common_vars;
    364 
    365 	cvars->sky_intensity = clamp(cvars->light_intensity, 0.2, 1.0);
    366 	vec3_scale(cvars->sun_color, cvars->sky_intensity, gtmp);
    367 
    368 	glEnable(GL_DEPTH_TEST);
    369 
    370 	glClearColor( gtmp[0], gtmp[1], gtmp[2], 1.0 ); //clear background screen to black
    371 	/* glClearColor( 0.5294f * adjust, 0.8078f * adjust, 0.9216f * adjust, 1.0f ); //clear background screen to black */
    372 	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    373 
    374 	check_gl();
    375 
    376 	static float id[MAT4_ELEMS] = { 0 };
    377 	static float view[MAT4_ELEMS] = { 0 };
    378 	static float view_proj[MAT4_ELEMS] = { 0 };
    379 	static float normal_matrix[MAT4_ELEMS] = { 0 };
    380 
    381 	mat4_id(id);
    382 	mat4_id(cvars->model_view);
    383 
    384 	mat4 *projection = config->projection;
    385 
    386 	struct node *camera_node = get_node(&config->camera);
    387 	assert(camera_node);
    388 
    389 	const mat4 *camera = camera_node->mat;
    390 
    391 	struct entity *entities =
    392 		get_all_entities(&num_entities, NULL);
    393 
    394 	struct gpu_program *program = NULL;
    395 
    396 	mat4_inverse((float*)camera, view);
    397 	mat4_multiply(projection, view, view_proj);
    398 
    399 	if (config->is_depth_pass) {
    400 		glDisable(GL_CULL_FACE);
    401 		mat4_multiply(bias_matrix, view_proj, config->depth_vp);
    402 	}
    403 	else {
    404 		glCullFace(GL_BACK);
    405 	}
    406 
    407 	mat4_inverse((float *)camera, view);
    408 	mat4_multiply(projection, view, view_proj);
    409 
    410 	struct model *skybox_model = get_model(&game->skybox.model_id);
    411 	assert(skybox_model);
    412 
    413 	glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_model->texture);
    414 	check_gl();
    415 
    416 	cvars->camera_position = (float*)&camera[M_X];
    417 
    418 	for (u32 i = 0; i < num_entities; ++i) {
    419 		struct entity *entity = &entities[i];
    420 		struct model *model = get_model(&entity->model_id);
    421 		assert(model);
    422 		struct node *node = get_node(&entity->node_id);
    423 		assert(node);
    424 
    425 		if (entity->flags & ENT_INVISIBLE)
    426 			continue;
    427 
    428 		if (config->is_depth_pass && !(entity->flags & ENT_CASTS_SHADOWS))
    429 			continue;
    430 
    431 		program = &gpu->programs[model->shader];
    432 
    433 		glUseProgram(program->handle);
    434 		check_gl();
    435 
    436 		mat4_multiply(view_proj, node->mat, cvars->mvp);
    437 		mat4_copy(node->mat, cvars->model_view);
    438 		mat4_multiply(config->depth_vp, cvars->model_view, cvars->depth_mvp);
    439 
    440 		void *shader_data[] = {
    441 			[COMMON_UNIFORMS] = cvars,
    442 			[CHESS_PIECE_UNIFORMS] = entity->data,
    443 		};
    444 
    445 		bind_uniforms(program, shader_data, ARRAY_SIZE(shader_data));
    446 		check_gl();
    447 
    448 		/*
    449 		recalc_normals(program->uniforms[UNIFORM_NORMAL_MATRIX].location,
    450 					   model_view, normal_matrix);
    451 
    452 		check_gl();
    453 		*/
    454 
    455 		struct geometry *geo = get_geometry(&model->geom_id);
    456 		/* debug("geo node %s\n", node->label); */
    457 		assert(geo);
    458 		render_geometry(geo, program);
    459 		check_gl();
    460 	}
    461 
    462 	if (gpu->wireframe) {
    463 		glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
    464 	}
    465 	else {
    466 		glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
    467 	}
    468 
    469 	if (!config->is_depth_pass) {
    470 		mat4_inverse((float*)camera, view);
    471 		mat4_remove_translations(view);
    472 		mat4_multiply(projection, view, view_proj);
    473 
    474 		render_skybox(&game->skybox, view_proj);
    475 	}
    476 
    477 	if (config->draw_ui)
    478 		render_ui(&game->ui, view);
    479 
    480 	//player
    481 	// y tho
    482 
    483 	// terrain
    484 
    485 	/* glUniformMatrix4fv(res->uniforms.mvp, 1, 0, mvp); */
    486 	/* glUniformMatrix4fv(res->uniforms.model_view, 1, 0, id); */
    487 	/* glUniformMatrix4fv(res->uniforms.world, 1, 0, id); */
    488 	/* glUniformMatrix4fv(res->uniforms.normal_matrix, 1, 0, id); */
    489 	/* recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix); */
    490 	/* render_geom(res, geom, GL_TRIANGLES); */
    491 	/* glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); */
    492 	/* render_geom(res, geom, GL_TRIANGLES); */
    493 }
    494 
    495 
    496 void update_test_game (struct engine *engine, struct test_game *game) {
    497 	static int toggle_fog = 0;
    498 	static int needs_terrain_update = 0;
    499 		//struct terrain   *terrain		 = &game->terrain;
    500 	struct node *root     = get_node(&game->root_id);
    501 	struct entity *player = get_player(game);
    502 	struct node *pnode    = get_node(&player->node_id);
    503 	struct node *cam_node = get_node(&game->camera_node_id);
    504 	struct common_uniforms *cvars = &game->common_vars;
    505 
    506 	assert(pnode);
    507 	assert(cam_node);
    508 
    509 	float *time = &game->time;
    510 	float *light = cvars->light_dir;
    511 
    512 	gravity(player, engine->dt);
    513 
    514 	if (needs_terrain_update) {
    515 		/* update_terrain(terrain); */
    516 		needs_terrain_update = 0;
    517 	}
    518 
    519 	/* spherical_dir(game->test_resources.camera.coords, camera_dir); */
    520 	/* vec3_scale(camera_dir, -1, camera_dir); */
    521 
    522 	if (engine->input.modifiers & KMOD_ALT &&
    523 		ideq(&game->camera_node_id, &game->free_camera_id))
    524 	{
    525 		struct node *freecam_node = get_node(&game->free_camera_id);
    526 		assert(freecam_node);
    527 		assert(streq(freecam_node->label, "freecam"));
    528 		movement(engine, freecam_node, 1.0);
    529 	} else {
    530 		player_movement(engine, player);
    531 	}
    532 
    533 	assert(root->parent_id.id.generation == 0);
    534 
    535 	player_update(engine, game, player);
    536 
    537 #ifdef DEBUG
    538 	if (was_key_pressed_this_frame(engine, SDL_SCANCODE_R)) {
    539 		try_reload_shaders(&engine->gpu);
    540 	}
    541 #endif
    542 
    543 	if (was_key_pressed_this_frame(engine, SDL_SCANCODE_F5)) {
    544 		engine->gpu.wireframe ^= 1;
    545 	}
    546 
    547 	if (was_key_pressed_this_frame(engine, SDL_SCANCODE_C)) {
    548 		printf("light_dir %f %f %f\n", light[0], light[1], light[2]);
    549 	}
    550 
    551 	if (was_key_pressed_this_frame(engine, SDL_SCANCODE_F)) {
    552 		toggle_fog = 1;
    553 	}
    554 
    555 	if (was_key_pressed_this_frame(engine, SDL_SCANCODE_EQUALS)) {
    556 		if (!ideq(&game->camera_node_id, &game->free_camera_id)) {
    557 			debug("switching to freecam\n");
    558 			game->camera_node_id = game->free_camera_id;
    559 		}
    560 		else {
    561 			debug("switching to orbitcam\n");
    562 			game->camera_node_id = game->orbit_camera.node_id;
    563 		}
    564 	}
    565 
    566 	if (toggle_fog) {
    567 		cvars->fog_on ^= 1;
    568 		toggle_fog = 0;
    569 	}
    570 
    571 	*time = SDL_GetTicks();
    572 
    573 	day_night_cycle(*time, game);
    574 
    575 	node_recalc(root);
    576 }
    577 
    578 void test_game_frame(struct engine *engine, struct test_game *game)
    579 {
    580 	static float depth_vp[MAT4_ELEMS];
    581 	mat4_id(depth_vp);
    582 
    583 	struct render_config fbo_render_config = {
    584 		.draw_ui = 0,
    585 		.is_depth_pass = 1,
    586 		.camera = game->sun_camera_id,
    587 		.projection = game->proj_ortho,
    588 		.depth_vp = depth_vp
    589 	};
    590 
    591 	struct render_config default_config = {
    592 		.draw_ui = 0,
    593 		.is_depth_pass = 0,
    594 		.camera = game->camera_node_id,
    595 		.projection = game->proj_persp,
    596 		.depth_vp = depth_vp
    597 	};
    598 
    599 	struct entity *player = get_entity(&game->player_id);
    600 	if (engine->input.resized_height) {
    601 		mat4_perspective(60 /* fov */,
    602 				(float)engine->width / (float)engine->height, 0.1,
    603 				10000.0, game->proj_persp);
    604 
    605 		resize_fbos(player, &game->shadow_buffer, game->proj_ortho,
    606 			engine->width, engine->height);
    607 	}
    608 
    609 	update_test_game(engine, game);
    610 
    611 	//struct fbo *fbo = &game->shadow_buffer;
    612 	//check_fbo(fbo);
    613 	//bind_fbo(fbo);
    614 		/* glDrawBuffer(GL_NONE); */
    615 
    616 	//render_test_game(&engine->gpu, game, &fbo_render_config);
    617 	//unbind_fbo(&game->shadow_buffer);
    618 	render_test_game(&engine->gpu, game, &default_config);
    619 }
    620 
    621 void init_test_game(struct engine *engine, struct test_game *game)
    622 {
    623 	memset(game, 0, sizeof(*game));
    624 	struct terrain *terrain = &game->terrain;
    625 	struct entity *player;
    626 	struct model *model;
    627 	struct common_uniforms *cvars = &game->common_vars;
    628 
    629 	init_test_gl(game, &engine->gpu, engine->width, engine->height);
    630 
    631 	init_id(&game->root_id);
    632 	init_id(&game->sun_camera_id);
    633 	init_id(&game->free_camera_id);
    634 
    635 	struct node *root = new_node(&game->root_id);
    636 	struct node *sun_camera = new_node(&game->sun_camera_id);
    637 
    638 	assert(root->parent_id.id.generation == 0);
    639 	assert(root);
    640 	assert(sun_camera);
    641 
    642 	const double size = 4000.0;
    643 	//double scale = 0.03;
    644 	double scale = 0.03;
    645 
    646 	create_skybox(&game->skybox, &engine->gpu.programs[SKYBOX_PROGRAM]);
    647 	create_ui(&game->ui, engine->width, engine->height, &engine->gpu.programs[UI_PROGRAM]);
    648 
    649 	terrain->settings = (struct perlin_settings){
    650 		.depth = 1,
    651 		.freq  = scale * 0.08,
    652 		.o1 = 2.0, .o1s = 0.5,
    653 		.o2 = 4.0, .o2s = 0.25,
    654 		.amplitude	= 70.0,
    655 		.ox = 0,
    656 		.oy = 0,
    657 		.exp = 5.3,
    658 		.scale = scale
    659 	};
    660 
    661 	init_terrain(terrain, size);
    662 
    663 	/* terrain->samples = load_samples(&seed, &terrain->n_samples); */
    664 	terrain->n_samples = 0;
    665 	create_terrain(terrain, size, engine->seed);
    666 	//load_terrain(terrain);
    667 	/* update_terrain(terrain, terrain->cell_size); */
    668 	/* get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE; */
    669 
    670 	/* node_scale(&game->skybox.node, size/4.0); */
    671 
    672 	mat4_id(cvars->mvp);
    673 
    674 	cvars->light_intensity = 0.8;
    675 
    676 	cvars->light_dir[0] = 0.8;
    677 	cvars->light_dir[1] = 0.8;
    678 	cvars->light_dir[2] = 0.8;
    679 
    680 	cvars->sun_color[0] = 0.5;
    681 	cvars->sun_color[1] = 0.6;
    682 	cvars->sun_color[2] = 0.7;
    683 
    684 	cvars->fog_on = 0;
    685 	//cvars->diffuse_on = 0;
    686 
    687 	node_init(root);
    688 	node_init(sun_camera);
    689 	new_orbit(&game->orbit_camera);
    690 
    691 	node_set_label(root, "root");
    692 
    693 	// ENTITIES
    694 
    695 	// player entity
    696 	init_id(&game->player_id);
    697 	player = new_entity(&game->player_id);
    698 	player->flags |= ENT_CASTS_SHADOWS;
    699 	struct node *pnode = get_node(&player->node_id);
    700 	assert(pnode);
    701 
    702 	player->model_id = get_model_by_name("pirate_officer", NULL);
    703 	assert(!is_null_id(&player->model_id));
    704 
    705 
    706 	node_set_label(pnode, "player");
    707 	/* node_rotate(pnode, V3(-5.0,0,0)); */
    708 	node_attach(&player->node_id, &game->root_id);
    709 	assert(ideq(&pnode->parent_id, &game->root_id));
    710 
    711 	node_translate(pnode, V3(terrain->size/2.,terrain->size/2.,0.0));
    712 
    713 	// orbit camera
    714 	game->orbit_camera.coords.azimuth = -quat_yaw(pnode->orientation) - RAD(90.0);
    715 	game->orbit_camera.coords.inclination = RAD(60);
    716 	game->orbit_camera.coords.radius = 5.0;
    717 	game->camera_node_id = game->orbit_camera.node_id;
    718 
    719 	// free camera
    720 	struct node *freecam = new_node(&game->free_camera_id);
    721 	node_set_label(freecam, "freecam");
    722 	node_attach(&game->free_camera_id, &player->node_id);
    723 	quat_axis_angle(V3(1,0,0), -45, freecam->orientation);
    724 	node_rotate(freecam, V3(100, 0, 0));
    725 	node_translate(freecam, V3(0,-40,20));
    726 
    727 	// FBO STUFF
    728 	init_fbo(&game->shadow_buffer);
    729 	resize_fbos(player, &game->shadow_buffer, game->proj_ortho, engine->width, engine->height);
    730 	// FBO STUFF END
    731 
    732 	// TEXTURES
    733 	// END TEXTURES
    734 }
    735 
    736 void default_scene(struct test_game *game) {
    737 	struct terrain *terrain = &game->terrain;
    738 	struct entity *terrain_ent = get_terrain_entity(terrain);
    739 	struct entity *player = get_player(game);
    740 
    741 	// show terrain
    742 	terrain_ent->flags &= ~ENT_INVISIBLE;
    743 
    744 	// show player
    745 	player->flags &= ~ENT_INVISIBLE;
    746 
    747 	struct entity *tower = new_entity(NULL);
    748 	struct node *tnode = get_node(&tower->node_id);
    749 	struct node *pnode = get_node(&player->node_id);
    750 
    751 	assert(tnode);
    752 	tower->model_id = get_model_by_name("tower", NULL);
    753 	node_set_label(tnode, "tower");
    754 	node_attach(&tower->node_id, &player->node_id);
    755 	node_translate(tnode, V3(0.0, 50.0, 0.0));
    756 	node_recalc(tnode);
    757 	float z = terrain->fn(terrain, tnode->mat[M_X], tnode->mat[M_Y]);
    758 	/* node_detach(tnode, pnode); */
    759 	tnode->mat[M_Z] = z;
    760 }
    761 
    762 
    763 
    764 void entity_test_scene(struct terrain *terrain)
    765 {
    766 	struct model_id rock_model;
    767 	init_id(&rock_model);
    768 
    769 	/* model_id rock_model = get_static_model(model_tower, NULL); */
    770 	struct model *pmodel  = new_model(&rock_model, "procrock"); assert(pmodel);
    771 	struct geometry *geom = get_geometry(&pmodel->geom_id); assert(geom);
    772 	proc_sphere(geom);
    773 
    774 	for (int i = 0; i < 200; i++) {
    775 		struct entity *ent = new_entity(NULL);
    776 		struct node *node  = get_node(&ent->node_id);
    777 
    778 		ent->model_id = rock_model;
    779 
    780 		double x = rand_0to1() * terrain->size;
    781 		double y = rand_0to1() * terrain->size;
    782 		double z = terrain->fn(terrain, x, y);
    783 
    784 		node_scale(node, pow(15.0, rand_0to1()));
    785 		node_rotate(node, V3(rand_0to1(),rand_0to1(),rand_0to1()));
    786 		node_translate(node, V3(x, y, z));
    787 		node_set_label(node, "rock");
    788 
    789 		node_recalc(node);
    790 	}
    791 
    792 }
    793 
    794 void pbr_scene(struct test_game *game)
    795 {
    796 	struct entity *ent = new_entity(NULL);
    797 	struct node *node  = get_node(&ent->node_id); assert(node);
    798 	struct entity *player = get_player(game);
    799 
    800 	ent->model_id = get_model_by_name("icosphere", NULL);
    801 	node_set_label(node, "sphere");
    802 }