135 lines
3.1 KiB
C
135 lines
3.1 KiB
C
#include "animation.h"
|
|
#include "gpu.h"
|
|
#include "model_format_glb.h"
|
|
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#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;
|
|
}
|