#include "animation.h" #include "gpu.h" #include "model_format_glb.h" #include #include #include #include #define W 1280 #define H 720 #define DT (1'000'000 / 60) // Assume 60 Hz for now #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) static light_params_t light_params; static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) { (void)window; (void)scancode; (void)mods; if (action != GLFW_PRESS) return; switch (key) { case GLFW_KEY_Q: glfwSetWindowShouldClose(window, GL_TRUE); break; case GLFW_KEY_UP: light_params.cloudiness += 0.05; if (light_params.cloudiness > 1) light_params.cloudiness = 1; break; case GLFW_KEY_DOWN: light_params.cloudiness -= 0.05; if (light_params.cloudiness < 0) light_params.cloudiness = 0; break; } } int main(int argc, char *argv[]) { // Read model from passed path if (argc != 2) { fprintf(stderr, "Usage: %s PATH/TO/MODEL\n", argv[0]); return 1; } model_t model = model_format_glb_read(argv[1]); // Set up window glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); GLFWwindow *window = glfwCreateWindow(W, H, "Foo", nullptr, nullptr); assert(window); // Register input callbacks glfwSetKeyCallback(window, key_callback); // Initialise GPU and load model gpu_ctx_t gpu; gpu_model_t gpu_models[2]; gpu_init(&gpu, window, "Foo"); gpu_model_load(&gpu, &model, gpu_models + 0); gpu_model_load(&gpu, &model, gpu_models + 1); const vec3_t cam = { 2, 2, -8 }; const vec3_t tgt = { 0, 0, 0 }; const vec3_t up = { 0, 1, 0 }; const mat4_t view = mat4_lookat(cam, tgt, up); const mat4_t proj = mat4_perspective((float)W / H, PI / 12, 0.1, 100.0); const mat4_t vp = mat4_mul(proj, view); mat4_t transforms[NELEMS(gpu_models)] = { mat4_mul( MAT4_TRANSLATE(1, 0, 0), (mat4_t) { { 0, 0, -1, 0 }, { -1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 1 }, }), mat4_mul( MAT4_TRANSLATE(2, 0, 0), mat4_mul( MAT4_ROTATE_Y(PI), (mat4_t) { { 0, 0, -1, 0 }, { -1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 1 }, })), }; // Set up animation animation_state_t anim = animation_init(&model); animation_start(&anim, &model, 0); light_params.sun_dir = vec3_norm((vec3_t) { 2, 4, -1 }); light_params.cloudiness = 0.0; while (!glfwWindowShouldClose(window)) { glfwPollEvents(); transforms[0] = mat4_mul(MAT4_ROTATE_Y(PI / 170), transforms[0]); transforms[1] = mat4_mul(MAT4_ROTATE_Y(-PI / 340), transforms[1]); animation_update(&anim, &model, DT); const mat4_t *bone_matrices[NELEMS(gpu_models)] = { anim.bone_matrices, anim.bone_matrices, }; gpu_render( &gpu, vp, light_params, NELEMS(gpu_models), gpu_models, bone_matrices, transforms); } // Clean up animation_cleanup(&anim); gpu_model_cleanup(&gpu, gpu_models + 0); gpu_model_cleanup(&gpu, gpu_models + 1); gpu_cleanup(&gpu); model_cleanup(&model); glfwDestroyWindow(window); glfwTerminate(); return 0; }