#include "gpu.h" #include #include #include #include #ifndef M_PI #define M_PI 3.14159265358979324 #endif #define W 800 #define H 600 static const vertex_t vertices[] = { { { 0.000, 0.612, 0.000 }, { 1, 0, 0 } }, { { -0.500, -0.204, -0.289 }, { 0, 1, 0 } }, { { 0.500, -0.204, -0.289 }, { 0, 0, 1 } }, { { 0.000, -0.204, 0.577 }, { 1, 1, 1 } }, }; static const uint16_t indices[] = { 0, 3, 1, 0, 1, 2, 0, 2, 3, 3, 2, 1, }; typedef enum { AXIS_X, AXIS_Y, AXIS_Z, } axis_t; static axis_t rot_axis = AXIS_Y; #define ID \ { \ { 1, 0, 0, 0 }, \ { 0, 1, 0, 0 }, \ { 0, 0, 1, 0 }, \ { 0, 0, 0, 1 }, \ } #define SCALE(sf) \ { \ { sf, 0, 0, 0 }, \ { 0, sf, 0, 0 }, \ { 0, 0, sf, 0 }, \ { 0, 0, 0, 1 }, \ } #define TRANSLATE(x, y, z) \ { \ { 1, 0, 0, 0 }, \ { 0, 1, 0, 0 }, \ { 0, 0, 1, 0 }, \ { x, y, z, 1 }, \ } #define ROT_X(a) \ { \ { 1, 0, 0, 0 }, \ { 0, cosf(a), sinf(a), 0 }, \ { 0, -sinf(a), cosf(a), 0 }, \ { 0, 0, 0, 1 }, \ } #define ROT_Y(a) \ { \ { cosf(a), 0, -sinf(a), 0 }, \ { 0, 1, 0, 0 }, \ { sinf(a), 0, cosf(a), 0 }, \ { 0, 0, 0, 1 }, \ } #define ROT_Z(a) \ { \ { cosf(a), sinf(a), 0, 0 }, \ { -sinf(a), cosf(a), 0, 0 }, \ { 0, 0, 1, 0 }, \ { 0, 0, 0, 1 }, \ } 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_X: rot_axis = AXIS_X; break; case GLFW_KEY_Y: rot_axis = AXIS_Y; break; case GLFW_KEY_Z: rot_axis = AXIS_Z; break; } } static mat4_t mul(mat4_t m, mat4_t n) { #define ELEM(i, j) \ m.x.i *n.j.x + m.y.i *n.j.y + m.z.i *n.j.z + m.w.i *n.j.w return (mat4_t) { { ELEM(x, x), ELEM(y, x), ELEM(z, x), ELEM(w, x) }, { ELEM(x, y), ELEM(y, y), ELEM(z, y), ELEM(w, y) }, { ELEM(x, z), ELEM(y, z), ELEM(z, z), ELEM(w, z) }, { ELEM(x, w), ELEM(y, w), ELEM(z, w), ELEM(w, w) }, }; #undef MUL_ELEM } static mat4_t persp(float aspect, float fov, float ncp, float fcp) { const float r = 2 * ncp * tanf(fov / 2); const float t = r * aspect; return (mat4_t) { { ncp / t, 0, 0, 0 }, { 0, -ncp / r, 0, 0 }, { 0, 0, fcp / (fcp - ncp), 1 }, { 0, 0, -fcp * ncp / (fcp - ncp), 0 }, }; } int main() { // 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 const gpu_config_t gpu_config = { .application_name = "Foo", .window = window, .vertex_data = vertices, .vertex_data_size = sizeof(vertices), .index_data = indices, .index_data_size = sizeof(indices), }; gpu_ctx_t gpu; gpu_init(&gpu, &gpu_config); mvp_t mvp = { .model = SCALE(2), .view = TRANSLATE(0, 0, 4.0), .proj = persp((float)W / H, M_PI / 6, 0.1, 10.0), }; const mat4_t rotx = ROT_X(M_PI / 128); const mat4_t roty = ROT_Y(M_PI / 128); const mat4_t rotz = ROT_Z(M_PI / 128); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); switch (rot_axis) { case AXIS_X: mvp.model = mul(rotx, mvp.model); break; case AXIS_Y: mvp.model = mul(roty, mvp.model); break; case AXIS_Z: mvp.model = mul(rotz, mvp.model); break; } gpu_render(&gpu, &mvp); } // Clean up gpu_cleanup(&gpu); glfwDestroyWindow(window); glfwTerminate(); return 0; }