From 368729f0f3a7d96c221196832242b2add00f5542 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Mon, 1 Sep 2025 11:02:30 -0500 Subject: [PATCH] Fixed some camera bugs. --- src/display/CMakeLists.txt | 3 +- src/display/camera.c | 32 ++++---- src/display/display.c | 21 ++++- src/display/renderer.c | 32 -------- src/display/renderer.h | 16 ---- src/display/scene/CMakeLists.txt | 13 +++ src/display/scene/overworld/CMakeLists.txt | 10 +++ src/display/scene/overworld/sceneoverworld.c | 58 ++++++++++++++ src/display/scene/overworld/sceneoverworld.h | 31 ++++++++ src/display/scene/scene.h | 32 ++++++++ src/display/scene/scenemanager.c | 52 ++++++++++++ src/display/scene/scenemanager.h | 21 +++++ src/display/spritebatch/CMakeLists.txt | 10 +++ src/display/spritebatch/spritebatch.c | 75 ++++++++++++++++++ src/display/spritebatch/spritebatch.h | 83 ++++++++++++++++++++ src/rpg/entity/entity.h | 2 +- src/rpg/entity/player.h | 2 +- 17 files changed, 423 insertions(+), 70 deletions(-) delete mode 100644 src/display/renderer.c delete mode 100644 src/display/renderer.h create mode 100644 src/display/scene/CMakeLists.txt create mode 100644 src/display/scene/overworld/CMakeLists.txt create mode 100644 src/display/scene/overworld/sceneoverworld.c create mode 100644 src/display/scene/overworld/sceneoverworld.h create mode 100644 src/display/scene/scene.h create mode 100644 src/display/scene/scenemanager.c create mode 100644 src/display/scene/scenemanager.h create mode 100644 src/display/spritebatch/CMakeLists.txt create mode 100644 src/display/spritebatch/spritebatch.c create mode 100644 src/display/spritebatch/spritebatch.h diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt index af12776..84b6db8 100644 --- a/src/display/CMakeLists.txt +++ b/src/display/CMakeLists.txt @@ -8,13 +8,14 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE display.c camera.c - renderer.c ) # Subdirectories add_subdirectory(framebuffer) add_subdirectory(mesh) add_subdirectory(texture) +add_subdirectory(scene) +add_subdirectory(spritebatch) if(DUSK_TARGET_SYSTEM STREQUAL "linux") target_compile_definitions(${DUSK_TARGET_NAME} diff --git a/src/display/camera.c b/src/display/camera.c index ee291de..c164966 100644 --- a/src/display/camera.c +++ b/src/display/camera.c @@ -16,22 +16,20 @@ camera_t *CAMERA_MAIN = NULL; void cameraInit(camera_t *camera) { assertNotNull(camera, "Not a camera component"); - camera->type = CAMERA_TYPE_PERSPECTIVE - ; - glm_mat4_identity(camera->transform); - camera->perspective.fov = 45.0f; - + camera->type = CAMERA_TYPE_PERSPECTIVE; + camera->perspective.fov = glm_rad(45.0f); camera->nearClip = 0.1f; camera->farClip = 100.0f; - glm_look( - (vec3){ 3.0f, 3.0f, 3.0f }, + + glm_lookat( + (vec3){ 5.0f, 5.0f, 5.0f }, (vec3){ 0.0f, 0.0f, 0.0f }, (vec3){ 0.0f, 1.0f, 0.0f }, camera->transform ); } -void cameraPush(camera_t *camera) { +void cameraPushMatrix(camera_t *camera) { assertNotNull(camera, "Not a camera component"); mat4 projection; @@ -50,12 +48,13 @@ void cameraPush(camera_t *camera) { break; case CAMERA_TYPE_PERSPECTIVE: + const float_t aspect = ( + (float_t)frameBufferGetWidth(FRAMEBUFFER_BOUND) / + (float_t)frameBufferGetHeight(FRAMEBUFFER_BOUND) + ); glm_perspective( camera->perspective.fov, - ( - (float_t)frameBufferGetWidth(FRAMEBUFFER_BOUND) / - (float_t)frameBufferGetHeight(FRAMEBUFFER_BOUND) - ), + aspect, camera->nearClip, camera->farClip, projection @@ -63,20 +62,21 @@ void cameraPush(camera_t *camera) { } #if DISPLAY_SDL2 - mat4 pv; - glm_mat4_mul(projection, camera->transform, pv); + // mat4 pv; + // glm_mat4_mul(projection, camera->transform, pv); glPushMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glLoadMatrixf((const GLfloat*)pv); + glLoadMatrixf((const GLfloat*)projection); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + glLoadMatrixf((const GLfloat*)camera->transform); #endif } -void cameraPop(void) { +void cameraPopMatrix(void) { #if DISPLAY_SDL2 glPopMatrix(); #endif diff --git a/src/display/display.c b/src/display/display.c index bcf28ca..62c88f8 100644 --- a/src/display/display.c +++ b/src/display/display.c @@ -7,8 +7,9 @@ #include "display/display.h" #include "console/console.h" -#include "display/renderer.h" #include "display/framebuffer/framebuffer.h" +#include "display/scene/scenemanager.h" +#include "display/spritebatch/spritebatch.h" #include "display/mesh/quad.h" @@ -59,6 +60,8 @@ errorret_t displayInit(void) { quadInit(); frameBufferInitBackbuffer(); + spriteBatchInit(); + sceneManagerInit(); errorOk(); } @@ -82,18 +85,30 @@ errorret_t displayUpdate(void) { SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight); glViewport(0, 0, windowWidth, windowHeight); #endif - - // rendererRender(CAMERA_MAIN); + + frameBufferBind(&FRAMEBUFFER_BACKBUFFER); + spriteBatchClear(); + + sceneManagerUpdate(); + sceneManagerRender(); #if DISPLAY_SDL2 SDL_GL_SwapWindow(DISPLAY.window); #endif + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + printf("GL Error: %d\n", err); + } + // For now, we just return an OK error. errorOk(); } errorret_t displayDispose(void) { + sceneManagerDispose(); + spriteBatchDispose(); + #if DISPLAY_SDL2 if(DISPLAY.glContext) { SDL_GL_DeleteContext(DISPLAY.glContext); diff --git a/src/display/renderer.c b/src/display/renderer.c deleted file mode 100644 index 0eb46fe..0000000 --- a/src/display/renderer.c +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "renderer.h" -#include "display/framebuffer/framebuffer.h" - -// void rendererRender(const ecsid_t camera) { -// if(camera == -1) return; - -// // Get the meshes. -// uint32_t meshCount; -// ecsid_t meshes[ECS_ENTITY_COUNT_MAX]; -// ecsid_t id; -// meshCount = meshRendererGetAll(meshes); - -// frameBufferBind(NULL); -// frameBufferClear( -// FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH, -// COLOR_CORNFLOWER_BLUE -// ); -// cameraPush(camera); -// for(uint32_t i = 0; i < meshCount; i++) { -// id = meshes[i]; -// nodeMatrixPush(id); -// meshRendererDraw(id); -// } -// cameraPop(); -// } \ No newline at end of file diff --git a/src/display/renderer.h b/src/display/renderer.h deleted file mode 100644 index 50b963c..0000000 --- a/src/display/renderer.h +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "display/camera.h" - -/** - * Render the given scene from the perspective of the given camera. - * - * @param camera The ID of the camera entity to render from. - */ -// void rendererRender(const ecsid_t camera); \ No newline at end of file diff --git a/src/display/scene/CMakeLists.txt b/src/display/scene/CMakeLists.txt new file mode 100644 index 0000000..0fcb97d --- /dev/null +++ b/src/display/scene/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + scenemanager.c +) + +# Subdirs +add_subdirectory(overworld) \ No newline at end of file diff --git a/src/display/scene/overworld/CMakeLists.txt b/src/display/scene/overworld/CMakeLists.txt new file mode 100644 index 0000000..b5ce235 --- /dev/null +++ b/src/display/scene/overworld/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + sceneoverworld.c +) \ No newline at end of file diff --git a/src/display/scene/overworld/sceneoverworld.c b/src/display/scene/overworld/sceneoverworld.c new file mode 100644 index 0000000..94d2a38 --- /dev/null +++ b/src/display/scene/overworld/sceneoverworld.c @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "sceneoverworld.h" +#include "rpg/entity/entity.h" +#include "display/spritebatch/spritebatch.h" +#include "display/framebuffer/framebuffer.h" +#include "display/scene/scenemanager.h" +#include "display/mesh/quad.h" + +camera_t SCENE_OVERWORLD_CAMERA; + +void sceneOverworldInit(void) { + cameraInit(&SCENE_OVERWORLD_CAMERA); + SCENE_OVERWORLD_CAMERA.type = CAMERA_TYPE_ORTHOGRAPHIC; + SCENE_OVERWORLD_CAMERA.orthographic.left = 0.0f; + SCENE_OVERWORLD_CAMERA.orthographic.right = frameBufferGetWidth(FRAMEBUFFER_BOUND); + SCENE_OVERWORLD_CAMERA.orthographic.top = 0.0f; + SCENE_OVERWORLD_CAMERA.orthographic.bottom = frameBufferGetHeight(FRAMEBUFFER_BOUND); + SCENE_OVERWORLD_CAMERA.nearClip = -1.0f; + SCENE_OVERWORLD_CAMERA.farClip = 100.0f; + + glm_mat4_identity(SCENE_OVERWORLD_CAMERA.transform); + + scene_t *scene = &SCENE_MANAGER_SCENES[SCENE_TYPE_OVERWORLD]; + scene->flags |= SCENE_FLAG_ACTIVE | SCENE_FLAG_VISIBLE; +} + +void sceneOverworldUpdate(void) { +} + +void sceneOverworldRender(void) { + frameBufferClear( + FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH, + COLOR_CORNFLOWER_BLUE + ); + + cameraPushMatrix(&SCENE_OVERWORLD_CAMERA); + meshDraw(&QUAD_MESH_SIMPLE, -1, -1); + + spriteBatchPush( + NULL, + 0.0f, 0.0f, 32.0f, 32.0f, + 0xFF, 0x00, 0x00, 0xFF, + 0.0f, 0.0f, 1.0f, 1.0f + ); + spriteBatchFlush(); + + cameraPopMatrix(); +} + +void sceneOverworldDispose(void) { + // Dispose of the overworld scene. +} diff --git a/src/display/scene/overworld/sceneoverworld.h b/src/display/scene/overworld/sceneoverworld.h new file mode 100644 index 0000000..e92c4dd --- /dev/null +++ b/src/display/scene/overworld/sceneoverworld.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "display/camera.h" + +extern camera_t SCENE_OVERWORLD_CAMERA; + +/** + * Initialize the overworld scene. + */ +void sceneOverworldInit(void); + +/** + * Update the overworld scene. + */ +void sceneOverworldUpdate(void); + +/** + * Render the overworld scene. + */ +void sceneOverworldRender(void); + +/** + * Dispose of the overworld scene. + */ +void sceneOverworldDispose(void); \ No newline at end of file diff --git a/src/display/scene/scene.h b/src/display/scene/scene.h new file mode 100644 index 0000000..1a01c05 --- /dev/null +++ b/src/display/scene/scene.h @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +#define SCENE_FLAG_VISIBLE (1 << 0) +#define SCENE_FLAG_ACTIVE (1 << 1) + +typedef struct { + void (*init)(void); + void (*update)(void); + void (*render)(void); + void (*dispose)(void); + void (*active)(void); + void (*sleep)(void); + + uint8_t flags; +} scene_t; + +typedef enum { + SCENE_TYPE_LOGO, + SCENE_TYPE_OVERWORLD, + + SCENE_TYPE_COUNT +} scenetype_t; + +#define SCENE_TYPE_INITIAL SCENE_TYPE_OVERWORLD \ No newline at end of file diff --git a/src/display/scene/scenemanager.c b/src/display/scene/scenemanager.c new file mode 100644 index 0000000..13d6225 --- /dev/null +++ b/src/display/scene/scenemanager.c @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "scenemanager.h" + +#include "display/scene/overworld/sceneoverworld.h" + +scenemanager_t SCENE_MANAGER; + +scene_t SCENE_MANAGER_SCENES[SCENE_TYPE_COUNT] = { + [SCENE_TYPE_LOGO] = { 0 }, + + [SCENE_TYPE_OVERWORLD] = { + .init = sceneOverworldInit, + .update = sceneOverworldUpdate, + .render = sceneOverworldRender, + .dispose = sceneOverworldDispose + } +}; + +void sceneManagerInit(void) { + scene_t *initial = &SCENE_MANAGER_SCENES[SCENE_TYPE_INITIAL]; + if(initial->init != NULL) initial->init(); +} + +void sceneManagerUpdate(void) { + // For each scene. + for(uint8_t i = 0; i < SCENE_TYPE_COUNT; i++) { + scene_t *scene = &SCENE_MANAGER_SCENES[i]; + if((scene->flags & SCENE_FLAG_ACTIVE) == 0) continue; + if(scene->update != NULL) scene->update(); + } +} + +void sceneManagerRender(void) { + for(uint8_t i = 0; i < SCENE_TYPE_COUNT; i++) { + scene_t *scene = &SCENE_MANAGER_SCENES[i]; + if((scene->flags & SCENE_FLAG_VISIBLE) == 0) continue; + if(scene->render != NULL) scene->render(); + } +} + +void sceneManagerDispose(void) { + for(uint8_t i = 0; i < SCENE_TYPE_COUNT; i++) { + scene_t *scene = &SCENE_MANAGER_SCENES[i]; + if(scene->dispose != NULL) scene->dispose(); + } +} diff --git a/src/display/scene/scenemanager.h b/src/display/scene/scenemanager.h new file mode 100644 index 0000000..2fb729d --- /dev/null +++ b/src/display/scene/scenemanager.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "scene.h" + +typedef struct { + int nothing; +} scenemanager_t; + +extern scenemanager_t SCENE_MANAGER; +extern scene_t SCENE_MANAGER_SCENES[SCENE_TYPE_COUNT]; + +void sceneManagerInit(void); +void sceneManagerUpdate(void); +void sceneManagerRender(void); +void sceneManagerDispose(void); \ No newline at end of file diff --git a/src/display/spritebatch/CMakeLists.txt b/src/display/spritebatch/CMakeLists.txt new file mode 100644 index 0000000..7c64a15 --- /dev/null +++ b/src/display/spritebatch/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + spritebatch.c +) \ No newline at end of file diff --git a/src/display/spritebatch/spritebatch.c b/src/display/spritebatch/spritebatch.c new file mode 100644 index 0000000..714d57f --- /dev/null +++ b/src/display/spritebatch/spritebatch.c @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "spritebatch.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "console/console.h" + +spritebatch_t SPRITEBATCH; + +void spriteBatchInit() { + SPRITEBATCH.spriteCount = 0; + SPRITEBATCH.currentTexture = NULL; + + meshInit( + &SPRITEBATCH.mesh, + MESH_PRIMITIVE_TRIANGLES, + SPRITEBATCH_VERTEX_COUNT, + &SPRITEBATCH.vertices[0] + ); +} + +void spriteBatchPush( + texture_t *texture, + const float_t minX, + const float_t minY, + const float_t maxX, + const float_t maxY, + const uint8_t r, + const uint8_t g, + const uint8_t b, + const uint8_t a, + const float_t u0, + const float_t v0, + const float_t u1, + const float_t v1 +) { + // Need to flush? + if( + SPRITEBATCH.currentTexture != texture || + SPRITEBATCH.spriteCount >= SPRITEBATCH_SPRITES_MAX + ) { + spriteBatchFlush(); + SPRITEBATCH.currentTexture = texture; + } + + quadBuffer( + &SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT], + minX, minY, maxX, maxY, + r, g, b, a, + u0, v0, u1, v1 + ); + + SPRITEBATCH.spriteCount++; +} + +void spriteBatchClear() { + SPRITEBATCH.spriteCount = 0; + SPRITEBATCH.currentTexture = NULL; +} + +void spriteBatchFlush() { + if(SPRITEBATCH.spriteCount == 0) return; + textureBind(SPRITEBATCH.currentTexture); + meshDraw(&SPRITEBATCH.mesh, 0, QUAD_VERTEX_COUNT * SPRITEBATCH.spriteCount); + spriteBatchClear(); +} + +void spriteBatchDispose() { + meshDispose(&SPRITEBATCH.mesh); +} \ No newline at end of file diff --git a/src/display/spritebatch/spritebatch.h b/src/display/spritebatch/spritebatch.h new file mode 100644 index 0000000..ad751a3 --- /dev/null +++ b/src/display/spritebatch/spritebatch.h @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "display/mesh/quad.h" +#include "display/texture/texture.h" + +#define SPRITEBATCH_SPRITES_MAX 1 +#define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT) + + +typedef struct { + mesh_t mesh; + int32_t spriteCount; + texture_t *currentTexture; + meshvertex_t vertices[SPRITEBATCH_VERTEX_COUNT]; +} spritebatch_t; + +extern spritebatch_t SPRITEBATCH; + +/** + * Initializes a sprite batch. + * + * @param spriteBatch The sprite batch to initialize. + */ +void spriteBatchInit(); + +/** + * Pushes a sprite to the batch. This basically "queues" it to render (well + * technically it is buffering the vertices to the mesh at the moment, but + * that is likely to change when we switch to VAOs or VBOs or even Shader UBOs). + * + * Currently changing texture pointer will cause the buffer to flush but this is + * also likely to change in the future. + * + * @param texture The texture to use for the sprite. + * @param minX The minimum x coordinate of the sprite. + * @param minY The minimum y coordinate of the sprite. + * @param maxX The maximum x coordinate of the sprite. + * @param maxY The maximum y coordinate of the sprite. + * @param r The red color component of the sprite. + * @param g The green color component of the sprite. + * @param b The blue color component of the sprite. + * @param a The alpha component of the sprite. + * @param u0 The texture coordinate for the top-left corner of the sprite. + * @param v0 The texture coordinate for the top-left corner of the sprite. + * @param u1 The texture coordinate for the bottom-right corner of the sprite. + * @param v1 The texture coordinate for the bottom-right corner of the sprite. + */ +void spriteBatchPush( + texture_t *texture, + const float_t minX, + const float_t minY, + const float_t maxX, + const float_t maxY, + const uint8_t r, + const uint8_t g, + const uint8_t b, + const uint8_t a, + const float_t u0, + const float_t v0, + const float_t u1, + const float_t v1 +); + +/** + * Clears the sprite batch. This will mean calling flush renders nothing. + */ +void spriteBatchClear(); + +/** + * Flushes the sprite batch, rendering all queued sprites. + */ +void spriteBatchFlush(); + +/** + * Disposes of the sprite batch, freeing any allocated resources. + */ +void spriteBatchDispose(); \ No newline at end of file diff --git a/src/rpg/entity/entity.h b/src/rpg/entity/entity.h index 1744af8..a9f04f0 100644 --- a/src/rpg/entity/entity.h +++ b/src/rpg/entity/entity.h @@ -7,7 +7,7 @@ #pragma once #include "direction.h" -#include "player.h" +#include "rpg/entity/player.h" #include "npc.h" #define ENTITY_COUNT_MAX 32 diff --git a/src/rpg/entity/player.h b/src/rpg/entity/player.h index 0780cbb..e5d9bdb 100644 --- a/src/rpg/entity/player.h +++ b/src/rpg/entity/player.h @@ -7,7 +7,7 @@ #pragma once #include "dusk.h" -#include "item/inventory.h" +#include "rpg/item/inventory.h" #define PLAYER_SPEED_WALK 1 #define PLAYER_SPEED_RUN 2