diff options
Diffstat (limited to 'gltfview/src')
| -rw-r--r-- | gltfview/src/game.c | 104 | 
1 files changed, 54 insertions, 50 deletions
| diff --git a/gltfview/src/game.c b/gltfview/src/game.c index d7352d4..f2e5a88 100644 --- a/gltfview/src/game.c +++ b/gltfview/src/game.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include <unistd.h> // usleep; TODO Remove. | 24 | #include <unistd.h> // usleep; TODO Remove. | 
| 25 | 25 | ||
| 26 | // Paths to various scene files. | 26 | // Paths to various scene files. | 
| 27 | static const char* BOX = "/assets/models/box.gltf"; | 27 | static const char* BOX = "/assets/models/box.gltf"; | 
| 28 | static const char* SUZANNE = "/assets/models/suzanne.gltf"; | 28 | static const char* SUZANNE = "/assets/models/suzanne.gltf"; | 
| 29 | static const char* SPONZA = | 29 | static const char* SPONZA = | 
| 30 | "/assets/glTF-Sample-Models/2.0/Sponza/glTF/Sponza.gltf"; | 30 | "/assets/glTF-Sample-Models/2.0/Sponza/glTF/Sponza.gltf"; | 
| @@ -37,8 +37,8 @@ static const char* DAMAGED_HELMET = | |||
| 37 | 37 | ||
| 38 | static const char* CLOUDS1_TEXTURE = "/assets/skybox/clouds1/clouds1_west.bmp"; | 38 | static const char* CLOUDS1_TEXTURE = "/assets/skybox/clouds1/clouds1_west.bmp"; | 
| 39 | 39 | ||
| 40 | static ShaderProgram* load_shader(RenderBackend* render_backend, | 40 | static ShaderProgram* load_shader( | 
| 41 | const char* view_mode) { | 41 | RenderBackend* render_backend, const char* view_mode) { | 
| 42 | ShaderProgram* shader = 0; | 42 | ShaderProgram* shader = 0; | 
| 43 | if (strcmp(view_mode, "debug") == 0) { | 43 | if (strcmp(view_mode, "debug") == 0) { | 
| 44 | shader = gfx_make_debug3d_shader(render_backend); | 44 | shader = gfx_make_debug3d_shader(render_backend); | 
| @@ -59,23 +59,24 @@ static Texture* load_environment_map(RenderBackend* render_backend) { | |||
| 59 | return gfx_load_texture( | 59 | return gfx_load_texture( | 
| 60 | render_backend, | 60 | render_backend, | 
| 61 | &(LoadTextureCmd){ | 61 | &(LoadTextureCmd){ | 
| 62 | .origin = TextureFromFile, | 62 | .origin = TextureFromFile, | 
| 63 | .type = LoadCubemap, | 63 | .type = LoadCubemap, | 
| 64 | .colour_space = sRGB, | 64 | .colour_space = sRGB, | 
| 65 | .filtering = NearestFiltering, | 65 | .filtering = NearestFiltering, | 
| 66 | .mipmaps = false, | 66 | .mipmaps = false, | 
| 67 | .data.cubemap.filepaths = { | 67 | .data.cubemap.filepaths = { | 
| 68 | mstring_make("/assets/skybox/clouds1/clouds1_east.bmp"), | 68 | mstring_make("/assets/skybox/clouds1/clouds1_east.bmp"), | 
| 69 | mstring_make("/assets/skybox/clouds1/clouds1_west.bmp"), | 69 | mstring_make("/assets/skybox/clouds1/clouds1_west.bmp"), | 
| 70 | mstring_make("/assets/skybox/clouds1/clouds1_up.bmp"), | 70 | mstring_make("/assets/skybox/clouds1/clouds1_up.bmp"), | 
| 71 | mstring_make("/assets/skybox/clouds1/clouds1_down.bmp"), | 71 | mstring_make("/assets/skybox/clouds1/clouds1_down.bmp"), | 
| 72 | mstring_make("/assets/skybox/clouds1/clouds1_north.bmp"), | 72 | mstring_make("/assets/skybox/clouds1/clouds1_north.bmp"), | 
| 73 | mstring_make("/assets/skybox/clouds1/clouds1_south.bmp")}}); | 73 | mstring_make("/assets/skybox/clouds1/clouds1_south.bmp")} | 
| 74 | }); | ||
| 74 | } | 75 | } | 
| 75 | 76 | ||
| 76 | /// Creates an object to render the skyquad in the background. | 77 | /// Creates an object to render the skyquad in the background. | 
| 77 | static SceneNode* make_skyquad_object_node(Game* game, | 78 | static SceneNode* make_skyquad_object_node( | 
| 78 | const Texture* environment_map) { | 79 | Game* game, const Texture* environment_map) { | 
| 79 | assert(game); | 80 | assert(game); | 
| 80 | 81 | ||
| 81 | SceneObject* skyquad_object = | 82 | SceneObject* skyquad_object = | 
| @@ -92,12 +93,12 @@ static SceneNode* make_skyquad_object_node(Game* game, | |||
| 92 | } | 93 | } | 
| 93 | 94 | ||
| 94 | /// Creates an environment light. | 95 | /// Creates an environment light. | 
| 95 | static SceneNode* make_environment_light(Game* game, | 96 | static SceneNode* make_environment_light( | 
| 96 | const Texture* environment_light) { | 97 | Game* game, const Texture* environment_light) { | 
| 97 | assert(game); | 98 | assert(game); | 
| 98 | 99 | ||
| 99 | Light* light = gfx_make_light(&(LightDesc){ | 100 | Light* light = gfx_make_light(&(LightDesc){ | 
| 100 | .type = EnvironmentLightType, | 101 | .type = EnvironmentLightType, | 
| 101 | .light = (EnvironmentLightDesc){.environment_map = environment_light}}); | 102 | .light = (EnvironmentLightDesc){.environment_map = environment_light}}); | 
| 102 | if (!light) { | 103 | if (!light) { | 
| 103 | return 0; | 104 | return 0; | 
| @@ -127,8 +128,8 @@ static bool load_skyquad(Game* game, SceneNode** node) { | |||
| 127 | } | 128 | } | 
| 128 | 129 | ||
| 129 | /// Loads the 3D scene. | 130 | /// Loads the 3D scene. | 
| 130 | static bool load_scene(Game* game, const char* scene_filepath, | 131 | static bool load_scene( | 
| 131 | const char* view_mode) { | 132 | Game* game, const char* scene_filepath, const char* view_mode) { | 
| 132 | assert(game); | 133 | assert(game); | 
| 133 | 134 | ||
| 134 | game->camera = gfx_make_camera(); | 135 | game->camera = gfx_make_camera(); | 
| @@ -151,9 +152,10 @@ static bool load_scene(Game* game, const char* scene_filepath, | |||
| 151 | return false; | 152 | return false; | 
| 152 | } | 153 | } | 
| 153 | 154 | ||
| 154 | if (!gfx_load_scene(game->gfx, sky_node, shader, | 155 | if (!gfx_load_scene( | 
| 155 | &(LoadSceneCmd){.origin = SceneFromFile, | 156 | game->gfx, sky_node, shader, | 
| 156 | .filepath = scene_filepath})) { | 157 | &(LoadSceneCmd){ | 
| 158 | .origin = SceneFromFile, .filepath = scene_filepath})) { | ||
| 157 | return false; | 159 | return false; | 
| 158 | } | 160 | } | 
| 159 | 161 | ||
| @@ -164,14 +166,14 @@ static bool load_scene(Game* game, const char* scene_filepath, | |||
| 164 | static bool load_texture_debugger_scene(Game* game) { | 166 | static bool load_texture_debugger_scene(Game* game) { | 
| 165 | assert(game); | 167 | assert(game); | 
| 166 | 168 | ||
| 167 | Texture* texture = | 169 | Texture* texture = gfx_load_texture( | 
| 168 | gfx_load_texture(game->render_backend, | 170 | game->render_backend, | 
| 169 | &(LoadTextureCmd){.origin = TextureFromFile, | 171 | &(LoadTextureCmd){ | 
| 170 | .type = LoadTexture, | 172 | .origin = TextureFromFile, | 
| 171 | .filtering = LinearFiltering, | 173 | .type = LoadTexture, | 
| 172 | .mipmaps = false, | 174 | .filtering = LinearFiltering, | 
| 173 | .data.texture.filepath = | 175 | .mipmaps = false, | 
| 174 | mstring_make(CLOUDS1_TEXTURE)}); | 176 | .data.texture.filepath = mstring_make(CLOUDS1_TEXTURE)}); | 
| 175 | 177 | ||
| 176 | game->camera = gfx_make_camera(); | 178 | game->camera = gfx_make_camera(); | 
| 177 | if (!game->camera) { | 179 | if (!game->camera) { | 
| @@ -191,12 +193,12 @@ static bool load_texture_debugger_scene(Game* game) { | |||
| 191 | } | 193 | } | 
| 192 | 194 | ||
| 193 | MaterialDesc material_desc = (MaterialDesc){0}; | 195 | MaterialDesc material_desc = (MaterialDesc){0}; | 
| 194 | material_desc.shader = shader; | 196 | material_desc.uniforms[0] = (ShaderUniform){ | 
| 195 | material_desc.uniforms[0] = (ShaderUniform){.type = UniformTexture, | 197 | .type = UniformTexture, | 
| 196 | .value.texture = texture, | 198 | .value.texture = texture, | 
| 197 | .name = sstring_make("Texture")}; | 199 | .name = sstring_make("Texture")}; | 
| 198 | material_desc.num_uniforms = 1; | 200 | material_desc.num_uniforms = 1; | 
| 199 | Material* material = gfx_make_material(&material_desc); | 201 | Material* material = gfx_make_material(&material_desc); | 
| 200 | if (!material) { | 202 | if (!material) { | 
| 201 | return false; | 203 | return false; | 
| 202 | } | 204 | } | 
| @@ -204,7 +206,8 @@ static bool load_texture_debugger_scene(Game* game) { | |||
| 204 | MeshDesc mesh_desc = (MeshDesc){0}; | 206 | MeshDesc mesh_desc = (MeshDesc){0}; | 
| 205 | mesh_desc.geometry = geometry; | 207 | mesh_desc.geometry = geometry; | 
| 206 | mesh_desc.material = material; | 208 | mesh_desc.material = material; | 
| 207 | Mesh* mesh = gfx_make_mesh(&mesh_desc); | 209 | mesh_desc.shader = shader; | 
| 210 | Mesh* mesh = gfx_make_mesh(&mesh_desc); | ||
| 208 | if (!mesh) { | 211 | if (!mesh) { | 
| 209 | return false; | 212 | return false; | 
| 210 | } | 213 | } | 
| @@ -224,7 +227,7 @@ static bool load_texture_debugger_scene(Game* game) { | |||
| 224 | 227 | ||
| 225 | bool game_new(Game* game, int argc, const char** argv) { | 228 | bool game_new(Game* game, int argc, const char** argv) { | 
| 226 | // TODO: getopt() to implement proper argument parsing. | 229 | // TODO: getopt() to implement proper argument parsing. | 
| 227 | const char* view_mode = argc > 1 ? argv[1] : ""; | 230 | const char* view_mode = argc > 1 ? argv[1] : ""; | 
| 228 | const char* scene_filepath = argc > 2 ? argv[2] : DEFAULT_SCENE_FILE; | 231 | const char* scene_filepath = argc > 2 ? argv[2] : DEFAULT_SCENE_FILE; | 
| 229 | 232 | ||
| 230 | game->gfx = gfx_init(); | 233 | game->gfx = gfx_init(); | 
| @@ -233,7 +236,7 @@ bool game_new(Game* game, int argc, const char** argv) { | |||
| 233 | } | 236 | } | 
| 234 | 237 | ||
| 235 | game->render_backend = gfx_get_render_backend(game->gfx); | 238 | game->render_backend = gfx_get_render_backend(game->gfx); | 
| 236 | game->renderer = gfx_get_renderer(game->gfx); | 239 | game->renderer = gfx_get_renderer(game->gfx); | 
| 237 | 240 | ||
| 238 | game->scene = gfx_make_scene(game->gfx); | 241 | game->scene = gfx_make_scene(game->gfx); | 
| 239 | if (!game->scene) { | 242 | if (!game->scene) { | 
| @@ -270,26 +273,27 @@ void game_update(Game* game, double t, double dt) { | |||
| 270 | game->elapsed -= 1.0; | 273 | game->elapsed -= 1.0; | 
| 271 | } | 274 | } | 
| 272 | Camera* camera = gfx_get_camera_camera(game->camera); | 275 | Camera* camera = gfx_get_camera_camera(game->camera); | 
| 273 | spatial3_orbit(&camera->spatial, vec3_make(0, 0, 0), | 276 | spatial3_orbit( | 
| 274 | /*radius=*/2, | 277 | &camera->spatial, vec3_make(0, 0, 0), | 
| 275 | /*azimuth=*/t * 0.5, /*zenith=*/0); | 278 | /*radius=*/2, | 
| 279 | /*azimuth=*/t * 0.5, /*zenith=*/0); | ||
| 276 | spatial3_lookat(&camera->spatial, vec3_make(0, 0, 0)); | 280 | spatial3_lookat(&camera->spatial, vec3_make(0, 0, 0)); | 
| 277 | } | 281 | } | 
| 278 | 282 | ||
| 279 | void game_render(const Game* game) { | 283 | void game_render(const Game* game) { | 
| 280 | gfx_render_scene(game->renderer, game->render_backend, game->scene, | 284 | gfx_render_scene( | 
| 281 | game->camera); | 285 | game->renderer, game->render_backend, game->scene, game->camera); | 
| 282 | } | 286 | } | 
| 283 | 287 | ||
| 284 | void game_set_viewport(Game* game, int width, int height) { | 288 | void game_set_viewport(Game* game, int width, int height) { | 
| 285 | gfx_set_viewport(game->render_backend, width, height); | 289 | gfx_set_viewport(game->render_backend, width, height); | 
| 286 | 290 | ||
| 287 | const R fovy = 90 * TO_RAD; | 291 | const R fovy = 90 * TO_RAD; | 
| 288 | const R aspect = (R)width / (R)height; | 292 | const R aspect = (R)width / (R)height; | 
| 289 | const R near = 0.1; | 293 | const R near = 0.1; | 
| 290 | const R far = 1000; | 294 | const R far = 1000; | 
| 291 | const mat4 projection = mat4_perspective(fovy, aspect, near, far); | 295 | const mat4 projection = mat4_perspective(fovy, aspect, near, far); | 
| 292 | 296 | ||
| 293 | Camera* camera = gfx_get_camera_camera(game->camera); | 297 | Camera* camera = gfx_get_camera_camera(game->camera); | 
| 294 | camera->projection = projection; | 298 | camera->projection = projection; | 
| 295 | } | 299 | } | 
