From 3f1786b28199d3b82e4008e873883ea5e777b17b Mon Sep 17 00:00:00 2001 From: Frothy <76622149+FrothyMarrow@users.noreply.github.com> Date: Tue, 21 May 2024 20:16:36 -0400 Subject: [PATCH] feat: zig rewrite --- build.zig | 23 ++-- include/vector.h | 13 -- src/app.zig | 45 +++++++ src/main.c | 316 ----------------------------------------------- src/render.zig | 30 +++++ src/vector.c | 33 ----- src/window.zig | 84 +++++++++++++ 7 files changed, 169 insertions(+), 375 deletions(-) delete mode 100644 include/vector.h create mode 100644 src/app.zig delete mode 100644 src/main.c create mode 100644 src/render.zig delete mode 100644 src/vector.c create mode 100644 src/window.zig diff --git a/build.zig b/build.zig index 8ab4111..ec0c18a 100644 --- a/build.zig +++ b/build.zig @@ -11,29 +11,26 @@ pub fn build(b: *std.Build) void { .link_libc = true, .optimize = mode, .target = target, + .root_source_file = .{ + .src_path = .{ + .owner = b, + .sub_path = "src/app.zig", + }, + }, }); phy.defineCMacro("GL_SILENCE_DEPRECATION", &.{}); phy.defineCMacro("GLFW_INCLUDE_GLCOREARB", &.{}); - phy.addIncludePath(.{ - .src_path = .{ .owner = b, .sub_path = "include" }, - }); - phy.addCSourceFiles(.{ - .root = .{ - .src_path = .{ .owner = b, .sub_path = "src" }, - }, - .files = &.{ - "main.c", - "vector.c", - }, - }); phy.linkSystemLibrary("glfw"); phy.linkFramework("OpenGL"); b.installArtifact(phy); const phy_run = b.addRunArtifact(phy); - const run_step = b.step("run", "Run the phy binary"); + const run_step = b.step( + "run", + "Run the phy binary", + ); run_step.dependOn(&phy_run.step); } diff --git a/include/vector.h b/include/vector.h deleted file mode 100644 index 1e38c68..0000000 --- a/include/vector.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -typedef float Vector3f[3]; - -void vec3_add(Vector3f a, Vector3f b, Vector3f dest); - -void vec3_sub(Vector3f a, Vector3f b, Vector3f dest); - -float vec3_dot(Vector3f a, Vector3f b); - -void vec3_cross(Vector3f a, Vector3f b, Vector3f dest); - -void vec3_normalize(Vector3f a); diff --git a/src/app.zig b/src/app.zig new file mode 100644 index 0000000..6dfc706 --- /dev/null +++ b/src/app.zig @@ -0,0 +1,45 @@ +const std = @import("std"); +const win = @import("window.zig"); +const render = @import("render.zig"); + +const AppError = error{ + WindowCreationError, + RendererCreationError, +}; + +pub fn main() AppError!void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const allocator = gpa.allocator(); + + const window = win.create(allocator, .{ + .title = "Phy", + .width = 800, + .height = 600, + }) catch { + std.debug.print("Failed to create App window\n", .{}); + return error.WindowCreationError; + }; + + defer allocator.destroy(window); + defer window.deinit(); + + const renderer = render.create(allocator) catch { + std.debug.print("Failed to create App renderer\n", .{}); + return error.RendererCreationError; + }; + + defer allocator.destroy(renderer); + + while (!window.shouldClose()) { + window.pollEvents(); + + renderer.clearColor(.{ + .r = 0.2, + .g = 0.3, + .b = 0.3, + .a = 1.0, + }); + + window.swapBuffers(); + } +} diff --git a/src/main.c b/src/main.c deleted file mode 100644 index c0ceb8f..0000000 --- a/src/main.c +++ /dev/null @@ -1,316 +0,0 @@ -#include "vector.h" - -#include - -#include -#include -#include - -#define DEG_TO_RAD M_PI / 180 - -#define WIDTH 800 -#define HEIGHT 600 - -void glfwErrorCallback(int errorCode, const char *description); - -void glfwKeyCallback(GLFWwindow *window, int key, int scancode, int action, - int mods); - -unsigned int createShader(const char *filename, GLenum shaderType); - -unsigned int createShaderProgram(unsigned int vertexShader, - unsigned int fragmentShader); - -void createProjection(float fovy, float aspectRatio, float front, float back, - float *dest); - -void lookAt(Vector3f from, Vector3f to, Vector3f up, float *dest); - -int main(void) { - if (!glfwInit()) { - printf("Failed to intialize GLFW!\n"); - return 1; - } - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - glfwSetErrorCallback(glfwErrorCallback); - - GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Phy", NULL, NULL); - - glfwMakeContextCurrent(window); - - glfwSetKeyCallback(window, glfwKeyCallback); - - if (!window) { - printf("Failed to create GLFW window!\n"); - glfwTerminate(); - return 1; - } - - float vertices[] = { - // clang-format off - -0.5f, -0.5f, -0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, - -0.5f, -0.5f, 0.5f, - 0.5f, -0.5f, 0.5f, - 0.5f, 0.5f, 0.5f, - -0.5f, 0.5f, 0.5f, - - -0.5f, 0.5f, -0.5f, - -0.5f, -0.5f, -0.5f, - -0.5f, -0.5f, 0.5f, - -0.5f, 0.5f, 0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, 0.5f, -0.5f, - 0.5f, 0.5f, 0.5f, - 0.5f, -0.5f, 0.5f, - - -0.5f, -0.5f, -0.5f, - 0.5f, -0.5f, -0.5f, - 0.5f, -0.5f, 0.5f, - -0.5f, -0.5f, 0.5f, - 0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, -0.5f, - -0.5f, 0.5f, 0.5f, - 0.5f, 0.5f, 0.5f, - // clang-format on - }; - - unsigned int indices[] = { - // clang-format off - 0, 3, 2, - 2, 1, 0, - 4, 5, 6, - 6, 7 ,4, - - 11, 8, 9, - 9, 10, 11, - 12, 13, 14, - 14, 15, 12, - - 16, 17, 18, - 18, 19, 16, - 20, 21, 22, - 22, 23, 20 - // clang-format on - }; - - unsigned int vertexArray = 0; - glGenVertexArrays(1, &vertexArray); - - glBindVertexArray(vertexArray); - - unsigned int vertexBuffer = 0; - glGenBuffers(1, &vertexBuffer); - - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); - glEnableVertexAttribArray(0); - - unsigned int elementBuffer = 0; - glGenBuffers(1, &elementBuffer); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, - GL_STATIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - - unsigned int vertexShader = - createShader("./shader/vertex.glsl", GL_VERTEX_SHADER); - unsigned int fragmentShader = - createShader("./shader/fragment.glsl", GL_FRAGMENT_SHADER); - - unsigned int shaderProgram = - createShaderProgram(vertexShader, fragmentShader); - - glUseProgram(shaderProgram); - glBindVertexArray(vertexArray); - - glEnable(GL_DEPTH_TEST); - - Vector3f from = {0, 0, 1}; - - glfwSetWindowUserPointer(window, from); - - while (!glfwWindowShouldClose(window)) { - glfwPollEvents(); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); - - int uProjection = glGetUniformLocation(shaderProgram, "uProjection"); - - float projection[16] = {0}; - createProjection(90, (float)WIDTH / HEIGHT, 0.1f, 10.0f, projection); - - glUniformMatrix4fv(uProjection, 1, GL_FALSE, projection); - - int uView = glGetUniformLocation(shaderProgram, "uView"); - - float view[16] = {0}; - Vector3f to = {from[0], from[1], from[2] - 1}; - Vector3f up = {0.0f, 1.0f, 0.0f}; - lookAt(from, to, up, view); - - glUniformMatrix4fv(uView, 1, GL_FALSE, view); - - glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); - - glfwSwapBuffers(window); - } - - glDeleteBuffers(1, &vertexBuffer); - glDeleteVertexArrays(1, &vertexArray); - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - glDeleteProgram(shaderProgram); - - glfwDestroyWindow(window); - glfwTerminate(); - - return 0; -} - -void glfwErrorCallback(int errorCode, const char *description) { - printf("GLFW Error: %d, %s\n", errorCode, description); -} - -void glfwKeyCallback(GLFWwindow *window, int key, int scancode, int action, - int mods) { - - if (action != GLFW_PRESS && action != GLFW_REPEAT) - return; - - Vector3f *from = (Vector3f *)glfwGetWindowUserPointer(window); - float delta = 0.1f; - - switch (key) { - case GLFW_KEY_UP: - from[0][1] += delta; - break; - case GLFW_KEY_DOWN: - from[0][1] += -delta; - break; - case GLFW_KEY_RIGHT: - from[0][0] += delta; - break; - case GLFW_KEY_LEFT: - from[0][0] += -delta; - break; - case GLFW_KEY_SPACE: - from[0][2] += delta; - break; - case GLFW_KEY_LEFT_CONTROL: - from[0][2] += -delta; - break; - } -} - -unsigned int createShader(const char *filename, GLenum shaderType) { - FILE *file = fopen(filename, "r"); - - if (!file) { - printf("Failed to open file: %s\n", filename); - return 0; - } - - fseek(file, 0, SEEK_END); - long filesize = ftell(file); - fseek(file, 0, SEEK_SET); - - char *shaderSource = malloc(filesize + 1); - fread(shaderSource, filesize, 1, file); - - shaderSource[filesize] = '\0'; - - fclose(file); - - unsigned int shader = 0; - shader = glCreateShader(shaderType); - - glShaderSource(shader, 1, (const char **)&shaderSource, NULL); - glCompileShader(shader); - - free(shaderSource); - - int shaderCompiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompiled); - - if (!shaderCompiled) { - printf("Shader compilation failed\n"); - return 0; - } - - return shader; -} - -unsigned int createShaderProgram(unsigned int vertexShader, - unsigned int fragmentShader) { - unsigned int shaderProgram; - shaderProgram = glCreateProgram(); - - glAttachShader(shaderProgram, vertexShader); - glAttachShader(shaderProgram, fragmentShader); - glLinkProgram(shaderProgram); - - int shaderProgramLinked = 0; - glGetProgramiv(shaderProgram, GL_LINK_STATUS, &shaderProgramLinked); - - if (!shaderProgramLinked) { - printf("Shader program linking failed"); - return 0; - } - - return shaderProgram; -} - -void createProjection(float fovy, float aspectRatio, float front, float back, - float *dest) { - float tangent = tan(fovy / 2 * DEG_TO_RAD); - float top = front * tangent; - float right = top * aspectRatio; - - dest[0] = front / right; - dest[5] = front / top; - dest[10] = -(back + front) / (back - front); - dest[11] = -1; - dest[14] = -(2 * back * front) / (back - front); - dest[15] = 0; -} - -void lookAt(Vector3f from, Vector3f to, Vector3f up, float *dest) { - Vector3f forward = {0}; - vec3_sub(from, to, forward); - vec3_normalize(forward); - - Vector3f left = {0}; - vec3_cross(up, forward, left); - vec3_normalize(left); - - Vector3f actualUp = {0}; - vec3_cross(forward, left, actualUp); - dest[0] = left[0]; - dest[4] = left[1]; - dest[8] = left[2]; - dest[1] = up[0]; - dest[5] = up[1]; - dest[9] = up[2]; - dest[2] = forward[0]; - dest[6] = forward[1]; - dest[10] = forward[2]; - - dest[12] = -vec3_dot(left, from); - dest[13] = -vec3_dot(actualUp, from); - dest[14] = -vec3_dot(forward, from); - dest[15] = 1; -} diff --git a/src/render.zig b/src/render.zig new file mode 100644 index 0000000..ea53e22 --- /dev/null +++ b/src/render.zig @@ -0,0 +1,30 @@ +const std = @import("std"); +const c = @cImport({ + @cInclude("OpenGL/gl3.h"); +}); + +const Color = struct { + r: f32, + g: f32, + b: f32, + a: f32, +}; + +const Renderer = struct { + pub fn clearColor(_: *Renderer, color: Color) void { + c.glClear(c.GL_COLOR_BUFFER_BIT); + c.glClearColor(color.r, color.g, color.b, color.a); + } +}; + +const RendererError = error{ + FailedToAllocateRenderer, +}; + +pub fn create(allocator: std.mem.Allocator) RendererError!*Renderer { + const renderer = allocator.create(Renderer) catch { + std.debug.print("Failed to allocate Renderer\n", .{}); + return RendererError.FailedToAllocateRenderer; + }; + return renderer; +} diff --git a/src/vector.c b/src/vector.c deleted file mode 100644 index 4897a5f..0000000 --- a/src/vector.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "vector.h" - -#include -#include - -void vec3_add(Vector3f a, Vector3f b, Vector3f dest) { - dest[0] = a[0] + b[0]; - dest[1] = a[1] + b[1]; - dest[2] = a[2] + b[2]; -} - -void vec3_sub(Vector3f a, Vector3f b, Vector3f dest) { - dest[0] = a[0] - b[0]; - dest[1] = a[1] - b[1]; - dest[2] = a[2] - b[2]; -} - -void vec3_cross(Vector3f a, Vector3f b, Vector3f dest) { - dest[0] = a[1] * b[2] - a[2] * b[1]; - dest[1] = a[2] * b[0] - a[0] * b[2]; - dest[2] = a[0] * b[1] - a[1] * b[0]; -} - -float vec3_dot(Vector3f a, Vector3f b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; -} - -void vec3_normalize(Vector3f a) { - float length = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); - a[0] /= length; - a[1] /= length; - a[2] /= length; -} diff --git a/src/window.zig b/src/window.zig new file mode 100644 index 0000000..abd1e06 --- /dev/null +++ b/src/window.zig @@ -0,0 +1,84 @@ +const std = @import("std"); +const c = @cImport({ + @cInclude("GLFW/glfw3.h"); +}); + +const WindowSpec = struct { + title: []const u8, + width: u32, + height: u32, +}; + +pub const Window = struct { + windowPtr: *c.struct_GLFWwindow, + spec: WindowSpec, + + pub fn shouldClose(self: *Window) bool { + return c.glfwWindowShouldClose(self.windowPtr) != 0; + } + + pub fn swapBuffers(self: *Window) void { + c.glfwSwapBuffers(self.windowPtr); + } + + pub fn pollEvents(_: *Window) void { + c.glfwPollEvents(); + } + + pub fn deinit(self: *Window) void { + c.glfwDestroyWindow(self.windowPtr); + c.glfwTerminate(); + } +}; + +pub const WindowError = error{ + GlfwInitFailed, + GlfwCreateWindowFailed, +}; + +pub fn create(allocator: std.mem.Allocator, spec: WindowSpec) WindowError!*Window { + if (c.glfwInit() == 0) { + std.debug.print("Failed to initialize GLFW\n", .{}); + return WindowError.GlfwInitFailed; + } + + c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 3); + c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 3); + c.glfwWindowHint(c.GLFW_OPENGL_PROFILE, c.GLFW_OPENGL_CORE_PROFILE); + c.glfwWindowHint(c.GLFW_RESIZABLE, c.GLFW_FALSE); + + _ = c.glfwSetErrorCallback(glfwErrorCallback); + + const window = allocator.create(Window) catch { + std.debug.print("Failed to allocate Window struct\n", .{}); + return WindowError.GlfwCreateWindowFailed; + }; + + const windowPtr = c.glfwCreateWindow( + @intCast(spec.width), + @intCast(spec.height), + spec.title.ptr, + null, + null, + ) orelse { + std.debug.print("Failed to create GLFW window\n", .{}); + c.glfwTerminate(); + return WindowError.GlfwCreateWindowFailed; + }; + + c.glfwMakeContextCurrent(windowPtr); + + window.* = .{ + .windowPtr = windowPtr, + .spec = spec, + }; + + return window; +} + +fn glfwErrorCallback(errorCode: c_int, description: [*c]const u8) callconv(.C) void { + std.debug.print("GLFW error: {}\n", .{errorCode}); + if (description != null) { + std.debug.print("Description: {?s}\n", .{description}); + } +}