feat: add model matrix transformation hierarchy and delta time tracking
This commit is contained in:
@@ -20,7 +20,9 @@ add_executable(BeyondDepth src/main.c
|
||||
external/glad/src/glad.c
|
||||
src/engine/renderer/shaders/shader.c
|
||||
src/engine/renderer/shaders/shader.h
|
||||
src/engine/renderer/data/engine_data.h)
|
||||
src/engine/renderer/data/engine_data.h
|
||||
src/engine/renderer/mesh/mesh.c
|
||||
src/engine/renderer/mesh/mesh.h)
|
||||
|
||||
set_target_properties(BeyondDepth PROPERTIES WIN32_EXECUTABLE FALSE)
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "camera.h"
|
||||
#include "../..//core/logger/log.h"
|
||||
#include <cglm/cglm.h>
|
||||
#include "../shaders/shader.h"
|
||||
|
||||
void camera_init(Camera *self, vec3 initial_position, int width, int height) {
|
||||
// copy initial_pos vector
|
||||
@@ -16,9 +18,11 @@ void camera_init(Camera *self, vec3 initial_position, int width, int height) {
|
||||
glm_vec3_copy((vec3){0.0f, 1.0f, 0.0f}, self->Up);
|
||||
|
||||
// initialize controls and viewport
|
||||
self->speed = 0.1f;
|
||||
self->sensitivity = 100.0f;
|
||||
self->speed = 0.9f;
|
||||
self->sensitivity = 3.5f;
|
||||
self->FOV_deg = 45.0f;
|
||||
self->yaw = -90.0f;
|
||||
self->pitch = 0.0f;
|
||||
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
@@ -27,13 +31,6 @@ void camera_init(Camera *self, vec3 initial_position, int width, int height) {
|
||||
glm_mat4_identity(self->View);
|
||||
}
|
||||
|
||||
/*
|
||||
Camera l_camera = {
|
||||
.Position = { 0.0f, 0.0f, 0.0f },
|
||||
.Orientation = { 0.0f, 0.0f, -1.0f },
|
||||
.Up = { 0.0f, 1.0f, 0.0f }
|
||||
};*/
|
||||
|
||||
void camera_update_view_matrix(Camera *self) {
|
||||
// calc the center or target point (Pos + Orientation)
|
||||
vec3 target;
|
||||
@@ -50,31 +47,81 @@ void camera_update_projection(Camera *self, float nearPlane, float farPlane, mat
|
||||
|
||||
// TODO: Update matrix function signature to accept camera entity?
|
||||
// change name to camera_upload_matrix for clarity?
|
||||
void camera_matrix_to_shader(Camera *self, GLuint shader_program_ID, const char *uniform_name) {
|
||||
void camera_matrix_to_shader(Camera *self, Shader *shader, const char *uniform_name) {
|
||||
// update the view matrix first, camera position might have moved
|
||||
camera_update_view_matrix(self);
|
||||
|
||||
// calculate projection matrix (P) with temporary matrix 'projection' for the result
|
||||
mat4 projection;
|
||||
camera_update_projection(self, 0.1f, 100.0f, projection);
|
||||
camera_update_projection(self, 0.001f, 100.0f, projection);
|
||||
|
||||
// combine the matrices -- P * V -> PV
|
||||
mat4 view_projection;
|
||||
glm_mat4_mul(projection, self->View, view_projection);
|
||||
|
||||
// get uniform location
|
||||
GLint uniform_location = glGetUniformLocation(shader_program_ID, uniform_name);
|
||||
GLint uniform_location = shader->camMatrixLocation;
|
||||
|
||||
if (uniform_location == -1) {
|
||||
log_error("Warning: Uniform '%s' not found in shader program %u.\n", uniform_name, shader_program_ID);
|
||||
// log_error("Warning: Uniform '%s' not found in shader program %u.\n", uniform_name, shader);
|
||||
return;
|
||||
}
|
||||
|
||||
// upload combined matrix to the shader
|
||||
// view_projection[0] array pointer decays to first value
|
||||
glUniformMatrix4fv(uniform_location, 1, GL_FALSE, view_projection[0]);
|
||||
glUniformMatrix4fv(uniform_location, 1, GL_FALSE, *view_projection);
|
||||
}
|
||||
|
||||
void camera_inputs(Camera *self, SDL_Event *event) {
|
||||
// TODO: implementation for handling keyboard/mouse inputs for camera
|
||||
void camera_process_keyboard(Camera *self, const Uint8 *keyState, float deltaTime) {
|
||||
vec3 move;
|
||||
float current_speed = self->speed * deltaTime;
|
||||
|
||||
// forward/back
|
||||
if (keyState[SDL_SCANCODE_W]) {
|
||||
glm_vec3_scale(self->Orientation, current_speed, move);
|
||||
glm_vec3_add(self->Position, move, self->Position);
|
||||
}
|
||||
|
||||
if (keyState[SDL_SCANCODE_S]) {
|
||||
glm_vec3_scale(self->Orientation, current_speed, move);
|
||||
glm_vec3_sub(self->Position, move, self->Position);
|
||||
}
|
||||
|
||||
// strafe left/right
|
||||
vec3 right;
|
||||
glm_vec3_cross(self->Orientation, self->Up, right);
|
||||
glm_vec3_normalize(right);
|
||||
|
||||
if (keyState[SDL_SCANCODE_A]) {
|
||||
glm_vec3_scale(right, current_speed, move);
|
||||
glm_vec3_sub(self->Position, move, self->Position);
|
||||
}
|
||||
|
||||
if (keyState[SDL_SCANCODE_D]) {
|
||||
glm_vec3_scale(right, current_speed, move);
|
||||
glm_vec3_add(self->Position, move, self->Position);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add deltaTime arg for smoother rotation
|
||||
void camera_process_mouse(Camera *self, float xoffset, float yoffset, float deltaTime) {
|
||||
float effective_sensitivity = self->sensitivity * deltaTime;
|
||||
xoffset *= effective_sensitivity;
|
||||
yoffset *= effective_sensitivity;
|
||||
|
||||
self->yaw += xoffset;
|
||||
self->pitch += yoffset;
|
||||
|
||||
// clamps the pitch to prevent camera from flipping upside down
|
||||
if (self->pitch > 89.0f)
|
||||
self->pitch = 89.0f;
|
||||
if (self->pitch < -89.0f)
|
||||
self->pitch = -89.0f;
|
||||
|
||||
// calc new orientation vector from yaw and pitch
|
||||
vec3 new_orientation;
|
||||
new_orientation[0] = cos(glm_rad(self->yaw)) * cos(glm_rad(self->pitch));
|
||||
new_orientation[1] = sin(glm_rad(self->pitch));
|
||||
new_orientation[2] = sin(glm_rad(self->yaw)) * cos(glm_rad(self->pitch));
|
||||
glm_vec3_normalize_to(new_orientation, self->Orientation);
|
||||
}
|
||||
@@ -13,6 +13,8 @@ typedef struct {
|
||||
vec3 Position;
|
||||
vec3 Orientation;
|
||||
vec3 Up;
|
||||
float yaw;
|
||||
float pitch;
|
||||
float speed;
|
||||
float sensitivity;
|
||||
float FOV_deg;
|
||||
@@ -32,9 +34,12 @@ void camera_update_view_matrix(Camera *self);
|
||||
void camera_update_projection(Camera *self, float nearPlane, float forPlane, mat4 dest);
|
||||
|
||||
// generates (projection * view) and uploads to the shader program
|
||||
void camera_matrix_to_shader(Camera *self, GLuint shader_program_ID, const char *uniform_name);
|
||||
void camera_matrix_to_shader(Camera *self, Shader *shader, const char *uniform_name);
|
||||
|
||||
// TODO: Input handling (needs full SDL context later)
|
||||
void camera_inputs(Camera *self, SDL_Event *event);
|
||||
|
||||
void camera_process_keyboard(Camera *self, const Uint8 *keystate, float deltaTime);
|
||||
void camera_process_mouse(Camera *self, float xoffset, float yoffset, float deltaTime);
|
||||
|
||||
#endif //CAMERA_H
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include "../camera/camera.h"
|
||||
#include "../mesh/mesh.h"
|
||||
|
||||
typedef struct {
|
||||
// Camera instance
|
||||
@@ -15,10 +16,17 @@ typedef struct {
|
||||
// Shader program instance
|
||||
Shader shader;
|
||||
|
||||
// Mesh instance
|
||||
Mesh triangle_mesh;
|
||||
mat4 pyramidModel;
|
||||
|
||||
// Keep track of window size
|
||||
int window_width;
|
||||
int window_height;
|
||||
|
||||
float lastFrameTime; // time of the previous frame
|
||||
float deltaTime; // time elapsed since the last frame
|
||||
|
||||
// TODO: Add other components, SDL_Window* or Meshes, etc...
|
||||
} Engine_Data;
|
||||
|
||||
|
||||
93
src/engine/renderer/mesh/mesh.c
Normal file
93
src/engine/renderer/mesh/mesh.c
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Created by Tristan on 10/17/2025.
|
||||
//
|
||||
|
||||
#include "mesh.h"
|
||||
#include "../../core/logger/log.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
GLfloat vertices[] = {
|
||||
// Position // Color
|
||||
// X Y Z R G B // Index
|
||||
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 0: Apex
|
||||
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 1: Base Corner 1 (Red)
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // 2: Base Corner 2 (Green)
|
||||
0.0f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f // 3: Base Corner 3 (Blue)
|
||||
};
|
||||
|
||||
const size_t vertices_size = sizeof(vertices);
|
||||
|
||||
GLuint indices[] = {
|
||||
// side 1: (Apex, C1, C2)
|
||||
0, 1, 2, // vertices that form the triangle
|
||||
|
||||
// side2: (Apex, C2, C3)
|
||||
0, 2, 3,
|
||||
|
||||
// side 3: (Apex, C3, C1)
|
||||
0, 3, 1,
|
||||
|
||||
// base: (C1, C3, C2) - order is crucial for culling
|
||||
1, 3, 2
|
||||
|
||||
};
|
||||
|
||||
void mesh_init(Mesh *self, GLfloat *vertices, GLsizei vertices_size, GLuint *indices, GLsizei num_indices) {
|
||||
self->num_indices = num_indices;
|
||||
|
||||
// generate buffers, vao, vbo, ebo
|
||||
glGenVertexArrays(1, &self->VAO);
|
||||
glGenBuffers(1, &self->VBO);
|
||||
glGenBuffers(1, &self->EBO);
|
||||
|
||||
// bind the VAO
|
||||
glBindVertexArray(self->VAO);
|
||||
|
||||
// bind and upload VBO data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self->VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices_size, vertices, GL_STATIC_DRAW);
|
||||
|
||||
// bind and upload ebo data
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * num_indices, indices, GL_STATIC_DRAW);
|
||||
|
||||
// configure vertex attributes
|
||||
// a. Position attribute (layout = 0)
|
||||
// 3 floats per pos, stride = 6 floats total (3 pos + 3 colour), offset is 0
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// b. Color attribute (layout = 1)
|
||||
// 3 floats per color, stride = 6 floats total, offset is 3 floats (after pos)
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
// TODO: hader also expects layout = 2 but lazy, pray no crash
|
||||
|
||||
// unbind the VAO (so it can't be modified)
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
log_info("Mesh initialized with VAO: %u", self->VAO);
|
||||
}
|
||||
|
||||
void mesh_draw(Mesh *self) {
|
||||
// bind the vao
|
||||
glBindVertexArray(self->VAO);
|
||||
|
||||
// draw the triangle
|
||||
glDrawElements(GL_TRIANGLES, self->num_indices, GL_UNSIGNED_INT, 0);
|
||||
|
||||
// unbind
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void mesh_delete(Mesh *self) {
|
||||
glDeleteVertexArrays(1, &self->VAO);
|
||||
glDeleteBuffers(1, &self->VBO);
|
||||
glDeleteBuffers(1, &self->EBO);
|
||||
self->VAO = 0;
|
||||
self->VBO = 0;
|
||||
self->EBO = 0;
|
||||
}
|
||||
43
src/engine/renderer/mesh/mesh.h
Normal file
43
src/engine/renderer/mesh/mesh.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Created by Tristan on 10/17/2025.
|
||||
//
|
||||
|
||||
#ifndef MESH_H
|
||||
#define MESH_H
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <cglm/cglm.h>
|
||||
|
||||
// Vertices for a simple 2D triangle (x, y, z)
|
||||
// Add (r, g, b) color data after each pos
|
||||
// X, Y, Z, R, G, B
|
||||
extern GLfloat vertices[];
|
||||
extern const size_t vertices_size;
|
||||
// Indices define the order vertices are drawn
|
||||
extern GLuint indices[];
|
||||
|
||||
#define INDICES_COUNT 12
|
||||
|
||||
typedef struct {
|
||||
// Vertex Array Object
|
||||
GLuint VAO;
|
||||
|
||||
// Vertex Buffer Object
|
||||
GLuint VBO;
|
||||
|
||||
// Element Buffer Object
|
||||
GLuint EBO;
|
||||
|
||||
// Number of indices to draw
|
||||
GLsizei num_indices;
|
||||
} Mesh;
|
||||
|
||||
// initializes and uploads mesh data to gpu
|
||||
void mesh_init(Mesh *self, GLfloat *vertices, GLsizei vertices_size, GLuint *indices, GLsizei num_indices);
|
||||
|
||||
// Draws the mesh
|
||||
void mesh_draw(Mesh *self);
|
||||
|
||||
void mesh_delete(Mesh *self);
|
||||
|
||||
#endif //MESH_H
|
||||
@@ -64,9 +64,9 @@ Shader shader_create(const char *vertexFile, const char *fragmentFile) {
|
||||
char *vertexSource = get_file_contents(vertexFile);
|
||||
char *fragmentSource = get_file_contents(fragmentFile);
|
||||
|
||||
if (!vertexSource || !fragmentSource) {
|
||||
if (vertexSource == NULL || fragmentSource == NULL) {
|
||||
log_error("Failed to load shader files. Returning empty shader\n");
|
||||
Shader emptyShader = { .ID = 0};
|
||||
Shader emptyShader = { .ID = 0, .camMatrixLocation = -1};
|
||||
if (vertexSource)
|
||||
free(vertexSource);
|
||||
if (fragmentSource)
|
||||
@@ -101,7 +101,19 @@ Shader shader_create(const char *vertexFile, const char *fragmentFile) {
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
Shader newShader = { .ID = programID };
|
||||
GLint camMatrixLocation = glGetUniformLocation(programID, "camMatrix");
|
||||
if (camMatrixLocation == -1) {
|
||||
log_error("Uniform 'camMatrix' not found after linking shader program %u. Is it used in default.vert?", programID);
|
||||
}
|
||||
|
||||
GLint modelMatrixLocation = glGetUniformLocation(programID, "modelMatrix");
|
||||
if (modelMatrixLocation == -1) {
|
||||
log_warn("Uniform 'modelMatrix' not found in shader program %u. Is it used in default.vert?", programID);
|
||||
}
|
||||
|
||||
Shader newShader = { .ID = programID,
|
||||
.camMatrixLocation = camMatrixLocation,
|
||||
.modelMatrixLocation = modelMatrixLocation };
|
||||
return newShader;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
typedef struct {
|
||||
// Reference ID of the shader program
|
||||
GLuint ID;
|
||||
// Location of the camera matrix uniform, set at creation
|
||||
GLint camMatrixLocation;
|
||||
GLint modelMatrixLocation;
|
||||
} Shader;
|
||||
|
||||
char *get_file_contents(const char *filename);
|
||||
|
||||
113
src/main.c
113
src/main.c
@@ -17,6 +17,7 @@
|
||||
#include "engine/renderer/camera/camera.h"
|
||||
#include "engine/renderer/data/engine_data.h"
|
||||
#include "engine/renderer/shaders/shader.h"
|
||||
#include "engine/renderer/mesh/mesh.h"
|
||||
|
||||
static SDL_Window *window = NULL;
|
||||
static SDL_GLContext gl_context = NULL;
|
||||
@@ -28,6 +29,9 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
log_info("Starting program and initializing SDL...");
|
||||
/* Create the window */
|
||||
|
||||
int win_width = 1280;
|
||||
int win_height = 720;
|
||||
|
||||
// TODO: make use of arena allocators potentially? see: digital grove repo
|
||||
Engine_Data *state = (Engine_Data*)malloc(sizeof(Engine_Data));
|
||||
if (state == NULL) {
|
||||
@@ -35,25 +39,22 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
// pass allocated state back to the SDL loop
|
||||
*appstate = state;
|
||||
|
||||
int win_width = 1280;
|
||||
int win_height = 720;
|
||||
|
||||
// use of SDL_WINDOW_OPENGL flag to create a context-compatible window with shaders
|
||||
window = SDL_CreateWindow("Beyond Depth", win_width, win_height, SDL_WINDOW_OPENGL);
|
||||
if (!window) {
|
||||
log_error("Couldn't create SDL window: %s", SDL_GetError());
|
||||
free(state);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
state->window_width = win_width;
|
||||
state->window_height = win_height;
|
||||
|
||||
// create openGL context with openGL 3.3 core profile
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
|
||||
// use of SDL_WINDOW_OPENGL flag to create a context-compatible window with shaders
|
||||
window = SDL_CreateWindow("Beyond Depth", win_width, win_height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
|
||||
if (!window) {
|
||||
log_error("Couldn't create SDL window: %s", SDL_GetError());
|
||||
free(state);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
gl_context = SDL_GL_CreateContext(window);
|
||||
if (!gl_context) {
|
||||
log_error("Failed to create OpenGL context: %s", SDL_GetError());
|
||||
@@ -72,22 +73,27 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
// TODO: if still crashing on initial startup, ensure all of OpenGL, GLAD is properly initialized
|
||||
state->window_width = win_width;
|
||||
state->window_height = win_height;
|
||||
|
||||
vec3 initial_pos = {0.0f, 0.0f, 3.0f};
|
||||
camera_init(&state->camera, initial_pos, state->window_width, state->window_height);
|
||||
// z-buffer
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
state->shader = shader_create("default.vert", "default.frag");
|
||||
|
||||
if (state->shader.ID == 0) {
|
||||
log_error("Failed to initialize shader program");
|
||||
// TODO: cleanup memory
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
vec3 initial_pos = {0.0f, 0.0f, 2.0f};
|
||||
camera_init(&state->camera, initial_pos, state->window_width, state->window_height);
|
||||
|
||||
mesh_init(&state->triangle_mesh, vertices, (GLsizei)vertices_size, indices, INDICES_COUNT);
|
||||
|
||||
glm_mat4_identity(state->pyramidModel);
|
||||
|
||||
SDL_SetWindowRelativeMouseMode(window, true);
|
||||
|
||||
// pass allocated state back to the SDL loop
|
||||
*appstate = state;
|
||||
|
||||
log_info("Camera, Shaders and App State initialized");
|
||||
|
||||
@@ -97,11 +103,24 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
|
||||
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
|
||||
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
|
||||
{
|
||||
if (event->type == SDL_EVENT_KEY_DOWN ||
|
||||
event->type == SDL_EVENT_QUIT) {
|
||||
log_info("User pressed a key");
|
||||
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
|
||||
Engine_Data *state = (Engine_Data *)appstate;
|
||||
|
||||
// handles quitting
|
||||
if (event->type == SDL_EVENT_QUIT) {
|
||||
return SDL_APP_SUCCESS;
|
||||
}
|
||||
|
||||
// handles esc key to quit
|
||||
if (event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_ESCAPE) {
|
||||
return SDL_APP_SUCCESS;
|
||||
}
|
||||
|
||||
// handle mouse motion for camera look
|
||||
if (event->type == SDL_EVENT_MOUSE_MOTION) {
|
||||
// y movement inverted?
|
||||
camera_process_mouse(&state->camera, event->motion.xrel, -event->motion.yrel, state->deltaTime);
|
||||
}
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -111,6 +130,13 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
{
|
||||
Engine_Data *state = (Engine_Data *)appstate; // good practice
|
||||
|
||||
float currentTime = (float)SDL_GetTicks() / 1000.0f;
|
||||
state->deltaTime = currentTime - state->lastFrameTime;
|
||||
state->lastFrameTime = currentTime;
|
||||
|
||||
const Uint8 *keyState = SDL_GetKeyboardState(NULL);
|
||||
camera_process_keyboard(&state->camera, keyState, state->deltaTime);
|
||||
|
||||
// set viewport
|
||||
glViewport(0, 0, 1280, 720);
|
||||
|
||||
@@ -119,7 +145,39 @@ SDL_AppResult SDL_AppIterate(void *appstate)
|
||||
glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// TODO: add drawing logic
|
||||
// calculate "orbit" angle for total rotation overtime
|
||||
float rotation_speed_deg = 45.0f;
|
||||
float rotation_amount = glm_rad(rotation_speed_deg * state->deltaTime);
|
||||
|
||||
// accumulate total rotation
|
||||
static float total_rotation = 0.0f;
|
||||
total_rotation += rotation_amount;
|
||||
|
||||
shader_activate(&state->shader);
|
||||
|
||||
// upload camera matrix (P*V) to the shader
|
||||
camera_matrix_to_shader(&state->camera, &state->shader, "camMatrix");
|
||||
|
||||
float rotation = (float)SDL_GetTicks() / 1000.0f;
|
||||
glm_mat4_identity(state->pyramidModel);
|
||||
// rotate around the y-axis
|
||||
glm_rotate(state->pyramidModel, total_rotation * 0.5f, (vec3){0.0f, 1.0f, 0.0f});
|
||||
|
||||
mat4 orbitModel; // temporary object
|
||||
glm_mat4_identity(orbitModel);
|
||||
|
||||
glm_rotate(orbitModel, total_rotation, (vec3){0.0f, 1.0f, 0.0f});
|
||||
|
||||
glm_translate(orbitModel, (vec3){3.0f, 0.0f, 0.0f});
|
||||
|
||||
glm_rotate(orbitModel, total_rotation * 2.0f, (vec3){0.5f, 1.0f, 0.0f});
|
||||
|
||||
// upload model matrix to shader
|
||||
glUniformMatrix4fv(state->shader.modelMatrixLocation, 1, GL_FALSE, *state->pyramidModel);
|
||||
mesh_draw(&state->triangle_mesh);
|
||||
|
||||
glUniformMatrix4fv(state->shader.modelMatrixLocation, 1, GL_FALSE, *orbitModel);
|
||||
mesh_draw(&state->triangle_mesh);
|
||||
|
||||
// swap front and back buffers to display rendered frame
|
||||
SDL_GL_SwapWindow(window);
|
||||
@@ -134,7 +192,12 @@ void SDL_AppQuit(void *appstate, SDL_AppResult result)
|
||||
|
||||
// cleanup all resources
|
||||
if (state) {
|
||||
mesh_delete(&state->triangle_mesh);
|
||||
|
||||
if (state->shader.ID != 0) {
|
||||
shader_delete(&state->shader);
|
||||
}
|
||||
|
||||
free(state);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user