This commit is contained in:
Daniel Ledda
2025-01-12 23:40:39 +01:00
parent 25384c743d
commit c0deceec65
9 changed files with 247 additions and 98 deletions

View File

@@ -1,9 +1,9 @@
#include <iostream>
// stdlib TODO(djledda): get rid of this
#include <vector>
// Graphics bindings and libs
#include "lib/glad/glad.c"
#include <GLFW/glfw3.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/ext/matrix_transform.hpp>
#include <glm/glm.hpp>
@@ -11,31 +11,49 @@
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
// Project
#include "SomaSolve.cpp" // errors from iostream also defining the keyword `global`
#include "gfx/gfx.cpp"
#include "VoxelSpace.cpp"
#include "SomaSolve.cpp"
#include "./tests.cpp"
#include "lib/djstdlib/core.cpp"
// Library initialisation
#define STB_IMAGE_IMPLEMENTATION
#include "lib/loaders/stb_image.h"
#include "./tests.cpp"
#define TINYOBJLOADER_IMPLEMENTATION
#include "lib/loaders/tinyobj.h"
struct Entity;
struct Polycube;
struct SceneGraphNode;
uint32 new_entity();
Entity *get_entity(int id);
Entity *get_entity(uint32 id);
SceneGraphNode *get_scene_graph_node(int id);
uint32 new_graph_node();
void print_mat(glm::mat4* matrix) {
void log(glm::vec3* vector) {
glm::vec3 vec = *vector;
log(
"┌ ┐\n"
"│%7.2f%, %7.2f, %7.2f │\n"
"└ ┘\n",
vec[0], vec[1], vec[2]);
}
void log(glm::mat4* matrix) {
glm::mat4 mat = *matrix;
std::cout << mat[0][0] << mat[0][1] << mat[0][2] << mat[0][3] << std::endl;
std::cout << mat[1][0] << mat[1][1] << mat[1][2] << mat[1][3] << std::endl;
std::cout << mat[2][0] << mat[2][1] << mat[2][2] << mat[2][3] << std::endl;
std::cout << mat[3][0] << mat[3][1] << mat[3][2] << mat[3][3] << std::endl;
std::cout << std::endl;
log(
"┌ ┐\n"
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
"└ ┘\n",
mat[0][0], mat[0][1], mat[0][2], mat[0][3],
mat[1][0], mat[1][1], mat[1][2], mat[1][3],
mat[2][0], mat[2][1], mat[2][2], mat[2][3],
mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
}
struct Camera {
@@ -64,15 +82,6 @@ void camera_set_up(Camera *c, real32 up_x, real32 up_y, real32 up_z) {
c->up = glm::vec3(up_x, up_y, up_z);
}
struct GlobalAppState {
uint32 current_polycube;
uint32 last_polycube_visible;
Shader *active_shader;
std::vector<Polycube> polycubes;
};
GlobalAppState app_state = {};
struct WindowDims {
uint32 width;
uint32 height;
@@ -95,10 +104,21 @@ struct SceneGraphNode {
uint32 entity;
};
struct GlobalAppState {
bool wireframe = false;
uint32 current_polycube;
uint32 last_polycube_visible;
uint32 light;
Shader *active_shader;
std::vector<Polycube> polycubes;
};
GlobalAppState app_state = {};
void init_sg_node(SceneGraphNode *n) {
n->scale = glm::vec3(1.0f, 1.0f, 1.0f);
n->translation = glm::vec3(0.0f, 0.0f, 0.0f);
n->rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
n->rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
n->local = glm::mat4(1.0f);
n->world = n->local;
}
@@ -189,11 +209,12 @@ GLFWwindow *init_window_and_gl(WindowDims *window_dims) {
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
glEnable(GL_DEPTH_TEST);
return window;
}
void gl_update_viewport(WindowDims* window_dims, Frame* frame) {
void update_viewport_from_frame(WindowDims* window_dims, Frame* frame) {
glViewport(frame->x, window_dims->height - frame->y - frame->height, frame->width, frame->height);
}
@@ -202,32 +223,96 @@ Texture wall_tex = {0};
std::vector<Entity> entities = std::vector<Entity>();
std::vector<SceneGraphNode> scene_graph_nodes = std::vector<SceneGraphNode>();
void process_input(GLFWwindow *window) {
local_persist bool wireframe = false;
local_persist bool last_frame_state_press_enter = false;
local_persist bool last_frame_state_press = false;
struct Input {
struct {
bool escape;
bool enter;
bool space;
bool lshift;
bool x;
bool y;
bool z;
} keyboard;
struct {
real64 x;
real64 y;
bool btnLeft;
bool btnRight;
bool btnMiddle;
} mouse;
};
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
inline bool glfwMouse(GLFWwindow *window, int mouseBtnCode) {
switch (glfwGetMouseButton(window, mouseBtnCode)) {
case GLFW_RELEASE: return false;
case GLFW_PRESS: return true;
default: return false;
}
}
inline bool glfwKey(GLFWwindow *window, int keyCode) {
switch (glfwGetKey(window, keyCode)) {
case GLFW_RELEASE: return false;
case GLFW_PRESS: return true;
default: return false;
}
}
Input get_current_input(GLFWwindow *window) {
Input input = {0};
input.keyboard.escape = glfwKey(window, GLFW_KEY_ESCAPE);
input.keyboard.enter = glfwKey(window, GLFW_KEY_ENTER);
input.keyboard.space = glfwKey(window, GLFW_KEY_SPACE);
input.keyboard.lshift = glfwKey(window, GLFW_KEY_LEFT_SHIFT);
input.keyboard.x = glfwKey(window, GLFW_KEY_X);
input.keyboard.y = glfwKey(window, GLFW_KEY_Y);
input.keyboard.z = glfwKey(window, GLFW_KEY_Z);
input.mouse.btnLeft = glfwMouse(window, GLFW_MOUSE_BUTTON_LEFT);
input.mouse.btnRight = glfwMouse(window, GLFW_MOUSE_BUTTON_RIGHT);
input.mouse.btnMiddle = glfwMouse(window, GLFW_MOUSE_BUTTON_MIDDLE);
glfwGetCursorPos(window, &input.mouse.x, &input.mouse.y);
return input;
}
void process_input(GLFWwindow *window, Input *input, Input *prevInput) {
if (input->keyboard.escape) {
glfwSetWindowShouldClose(window, true);
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS && !last_frame_state_press) {
glPolygonMode(GL_FRONT_AND_BACK, !wireframe ? GL_LINE : GL_FILL);
wireframe = !wireframe;
last_frame_state_press = true;
} else if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_RELEASE) {
last_frame_state_press = false;
}
if (input->keyboard.space && !prevInput->keyboard.space) {
glPolygonMode(GL_FRONT_AND_BACK, !app_state.wireframe ? GL_LINE : GL_FILL);
app_state.wireframe = !app_state.wireframe;
}
if (glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS && !last_frame_state_press_enter) {
SceneGraphNode *node = get_scene_graph_node(get_entity(app_state.light)->scene_graph_node);
int shiftMultiplier = input->keyboard.lshift ? -1 : 1;
node->translation.x += 1.0 * input->keyboard.x * shiftMultiplier;
node->translation.y += 1.0 * input->keyboard.y * shiftMultiplier;
node->translation.z += 1.0 * input->keyboard.z * shiftMultiplier;
if (input->keyboard.enter && !prevInput->keyboard.enter) {
if (app_state.current_polycube == 6) {
app_state.current_polycube = 0;
} else {
app_state.current_polycube += 1;
}
last_frame_state_press_enter = true;
} else if (glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_RELEASE) {
last_frame_state_press_enter = false;
}
if (input->mouse.btnLeft) {
real64 deltaX = (input->mouse.x - prevInput->mouse.x) * 0.006;
Polycube *current_polycube = &app_state.polycubes[app_state.current_polycube];
SceneGraphNode *polycube_graph_node = get_scene_graph_node(current_polycube->graph_node);
if (deltaX > 0.00000001 || deltaX < -0.00000001) {
polycube_graph_node->rotation = glm::quat(glm::vec3(0, deltaX, 0)) * polycube_graph_node->rotation;
}
real64 deltaY = (input->mouse.y - prevInput->mouse.y) * 0.006;
if (deltaY > 0.00000001 || deltaY < -0.00000001) {
polycube_graph_node->rotation = polycube_graph_node->rotation * glm::quat(glm::vec3(deltaY, 0, 0));
}
}
}
@@ -240,7 +325,7 @@ uint32 new_entity() {
return (uint32)entities.size();
}
Entity *get_entity(int id) {
Entity *get_entity(uint32 id) {
return &entities[id - 1];
}
@@ -312,16 +397,20 @@ int main_gfx() {
app_state.last_polycube_visible = 6;
app_state.active_shader = 0;
app_state.polycubes = {};
app_state.light = new_entity();
Shader phong_shader = createShader("../assets/shaders/phong-solid.vertex.glsl"_s, "../assets/shaders/phong-solid.fragment.glsl"_s);
SceneGraphNode *light_graph_node = get_scene_graph_node(get_entity(app_state.light)->scene_graph_node);
light_graph_node->translation = glm::vec3(4.0f, 24.0f, 6.0f);
Shader phong_shader = createShader(
"./assets/shaders/phong-solid.vertex.glsl"_s,
"./assets/shaders/phong-solid.fragment.glsl"_s);
app_state.active_shader = &phong_shader;
cube_mesh = createMesh("../assets/models/c000000.obj");
wall_tex = createTexture("../assets/textures/brick-wall.jpg");
cube_mesh = createMesh("./assets/models/c000000.obj");
wall_tex = createTexture("./assets/textures/brick-wall.jpg");
Frame little_frame = createFrame(arena, 80, 60, 20, 20);
Frame big_frame = createFrame(arena, 800, 600, 0, 0);
Frame *frames[] = { &big_frame, &little_frame };
Frame main_frame = createFrame(arena, 800, 600, 0, 0);
SceneGraphNode root_node = {};
init_sg_node(&root_node);
@@ -335,27 +424,28 @@ int main_gfx() {
root_node.children.push_back(app_state.polycubes.back().graph_node);
}
big_frame.cam->pos = glm::vec3(0.0f, 4.0f, 4.0f);
camera_look_at(big_frame.cam, 0.0f, 0.0f, 0.0f);
glm::vec3 light_pos = glm::vec3(-15.0f, 10.0f, 6.0f);
main_frame.cam->pos = glm::vec3(4.0f, 4.0f, 4.0f);
camera_look_at(main_frame.cam, 0.0f, 0.0f, 0.0f);
glUseProgram(app_state.active_shader->prog_id);
glUniform3fv(
glGetUniformLocation(app_state.active_shader->prog_id, "light_pos"),
1, glm::value_ptr(light_pos));
glUniformMatrix4fv(
glGetUniformLocation(app_state.active_shader->prog_id, "projection"),
1, GL_FALSE, glm::value_ptr(big_frame.cam->proj));
glUniformMatrix4fv(
glGetUniformLocation(app_state.active_shader->prog_id, "view"),
1, GL_FALSE, glm::value_ptr(big_frame.cam->view));
setUniformMat4fv(app_state.active_shader, "projection", &main_frame.cam->proj);
setUniformMat4fv(app_state.active_shader, "view", &main_frame.cam->view);
real64 last_frame = glfwGetTime();
real64 time_delta = 1.0f/60.0f;
glm::vec3 lastLightPos = {};
Input prevInput = {};
while (!glfwWindowShouldClose(window)) {
time_delta = glfwGetTime() - last_frame;
process_input(window);
glfwPollEvents();
Input input = get_current_input(window);
process_input(window, &input, &prevInput);
SceneGraphNode *light_graph_node = get_scene_graph_node(get_entity(app_state.light)->scene_graph_node);
setUniform3fv(app_state.active_shader, "light_pos", &light_graph_node->translation);
setUniform3fv(app_state.active_shader, "camera", &main_frame.cam->pos);
if (app_state.last_polycube_visible != app_state.current_polycube) {
hide_polycube(&app_state.polycubes[app_state.last_polycube_visible]);
@@ -366,20 +456,19 @@ int main_gfx() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
gl_update_viewport(&window_dims, &big_frame);
update_viewport_from_frame(&window_dims, &main_frame);
Polycube *current_polycube = &app_state.polycubes[app_state.current_polycube];
get_scene_graph_node(current_polycube->graph_node)->rotation = glm::quat(glm::vec3(0, glfwGetTime() / 2, 0));
glBindVertexArray(cube_mesh.vao);
recalculate_scene_graph(&root_node);
GLint model_uniform_loc = glGetUniformLocation(app_state.active_shader->prog_id, "model");
glUniform3fv(
glGetUniformLocation(app_state.active_shader->prog_id, "solid_color"),
1, glm::value_ptr(current_polycube->color));
setUniform3fv(app_state.active_shader, "solid_color", &current_polycube->color);
int model_uniform = getUniformLocation(app_state.active_shader, "model");
for (Entity &entity : entities) {
if (entity.visible) {
glUniformMatrix4fv(model_uniform_loc, 1, GL_FALSE, glm::value_ptr(get_scene_graph_node(entity.scene_graph_node)->world));
setUniformMat4fv(model_uniform, &get_scene_graph_node(entity.scene_graph_node)->world);
glBindTexture(GL_TEXTURE_2D, entity.tex->tex_id);
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)entity.mesh->num_indices);
//glDrawElements(GL_TRIANGLES, entity->mesh->num_indices, GL_UNSIGNED_INT, 0);
@@ -387,7 +476,7 @@ int main_gfx() {
}
glfwSwapBuffers(window);
glfwPollEvents();
prevInput = input;
}
glfwTerminate();