summaryrefslogtreecommitdiff
path: root/gltfview/src/plugins/gltf_view.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2023-06-16 09:38:15 -0700
committer3gg <3gg@shellblade.net>2023-06-16 09:38:15 -0700
commit520e4e67cd9ff53f3c3512c80d07193625e07e3e (patch)
treef2f8acfc2eb0d2aa279263d93af00beef7e93a1b /gltfview/src/plugins/gltf_view.c
parent14e6edd6bfe94089d52b5c4b6899dea23923e9be (diff)
New plugin architecture.
Diffstat (limited to 'gltfview/src/plugins/gltf_view.c')
-rw-r--r--gltfview/src/plugins/gltf_view.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/gltfview/src/plugins/gltf_view.c b/gltfview/src/plugins/gltf_view.c
new file mode 100644
index 0000000..511c2e8
--- /dev/null
+++ b/gltfview/src/plugins/gltf_view.c
@@ -0,0 +1,167 @@
1#include "gltf_view.h"
2
3#include <gfx/renderer.h>
4#include <gfx/util/scene.h>
5#include <gfx/util/skyquad.h>
6#include <gfx/util/texture.h>
7#include <math/camera.h>
8#include <math/spatial3.h>
9
10#include <stdlib.h>
11
12// Paths to various scene files.
13/*static const char* BOX = "/assets/models/box.gltf";
14static const char* SUZANNE = "/assets/models/suzanne.gltf";
15static const char* SPONZA =
16 "/assets/glTF-Sample-Models/2.0/Sponza/glTF/Sponza.gltf";
17static const char* FLIGHT_HELMET =
18 "/assets/glTF-Sample-Models/2.0/FlightHelmet/glTF/FlightHelmet.gltf";
19static const char* DAMAGED_HELMET =
20 "/assets/glTF-Sample-Models/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf";*/
21static const char* GIRL =
22 "/home/jeanne/Nextcloud/assets/models/girl/girl-with-ground.gltf";
23
24#define DEFAULT_SCENE_FILE GIRL
25
26/// Load the skyquad texture.
27static Texture* load_environment_map(RenderBackend* render_backend) {
28 return gfx_load_texture(
29 render_backend,
30 &(LoadTextureCmd){
31 .origin = TextureFromFile,
32 .type = LoadCubemap,
33 .colour_space = sRGB,
34 .filtering = NearestFiltering,
35 .mipmaps = false,
36 .data.cubemap.filepaths = {
37 mstring_make("/assets/skybox/clouds1/clouds1_east.bmp"),
38 mstring_make("/assets/skybox/clouds1/clouds1_west.bmp"),
39 mstring_make("/assets/skybox/clouds1/clouds1_up.bmp"),
40 mstring_make("/assets/skybox/clouds1/clouds1_down.bmp"),
41 mstring_make("/assets/skybox/clouds1/clouds1_south.bmp"),
42 mstring_make("/assets/skybox/clouds1/clouds1_north.bmp")}
43 });
44}
45
46/// Load the skyquad and return the environment light node.
47static SceneNode* load_skyquad(RenderBackend* render_backend, SceneNode* root) {
48 assert(render_backend);
49 assert(root);
50
51 Texture* environment_map = load_environment_map(render_backend);
52 if (!environment_map) {
53 return 0;
54 }
55
56 return gfx_setup_skyquad(render_backend, root, environment_map);
57}
58
59/// Load the 3D scene.
60static SceneNode* load_scene(Game* game, const char* scene_filepath) {
61 assert(game);
62 assert(game->gfx);
63 assert(game->scene);
64
65 SceneNode* root = gfx_get_scene_root(game->scene);
66 RenderBackend* render_backend = gfx_get_render_backend(game->gfx);
67
68 Camera* camera = gfx_get_camera_camera(game->camera);
69 spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2));
70
71 SceneNode* sky_light_node = load_skyquad(render_backend, root);
72 if (!sky_light_node) {
73 return 0;
74 }
75
76 SceneNode* scene_node = gfx_load_scene(
77 game->gfx, sky_light_node,
78 &(LoadSceneCmd){.origin = SceneFromFile, .filepath = scene_filepath});
79 if (!scene_node) {
80 return 0;
81 }
82
83 gfx_log_node_hierarchy(root);
84
85 return scene_node;
86}
87
88State* init(Game* game) {
89 assert(game);
90
91 State* state = calloc(1, sizeof(State));
92 return state;
93}
94
95bool boot(State* state, Game* game) {
96 assert(state);
97 assert(game);
98
99 const int argc = game->argc;
100 const char** argv = game->argv;
101
102 // Usage: <scene file>
103 const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE;
104
105 SceneNode* node = load_scene(game, scene_filepath);
106 if (!node) {
107 return false;
108 }
109 Anima* anima = gfx_get_node_anima(node);
110 gfx_play_animation(
111 anima, &(AnimationPlaySettings){.name = "Walk", .loop = true});
112
113 return true;
114}
115
116void update(State* state, Game* game, double t, double dt) {
117 assert(state);
118 assert(game);
119 assert(game->scene);
120 assert(game->camera);
121
122 gfx_animate_scene(game->scene, (R)t);
123
124 const vec3 orbit_point = vec3_make(0, 2, 0);
125 Camera* camera = gfx_get_camera_camera(game->camera);
126 spatial3_orbit(
127 &camera->spatial, orbit_point,
128 /*radius=*/2.5,
129 /*azimuth=*/t * 0.5, /*zenith=*/0);
130 spatial3_lookat(&camera->spatial, orbit_point);
131}
132
133/// Render the bounding boxes of all scene objects.
134static void render_bounding_boxes(ImmRenderer* imm, const SceneNode* node) {
135 if (gfx_get_node_type(node) == ObjectNode) {
136 // TODO: Look at the scene log. The JointNodes are detached from the
137 // ObjectNodes. This is why the boxes are not being transformed as expected
138 // here. Anima needs to animate boxes? Use OOBB in addition to AABB?
139 const mat4 model = gfx_get_node_global_transform(node);
140 const SceneObject* obj = gfx_get_node_object(node);
141 const aabb3 box = gfx_calc_object_aabb(obj);
142 gfx_imm_set_model_matrix(imm, &model);
143 gfx_imm_draw_aabb(imm, box);
144 }
145
146 // Render children's boxes.
147 for (NodeIter it = gfx_get_node_child(node); it;
148 it = gfx_get_next_child(it)) {
149 render_bounding_boxes(imm, gfx_get_iter_node(it));
150 }
151}
152
153void render(State* state, const Game* game) {
154 assert(state);
155 assert(game);
156 assert(game->gfx);
157 assert(game->scene);
158 assert(game->camera);
159
160 ImmRenderer* imm = gfx_get_imm_renderer(game->gfx);
161 assert(imm);
162 gfx_imm_start(imm);
163 gfx_imm_set_camera(imm, gfx_get_camera_camera(game->camera));
164 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));
166 gfx_imm_end(imm);
167}