From 520e4e67cd9ff53f3c3512c80d07193625e07e3e Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 16 Jun 2023 09:38:15 -0700 Subject: New plugin architecture. --- gltfview/src/plugins/gltf_view.c | 167 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 gltfview/src/plugins/gltf_view.c (limited to 'gltfview/src/plugins/gltf_view.c') 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 @@ +#include "gltf_view.h" + +#include +#include +#include +#include +#include +#include + +#include + +// Paths to various scene files. +/*static const char* BOX = "/assets/models/box.gltf"; +static const char* SUZANNE = "/assets/models/suzanne.gltf"; +static const char* SPONZA = + "/assets/glTF-Sample-Models/2.0/Sponza/glTF/Sponza.gltf"; +static const char* FLIGHT_HELMET = + "/assets/glTF-Sample-Models/2.0/FlightHelmet/glTF/FlightHelmet.gltf"; +static const char* DAMAGED_HELMET = + "/assets/glTF-Sample-Models/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf";*/ +static const char* GIRL = + "/home/jeanne/Nextcloud/assets/models/girl/girl-with-ground.gltf"; + +#define DEFAULT_SCENE_FILE GIRL + +/// Load the skyquad texture. +static Texture* load_environment_map(RenderBackend* render_backend) { + return gfx_load_texture( + render_backend, + &(LoadTextureCmd){ + .origin = TextureFromFile, + .type = LoadCubemap, + .colour_space = sRGB, + .filtering = NearestFiltering, + .mipmaps = false, + .data.cubemap.filepaths = { + mstring_make("/assets/skybox/clouds1/clouds1_east.bmp"), + mstring_make("/assets/skybox/clouds1/clouds1_west.bmp"), + mstring_make("/assets/skybox/clouds1/clouds1_up.bmp"), + mstring_make("/assets/skybox/clouds1/clouds1_down.bmp"), + mstring_make("/assets/skybox/clouds1/clouds1_south.bmp"), + mstring_make("/assets/skybox/clouds1/clouds1_north.bmp")} + }); +} + +/// Load the skyquad and return the environment light node. +static SceneNode* load_skyquad(RenderBackend* render_backend, SceneNode* root) { + assert(render_backend); + assert(root); + + Texture* environment_map = load_environment_map(render_backend); + if (!environment_map) { + return 0; + } + + return gfx_setup_skyquad(render_backend, root, environment_map); +} + +/// Load the 3D scene. +static SceneNode* load_scene(Game* game, const char* scene_filepath) { + assert(game); + assert(game->gfx); + assert(game->scene); + + SceneNode* root = gfx_get_scene_root(game->scene); + RenderBackend* render_backend = gfx_get_render_backend(game->gfx); + + Camera* camera = gfx_get_camera_camera(game->camera); + spatial3_set_position(&camera->spatial, vec3_make(0, 0, 2)); + + SceneNode* sky_light_node = load_skyquad(render_backend, root); + if (!sky_light_node) { + return 0; + } + + SceneNode* scene_node = gfx_load_scene( + game->gfx, sky_light_node, + &(LoadSceneCmd){.origin = SceneFromFile, .filepath = scene_filepath}); + if (!scene_node) { + return 0; + } + + gfx_log_node_hierarchy(root); + + return scene_node; +} + +State* init(Game* game) { + assert(game); + + State* state = calloc(1, sizeof(State)); + return state; +} + +bool boot(State* state, Game* game) { + assert(state); + assert(game); + + const int argc = game->argc; + const char** argv = game->argv; + + // Usage: + const char* scene_filepath = argc > 1 ? argv[1] : DEFAULT_SCENE_FILE; + + SceneNode* node = load_scene(game, scene_filepath); + if (!node) { + return false; + } + Anima* anima = gfx_get_node_anima(node); + gfx_play_animation( + anima, &(AnimationPlaySettings){.name = "Walk", .loop = true}); + + return true; +} + +void update(State* state, Game* game, double t, double dt) { + assert(state); + assert(game); + assert(game->scene); + assert(game->camera); + + gfx_animate_scene(game->scene, (R)t); + + const vec3 orbit_point = vec3_make(0, 2, 0); + Camera* camera = gfx_get_camera_camera(game->camera); + spatial3_orbit( + &camera->spatial, orbit_point, + /*radius=*/2.5, + /*azimuth=*/t * 0.5, /*zenith=*/0); + spatial3_lookat(&camera->spatial, orbit_point); +} + +/// Render the bounding boxes of all scene objects. +static void render_bounding_boxes(ImmRenderer* imm, const SceneNode* node) { + if (gfx_get_node_type(node) == ObjectNode) { + // TODO: Look at the scene log. The JointNodes are detached from the + // ObjectNodes. This is why the boxes are not being transformed as expected + // here. Anima needs to animate boxes? Use OOBB in addition to AABB? + const mat4 model = gfx_get_node_global_transform(node); + const SceneObject* obj = gfx_get_node_object(node); + const aabb3 box = gfx_calc_object_aabb(obj); + gfx_imm_set_model_matrix(imm, &model); + gfx_imm_draw_aabb(imm, box); + } + + // Render children's boxes. + for (NodeIter it = gfx_get_node_child(node); it; + it = gfx_get_next_child(it)) { + render_bounding_boxes(imm, gfx_get_iter_node(it)); + } +} + +void render(State* state, const Game* game) { + assert(state); + assert(game); + assert(game->gfx); + assert(game->scene); + assert(game->camera); + + ImmRenderer* imm = gfx_get_imm_renderer(game->gfx); + assert(imm); + gfx_imm_start(imm); + gfx_imm_set_camera(imm, gfx_get_camera_camera(game->camera)); + gfx_imm_set_colour(imm, vec4_make(0.2, 0.2, 1.0, 0.3)); + render_bounding_boxes(imm, gfx_get_scene_root(game->scene)); + gfx_imm_end(imm); +} -- cgit v1.2.3