summaryrefslogtreecommitdiff
path: root/gltfview/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'gltfview/src/plugins')
-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
5 files changed, 166 insertions, 73 deletions
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"