summaryrefslogtreecommitdiff
path: root/gltfview/src
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2024-01-19 07:21:45 -0800
committer3gg <3gg@shellblade.net>2024-01-19 07:21:45 -0800
commit4212e57d06afac8a19b09fdebc24bad10b78f1ac (patch)
tree322b2e5cc2764ebd1855565bb8d871d9df33d704 /gltfview/src
parentfc883e0b0449509ba2e1c5d14d187feee098ab34 (diff)
Plugin refactor, moving scene from game to plugin.
Diffstat (limited to 'gltfview/src')
-rw-r--r--gltfview/src/game.c138
-rw-r--r--gltfview/src/game.h2
-rw-r--r--gltfview/src/plugins/gltf_view.c77
-rw-r--r--gltfview/src/plugins/gltf_view.h9
-rw-r--r--gltfview/src/plugins/plugin.h59
-rw-r--r--gltfview/src/plugins/texture_view.c91
-rw-r--r--gltfview/src/plugins/texture_view.h3
7 files changed, 249 insertions, 130 deletions
diff --git a/gltfview/src/game.c b/gltfview/src/game.c
index c331190..64be4f3 100644
--- a/gltfview/src/game.c
+++ b/gltfview/src/game.c
@@ -39,6 +39,78 @@ static const int WIDTH = 1350;
39static const int HEIGHT = 900; 39static const int HEIGHT = 900;
40static const int MAX_FPS = 60; 40static const int MAX_FPS = 60;
41 41
42/// Initialize the game's plugin.
43static bool init_plugin(Game* game) {
44 assert(game);
45 assert(game->plugin);
46 // Plugin state is allowed to be null, either when the plugin does not
47 // expose an init() or when init() does not initialize a state.
48 if (plugin_resolve(game->plugin, plugin_init, "init")) {
49 State* plugin_state = 0;
50 if (!plugin_call(game->plugin, plugin_init, "init", game, &plugin_state)) {
51 return false;
52 }
53 set_plugin_state(game->plugin, plugin_state);
54 }
55 return true; // Plugin does not need to expose an init().
56}
57
58/// Shutdown the game's plugin.
59/// The game's plugin is allowed to be null in the call to this function.
60static void shutdown_plugin(Game* game) {
61 assert(game);
62 if (game->plugin &&
63 (plugin_resolve(game->plugin, plugin_shutdown, "shutdown"))) {
64 void* plugin_state = get_plugin_state(game->plugin);
65 plugin_call(game->plugin, plugin_shutdown, "shutdown", game, plugin_state);
66 set_plugin_state(game->plugin, 0);
67 }
68}
69
70/// Boot the game's plugin.
71static bool boot_plugin(Game* game) {
72 assert(game);
73 assert(game->plugin);
74 if (plugin_resolve(game->plugin, plugin_boot, "boot")) {
75 void* plugin_state = get_plugin_state(game->plugin);
76 return plugin_call(game->plugin, plugin_boot, "boot", game, plugin_state);
77 }
78 return true; // Plugin does not need to expose a boot().
79}
80
81/// Update the plugin's state.
82static void update_plugin(Game* game, double t, double dt) {
83 assert(game);
84 assert(game->plugin);
85 if (plugin_resolve(game->plugin, plugin_update, "update")) {
86 void* plugin_state = get_plugin_state(game->plugin);
87 plugin_call(
88 game->plugin, plugin_update, "update", game, plugin_state, t, dt);
89 }
90}
91
92/// Plugin render.
93static void render_plugin(const Game* game) {
94 assert(game);
95 assert(game->plugin);
96 if (plugin_resolve(game->plugin, plugin_render, "render")) {
97 void* plugin_state = get_plugin_state(game->plugin);
98 plugin_call(game->plugin, plugin_render, "render", game, plugin_state);
99 }
100}
101
102/// Plugin resize.
103static void resize_plugin(Game* game, int width, int height) {
104 assert(game);
105 assert(game->plugin);
106 if (plugin_resolve(game->plugin, plugin_resize, "resize")) {
107 void* plugin_state = get_plugin_state(game->plugin);
108 plugin_call(
109 game->plugin, plugin_resize, "resize", game, plugin_state, width,
110 height);
111 }
112}
113
42void app_end(Game* game); 114void app_end(Game* game);
43 115
44bool app_init(const GfxAppDesc* desc, void** app_state) { 116bool app_init(const GfxAppDesc* desc, void** app_state) {
@@ -88,30 +160,14 @@ bool app_init(const GfxAppDesc* desc, void** app_state) {
88 if (!(game->gfx = gfx_init())) { 160 if (!(game->gfx = gfx_init())) {
89 goto cleanup; 161 goto cleanup;
90 } 162 }
91 if (!(game->scene = gfx_make_scene())) { 163
164 if (!init_plugin(game)) {
92 goto cleanup; 165 goto cleanup;
93 } 166 }
94 if (!(game->camera = gfx_make_camera())) { 167 if (!boot_plugin(game)) {
95 goto cleanup; 168 goto cleanup;
96 } 169 }
97 170
98 if (plugin_resolve(game->plugin, plugin_init, "init")) {
99 void* plugin_state = plugin_call(game->plugin, plugin_init, "init", game);
100 if (!plugin_state) {
101 goto cleanup;
102 }
103 set_plugin_state(game->plugin, plugin_state);
104 }
105
106 if (plugin_resolve(game->plugin, plugin_boot, "boot")) {
107 void* plugin_state = get_plugin_state(game->plugin);
108 bool boot_success =
109 plugin_call(game->plugin, plugin_boot, "boot", plugin_state, game);
110 if (!boot_success) {
111 goto cleanup;
112 }
113 }
114
115 *app_state = game; 171 *app_state = game;
116 return true; 172 return true;
117 173
@@ -123,6 +179,7 @@ cleanup:
123 179
124void app_end(Game* game) { 180void app_end(Game* game) {
125 assert(game); 181 assert(game);
182 shutdown_plugin(game);
126 if (game->gfx) { 183 if (game->gfx) {
127 gfx_destroy(&game->gfx); 184 gfx_destroy(&game->gfx);
128 } 185 }
@@ -136,53 +193,24 @@ void app_end(Game* game) {
136 193
137void app_update(Game* game, double t, double dt) { 194void app_update(Game* game, double t, double dt) {
138 plugin_engine_update(game->plugin_engine); 195 plugin_engine_update(game->plugin_engine);
139 if (plugin_reloaded(game->plugin) && 196 if (plugin_reloaded(game->plugin)) {
140 plugin_resolve(game->plugin, plugin_init, "init")) { 197 shutdown_plugin(game);
141 void* plugin_state = plugin_call(game->plugin, plugin_init, "init", game); 198 const bool result = init_plugin(game);
142 assert(plugin_state); // TODO: handle error better. 199 assert(result); // TODO: handle error better.
143 set_plugin_state(game->plugin, plugin_state);
144 } 200 }
145 201
146 if (plugin_resolve(game->plugin, plugin_update, "update")) { 202 update_plugin(game, t, dt);
147 // Plugin state may be null if plugin does not expose init().
148 void* plugin_state = get_plugin_state(game->plugin);
149 plugin_call(
150 game->plugin, plugin_update, "update", plugin_state, game, t, dt);
151 }
152} 203}
153 204
154void app_render(const Game* game) { 205void app_render(const Game* game) {
155 RenderBackend* render_backend = gfx_get_render_backend(game->gfx); 206 RenderBackend* render_backend = gfx_get_render_backend(game->gfx);
156 Renderer* renderer = gfx_get_renderer(game->gfx);
157
158 gfx_start_frame(render_backend); 207 gfx_start_frame(render_backend);
159 208 render_plugin(game);
160 gfx_render_scene(
161 renderer,
162 &(RenderSceneParams){
163 .mode = RenderDefault, .scene = game->scene, .camera = game->camera});
164
165 if (plugin_resolve(game->plugin, plugin_render, "render")) {
166 // Plugin state may be null if plugin does not expose init().
167 void* plugin_state = get_plugin_state(game->plugin);
168 plugin_call(game->plugin, plugin_render, "render", plugin_state, game);
169 }
170
171 gfx_end_frame(render_backend); 209 gfx_end_frame(render_backend);
172} 210}
173 211
174void app_resize(Game* game, int width, int height) { 212void app_resize(Game* game, int width, int height) {
175 RenderBackend* render_backend = gfx_get_render_backend(game->gfx); 213 resize_plugin(game, width, height);
176 gfx_set_viewport(render_backend, width, height);
177
178 const R fovy = 90 * TO_RAD;
179 const R aspect = (R)width / (R)height;
180 const R near = 0.1;
181 const R far = 1000;
182 const mat4 projection = mat4_perspective(fovy, aspect, near, far);
183
184 Camera* camera = gfx_get_camera_camera(game->camera);
185 camera->projection = projection;
186} 214}
187 215
188GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS); 216GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS);
diff --git a/gltfview/src/game.h b/gltfview/src/game.h
index 53725c7..93a5e39 100644
--- a/gltfview/src/game.h
+++ b/gltfview/src/game.h
@@ -16,6 +16,4 @@ typedef struct {
16 PluginEngine* plugin_engine; 16 PluginEngine* plugin_engine;
17 Plugin* plugin; 17 Plugin* plugin;
18 Gfx* gfx; 18 Gfx* gfx;
19 Scene* scene; // TODO: Move scene graph to plugin?
20 SceneCamera* camera; // TODO: Move too.
21} Game; 19} Game;
diff --git a/gltfview/src/plugins/gltf_view.c b/gltfview/src/plugins/gltf_view.c
index c3457a8..c19d1b8 100644
--- a/gltfview/src/plugins/gltf_view.c
+++ b/gltfview/src/plugins/gltf_view.c
@@ -1,6 +1,7 @@
1#include "gltf_view.h" 1#include "plugin.h"
2 2
3#include <gfx/renderer.h> 3#include <gfx/renderer.h>
4#include <gfx/scene.h>
4#include <gfx/util/scene.h> 5#include <gfx/util/scene.h>
5#include <gfx/util/skyquad.h> 6#include <gfx/util/skyquad.h>
6#include <gfx/util/texture.h> 7#include <gfx/util/texture.h>
@@ -23,6 +24,11 @@ static const char* GIRL =
23 24
24#define DEFAULT_SCENE_FILE GIRL 25#define DEFAULT_SCENE_FILE GIRL
25 26
27struct State {
28 Scene* scene;
29 SceneCamera* camera;
30};
31
26/// Load the skyquad texture. 32/// Load the skyquad texture.
27static Texture* load_environment_map(RenderBackend* render_backend) { 33static Texture* load_environment_map(RenderBackend* render_backend) {
28 return gfx_load_texture( 34 return gfx_load_texture(
@@ -57,15 +63,17 @@ static SceneNode* load_skyquad(RenderBackend* render_backend, SceneNode* root) {
57} 63}
58 64
59/// Load the 3D scene. 65/// Load the 3D scene.
60static SceneNode* load_scene(Game* game, const char* scene_filepath) { 66static SceneNode* load_scene(
67 Game* game, State* state, const char* scene_filepath) {
61 assert(game); 68 assert(game);
62 assert(game->gfx); 69 assert(game->gfx);
63 assert(game->scene); 70 assert(state);
71 assert(state->scene);
64 72
65 SceneNode* root = gfx_get_scene_root(game->scene); 73 SceneNode* root = gfx_get_scene_root(state->scene);
66 RenderBackend* render_backend = gfx_get_render_backend(game->gfx); 74 RenderBackend* render_backend = gfx_get_render_backend(game->gfx);
67 75
68 Camera* camera = gfx_get_camera_camera(game->camera); 76 Camera* camera = gfx_get_camera_camera(state->camera);
69 spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2)); 77 spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2));
70 78
71 SceneNode* sky_light_node = load_skyquad(render_backend, root); 79 SceneNode* sky_light_node = load_skyquad(render_backend, root);
@@ -85,16 +93,20 @@ static SceneNode* load_scene(Game* game, const char* scene_filepath) {
85 return scene_node; 93 return scene_node;
86} 94}
87 95
88State* init(Game* game) { 96bool init(Game* game, State** pp_state) {
89 assert(game); 97 assert(game);
90 98
91 State* state = calloc(1, sizeof(State)); 99 State* state = calloc(1, sizeof(State));
92 return state; 100 if (!state) {
93} 101 goto cleanup;
102 }
94 103
95bool boot(State* state, Game* game) { 104 if (!(state->scene = gfx_make_scene())) {
96 assert(state); 105 goto cleanup;
97 assert(game); 106 }
107 if (!(state->camera = gfx_make_camera())) {
108 goto cleanup;
109 }
98 110
99 const int argc = game->argc; 111 const int argc = game->argc;
100 const char** argv = game->argv; 112 const char** argv = game->argv;
@@ -102,27 +114,44 @@ bool boot(State* state, Game* game) {
102 // Usage: <scene file> 114 // Usage: <scene file>
103 const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE; 115 const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE;
104 116
105 SceneNode* node = load_scene(game, scene_filepath); 117 SceneNode* node = load_scene(game, state, scene_filepath);
106 if (!node) { 118 if (!node) {
107 return false; 119 goto cleanup;
108 } 120 }
109 Anima* anima = gfx_get_node_anima(node); 121 Anima* anima = gfx_get_node_anima(node);
110 gfx_play_animation( 122 gfx_play_animation(
111 anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); 123 anima, &(AnimationPlaySettings){.name = "Walk", .loop = true});
112 124
125 *pp_state = state;
113 return true; 126 return true;
127
128cleanup:
129 shutdown(game, state);
130 if (state) {
131 free(state);
132 }
133 return false;
114} 134}
115 135
116void update(State* state, Game* game, double t, double dt) { 136void shutdown(Game* game, State* state) {
117 assert(state); 137 assert(game);
138 if (state) {
139 gfx_destroy_camera(&state->camera);
140 gfx_destroy_scene(&state->scene);
141 // State freed by plugin engine.
142 }
143}
144
145void update(Game* game, State* state, double t, double dt) {
118 assert(game); 146 assert(game);
119 assert(game->scene); 147 assert(state);
120 assert(game->camera); 148 assert(state->scene);
149 assert(state->camera);
121 150
122 gfx_animate_scene(game->scene, (R)t); 151 gfx_animate_scene(state->scene, (R)t);
123 152
124 const vec3 orbit_point = vec3_make(0, 2, 0); 153 const vec3 orbit_point = vec3_make(0, 2, 0);
125 Camera* camera = gfx_get_camera_camera(game->camera); 154 Camera* camera = gfx_get_camera_camera(state->camera);
126 spatial3_orbit( 155 spatial3_orbit(
127 &camera->spatial, orbit_point, 156 &camera->spatial, orbit_point,
128 /*radius=*/2.5, 157 /*radius=*/2.5,
@@ -150,18 +179,18 @@ static void render_bounding_boxes(ImmRenderer* imm, const SceneNode* node) {
150 } 179 }
151} 180}
152 181
153void render(State* state, const Game* game) { 182void render(const Game* game, const State* state) {
154 assert(state); 183 assert(state);
155 assert(game); 184 assert(game);
156 assert(game->gfx); 185 assert(game->gfx);
157 assert(game->scene); 186 assert(state->scene);
158 assert(game->camera); 187 assert(state->camera);
159 188
160 ImmRenderer* imm = gfx_get_imm_renderer(game->gfx); 189 ImmRenderer* imm = gfx_get_imm_renderer(game->gfx);
161 assert(imm); 190 assert(imm);
162 gfx_imm_start(imm); 191 gfx_imm_start(imm);
163 gfx_imm_set_camera(imm, gfx_get_camera_camera(game->camera)); 192 gfx_imm_set_camera(imm, gfx_get_camera_camera(state->camera));
164 gfx_imm_set_colour(imm, vec4_make(0.2, 0.2, 1.0, 0.3)); 193 gfx_imm_set_colour(imm, vec4_make(0.2, 0.2, 1.0, 0.3));
165 render_bounding_boxes(imm, gfx_get_scene_root(game->scene)); 194 render_bounding_boxes(imm, gfx_get_scene_root(state->scene));
166 gfx_imm_end(imm); 195 gfx_imm_end(imm);
167} 196}
diff --git a/gltfview/src/plugins/gltf_view.h b/gltfview/src/plugins/gltf_view.h
deleted file mode 100644
index 670d88d..0000000
--- a/gltfview/src/plugins/gltf_view.h
+++ /dev/null
@@ -1,9 +0,0 @@
1#pragma once
2
3#include "plugin.h"
4
5#include <gfx/scene.h>
6
7typedef struct State {
8 int unused;
9} State;
diff --git a/gltfview/src/plugins/plugin.h b/gltfview/src/plugins/plugin.h
index 0e0e12c..a2632cd 100644
--- a/gltfview/src/plugins/plugin.h
+++ b/gltfview/src/plugins/plugin.h
@@ -1,21 +1,5 @@
1/* 1/*
2 * Game plugin. 2 * Game plugin.
3 *
4 * A game plugin exposes three functions:
5 * - boot(): called once when the plugin is first loaded during the lifetime of
6 * the game.
7 * - init() -> state: creates and returns the plugin's state.
8 * - update(state): takes and updates the state, possibly with side effects.
9 * - render(): performs custom rendering.
10 *
11 * boot() is convenient for one-time initialization of the scene.
12 *
13 * init() is called every time the plugin is loaded. It is assumed that the
14 * plugin's state is encapsulated in the object returned.
15 *
16 * update() updates the plugin state and has side effects on the scene. It is
17 * assumed that update does not reference any global, mutable state outside of
18 * the scene and the plugin state returned by init().
19 */ 3 */
20#pragma once 4#pragma once
21 5
@@ -28,22 +12,41 @@
28 12
29typedef struct State State; 13typedef struct State State;
30 14
31/// Initialize the plugin's state. 15/// Initialize the plugin, which may optionally return a state object.
32State* init(Game*); 16///
17/// This function is called every time the plugin is (re)loaded.
18///
19/// It is assumed that the plugin's state is fully encapsulated in the returned
20/// state object. The plugin should not store any (mutable) state outside of the
21/// returned state object (e.g., no mutable global variables.)
22bool init(Game*, State**);
23
24/// Shut down the plugin.
25///
26/// This function is called before the plugin is unloaded.
27///
28/// The plugin should perform any destruction needed, but not free the state
29/// object; freeing the state object's memory is handled by the caller.
30void shutdown(Game*, State*);
33 31
34/// Function called the first time the plugin is loaded throughout the 32/// Function called the first time the plugin is loaded throughout the
35/// application's lifetime. Allows the plugin to do one-time initialization of 33/// application's lifetime. This allows the plugin to do one-time initialization
36/// the game state. 34/// of the game state.
37bool boot(State*, Game*); 35bool boot(Game*, State*);
38 36
39/// Update the plugin's and the game's state. 37/// Update the plugin's and the game's state.
40void update(State*, Game*, double t, double dt); 38void update(Game*, State*, double t, double dt);
41 39
42/// Optional plugin rendering hook. 40/// Render hook.
43void render(State*, const Game*); 41void render(const Game*, const State*);
42
43/// Called when the game's window is resized.
44void resize(Game* game, State* state, int width, int height);
44 45
45// Signatures for the plugin's exposed functions. 46// Signatures for the plugin's exposed functions.
46typedef void* (*plugin_init)(Game*); 47typedef bool (*plugin_init)(Game*, State**);
47typedef bool (*plugin_boot)(State*, Game*); 48typedef bool (*plugin_shutdown)(Game*, State*);
48typedef void (*plugin_update)(State*, Game*, double t, double dt); 49typedef bool (*plugin_boot)(Game*, State*);
49typedef void (*plugin_render)(State*, const Game*); 50typedef void (*plugin_update)(Game*, State*, double t, double dt);
51typedef void (*plugin_render)(const Game*, const State*);
52typedef void (*plugin_resize)(Game* game, State* state, int width, int height);
diff --git a/gltfview/src/plugins/texture_view.c b/gltfview/src/plugins/texture_view.c
index f16c8d1..b424158 100644
--- a/gltfview/src/plugins/texture_view.c
+++ b/gltfview/src/plugins/texture_view.c
@@ -1,6 +1,7 @@
1#include "texture_view.h" 1#include "plugin.h"
2 2
3#include <gfx/render_backend.h> 3#include <gfx/render_backend.h>
4#include <gfx/renderer.h>
4#include <gfx/scene.h> 5#include <gfx/scene.h>
5#include <gfx/util/geometry.h> 6#include <gfx/util/geometry.h>
6#include <gfx/util/shader.h> 7#include <gfx/util/shader.h>
@@ -9,13 +10,25 @@
9#include <math/camera.h> 10#include <math/camera.h>
10 11
11#include <assert.h> 12#include <assert.h>
13#include <stdlib.h>
12 14
13// Default texture to load if no texture is provided. 15// Default texture to load if no texture is provided.
14static const char* DEFAULT_TEXTURE = "/assets/skybox/clouds1/clouds1_west.bmp"; 16static const char* DEFAULT_TEXTURE = "/assets/skybox/clouds1/clouds1_west.bmp";
15// static const char* DEFAULT_TEXTURE = "/assets/checkerboard.jpg"; 17// static const char* DEFAULT_TEXTURE = "/assets/checkerboard.jpg";
16 18
17bool boot(State* state, Game* game) { 19struct State {
20 Scene* scene;
21 SceneCamera* camera;
22};
23
24bool init(Game* game, State** pp_state) {
18 assert(game); 25 assert(game);
26 assert(pp_state);
27
28 State* state = calloc(1, sizeof(State));
29 if (!state) {
30 goto cleanup;
31 }
19 32
20 // Usage: [texture file] 33 // Usage: [texture file]
21 const char* texture_file = game->argc > 1 ? game->argv[1] : DEFAULT_TEXTURE; 34 const char* texture_file = game->argc > 1 ? game->argv[1] : DEFAULT_TEXTURE;
@@ -30,17 +43,17 @@ bool boot(State* state, Game* game) {
30 .mipmaps = false, 43 .mipmaps = false,
31 .data.texture.filepath = mstring_make(texture_file)}); 44 .data.texture.filepath = mstring_make(texture_file)});
32 if (!texture) { 45 if (!texture) {
33 return false; 46 goto cleanup;
34 } 47 }
35 48
36 ShaderProgram* shader = gfx_make_view_texture_shader(render_backend); 49 ShaderProgram* shader = gfx_make_view_texture_shader(render_backend);
37 if (!shader) { 50 if (!shader) {
38 return false; 51 goto cleanup;
39 } 52 }
40 53
41 Geometry* geometry = gfx_make_quad_11(render_backend); 54 Geometry* geometry = gfx_make_quad_11(render_backend);
42 if (!geometry) { 55 if (!geometry) {
43 return false; 56 goto cleanup;
44 } 57 }
45 58
46 MaterialDesc material_desc = (MaterialDesc){.num_uniforms = 1}; 59 MaterialDesc material_desc = (MaterialDesc){.num_uniforms = 1};
@@ -50,25 +63,85 @@ bool boot(State* state, Game* game) {
50 .name = sstring_make("Texture")}; 63 .name = sstring_make("Texture")};
51 Material* material = gfx_make_material(&material_desc); 64 Material* material = gfx_make_material(&material_desc);
52 if (!material) { 65 if (!material) {
53 return false; 66 goto cleanup;
54 } 67 }
55 68
56 const MeshDesc mesh_desc = 69 const MeshDesc mesh_desc =
57 (MeshDesc){.geometry = geometry, .material = material, .shader = shader}; 70 (MeshDesc){.geometry = geometry, .material = material, .shader = shader};
58 Mesh* mesh = gfx_make_mesh(&mesh_desc); 71 Mesh* mesh = gfx_make_mesh(&mesh_desc);
59 if (!mesh) { 72 if (!mesh) {
60 return false; 73 goto cleanup;
61 } 74 }
62 75
63 SceneObject* object = gfx_make_object(); 76 SceneObject* object = gfx_make_object();
64 if (!object) { 77 if (!object) {
65 return false; 78 goto cleanup;
66 } 79 }
67 gfx_add_object_mesh(object, mesh); 80 gfx_add_object_mesh(object, mesh);
68 81
82 if (!(state->scene = gfx_make_scene())) {
83 goto cleanup;
84 }
85
69 SceneNode* node = gfx_make_object_node(object); 86 SceneNode* node = gfx_make_object_node(object);
70 SceneNode* root = gfx_get_scene_root(game->scene); 87 if (!node) {
88 goto cleanup;
89 }
90 SceneNode* root = gfx_get_scene_root(state->scene);
91 if (!root) {
92 goto cleanup;
93 }
71 gfx_set_node_parent(node, root); 94 gfx_set_node_parent(node, root);
72 95
96 if (!(state->camera = gfx_make_camera())) {
97 goto cleanup;
98 }
99
100 *pp_state = state;
73 return true; 101 return true;
102
103cleanup:
104 shutdown(game, state);
105 if (state) {
106 free(state);
107 }
108 return false;
109}
110
111void shutdown(Game* game, State* state) {
112 assert(game);
113 if (state) {
114 gfx_destroy_camera(&state->camera);
115 gfx_destroy_scene(&state->scene);
116 // State freed by plugin engine.
117 }
118}
119
120void render(const Game* game, const State* state) {
121 assert(game);
122 assert(state);
123
124 Renderer* renderer = gfx_get_renderer(game->gfx);
125 gfx_render_scene(
126 renderer, &(RenderSceneParams){
127 .mode = RenderDefault,
128 .scene = state->scene,
129 .camera = state->camera});
130}
131
132void resize(Game* game, State* state, int width, int height) {
133 assert(game);
134 assert(state);
135
136 RenderBackend* render_backend = gfx_get_render_backend(game->gfx);
137 gfx_set_viewport(render_backend, width, height);
138
139 const R fovy = 90 * TO_RAD;
140 const R aspect = (R)width / (R)height;
141 const R near = 0.1;
142 const R far = 1000;
143 const mat4 projection = mat4_perspective(fovy, aspect, near, far);
144
145 Camera* camera = gfx_get_camera_camera(state->camera);
146 camera->projection = projection;
74} 147}
diff --git a/gltfview/src/plugins/texture_view.h b/gltfview/src/plugins/texture_view.h
deleted file mode 100644
index 956f34a..0000000
--- a/gltfview/src/plugins/texture_view.h
+++ /dev/null
@@ -1,3 +0,0 @@
1#pragma once
2
3#include "plugin.h"