Fixed camera

This commit is contained in:
2025-10-13 12:26:59 -05:00
parent 2c0fd84c72
commit 0c0650a2c3
6 changed files with 82 additions and 66 deletions

View File

@@ -1,6 +1,5 @@
exec "config/init-base"; exec "config/init-base";
screen height 270;
screen height 270; screen height 270;
bind ` toggleconsole; bind ` toggleconsole;

View File

@@ -98,6 +98,34 @@ void cameraPushMatrix(camera_t *camera) {
); );
break; break;
case CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT:
assertTrue(
camera->projType == CAMERA_PROJECTION_TYPE_PERSPECTIVE ||
camera->projType == CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED,
"Pixel perfect camera view requires perspective projection"
);
const float_t viewportHeight = (
(float_t)frameBufferGetHeight(FRAMEBUFFER_BOUND)
);
const float_t z = (viewportHeight / 2.0f) / (
camera->lookatPixelPerfect.pixelsPerUnit *
tanf(camera->perspective.fov / 2.0f)
);
vec3 position;
glm_vec3_copy(camera->lookatPixelPerfect.target, position);
glm_vec3_add(position, camera->lookatPixelPerfect.offset, position);
position[2] += z;
glm_lookat(
position,
camera->lookatPixelPerfect.target,
camera->lookatPixelPerfect.up,
view
);
break;
case CAMERA_VIEW_TYPE_2D: case CAMERA_VIEW_TYPE_2D:
glm_mat4_identity(view); glm_mat4_identity(view);
glm_translate(view, (vec3){ glm_translate(view, (vec3){

View File

@@ -20,7 +20,8 @@ typedef enum {
typedef enum { typedef enum {
CAMERA_VIEW_TYPE_MATRIX, CAMERA_VIEW_TYPE_MATRIX,
CAMERA_VIEW_TYPE_LOOKAT, CAMERA_VIEW_TYPE_LOOKAT,
CAMERA_VIEW_TYPE_2D CAMERA_VIEW_TYPE_2D,
CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT
} cameraviewtype_t; } cameraviewtype_t;
typedef struct { typedef struct {
@@ -36,6 +37,13 @@ typedef struct {
float_t up[3]; float_t up[3];
} lookat; } lookat;
struct {
float_t offset[3];
float_t target[3];
float_t up[3];
float_t pixelsPerUnit;
} lookatPixelPerfect;
struct { struct {
float_t position[2]; float_t position[2];
float_t zoom; float_t zoom;

View File

@@ -81,36 +81,36 @@ void playerInteraction(entity_t *entity) {
// Copy to max // Copy to max
glm_vec2_copy(interactBox.min, interactBox.max); glm_vec2_copy(interactBox.min, interactBox.max);
// Size of the hitbox // // Size of the hitbox
vec2 halfSize = { // vec2 halfSize = {
TILESET_ENTITIES.tileWidth * PLAYER_INTERACTION_SIZE * 0.5f, // 1 * PLAYER_INTERACTION_SIZE * 0.5f,
TILESET_ENTITIES.tileHeight * PLAYER_INTERACTION_SIZE * 0.5f // 1 * PLAYER_INTERACTION_SIZE * 0.5f
}; // };
// Subtract from min, add to max. // // Subtract from min, add to max.
glm_vec2_sub(interactBox.min, halfSize, interactBox.min); // glm_vec2_sub(interactBox.min, halfSize, interactBox.min);
glm_vec2_add(interactBox.max, halfSize, interactBox.max); // glm_vec2_add(interactBox.max, halfSize, interactBox.max);
// For each entity // // For each entity
entity_t *start = ENTITIES; // entity_t *start = ENTITIES;
entity_t *end = &ENTITIES[ENTITY_COUNT]; // entity_t *end = &ENTITIES[ENTITY_COUNT];
vec2 otherSize = { TILESET_ENTITIES.tileWidth, TILESET_ENTITIES.tileHeight }; // vec2 otherSize = { 1, 1 };
physicsbox_t otherBox; // physicsbox_t otherBox;
physicsboxboxresult_t result; // physicsboxboxresult_t result;
do { // do {
if(start->type != ENTITY_TYPE_NPC) continue; // if(start->type != ENTITY_TYPE_NPC) continue;
// Setup other box. // // Setup other box.
glm_vec2_copy(start->position, otherBox.min); // glm_vec2_copy(start->position, otherBox.min);
glm_vec2_copy(start->position, otherBox.max); // glm_vec2_copy(start->position, otherBox.max);
glm_vec2_sub(otherBox.min, otherSize, otherBox.min); // glm_vec2_sub(otherBox.min, otherSize, otherBox.min);
glm_vec2_add(otherBox.min, otherSize, otherBox.max); // glm_vec2_add(otherBox.min, otherSize, otherBox.max);
physicsBoxCheckBox(interactBox, otherBox, &result); // physicsBoxCheckBox(interactBox, otherBox, &result);
if(!result.hit) continue; // if(!result.hit) continue;
printf("Interacted with entity at (%.2f, %.2f)\n", start->position[0], start->position[1]); // printf("Interacted with entity at (%.2f, %.2f)\n", start->position[0], start->position[1]);
break; // break;
} while(++start != end); // } while(++start != end);
} }

View File

@@ -14,11 +14,23 @@
#include "rpg/rpgcamera.h" #include "rpg/rpgcamera.h"
#include "util/memory.h" #include "util/memory.h"
#define TILE_SIZE 1 #define TILE_SIZE 16
errorret_t sceneMapInit(scenedata_t *data) { errorret_t sceneMapInit(scenedata_t *data) {
cameraInitPerspective(&data->sceneMap.camera); cameraInitPerspective(&data->sceneMap.camera);
data->sceneMap.camera.projType = CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED; data->sceneMap.camera.projType = CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED;
data->sceneMap.camera.viewType = CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT;
glm_vec3_zero(data->sceneMap.camera.lookatPixelPerfect.offset);
data->sceneMap.camera.lookatPixelPerfect.offset[2] = 32.0f;
glm_vec3_copy(
(vec3){ 0.0f, 0.0f, 0.0f },
data->sceneMap.camera.lookatPixelPerfect.target
);
glm_vec3_copy(
(vec3){ 0.0f, 1.0f, 0.0f },
data->sceneMap.camera.lookatPixelPerfect.up
);
data->sceneMap.camera.lookatPixelPerfect.pixelsPerUnit = 1.0f;
errorOk(); errorOk();
} }
@@ -27,49 +39,20 @@ void sceneMapUpdate(scenedata_t *data) {
} }
void sceneMapRender(scenedata_t *data) { void sceneMapRender(scenedata_t *data) {
// Look at target. // Look at target.
glm_vec3_scale( glm_vec3_scale(
RPG_CAMERA.position, RPG_CAMERA.position,
TILE_SIZE, TILE_SIZE,
data->sceneMap.camera.lookat.target data->sceneMap.camera.lookatPixelPerfect.target
); );
// Center within tile // Center within tile
glm_vec3_add( glm_vec3_add(
data->sceneMap.camera.lookat.target, data->sceneMap.camera.lookatPixelPerfect.target,
(vec3){TILE_SIZE / 2.0f, TILE_SIZE / 2.0f, TILE_SIZE / 2.0f }, (vec3){TILE_SIZE / 2.0f, TILE_SIZE / 2.0f, TILE_SIZE / 2.0f },
data->sceneMap.camera.lookat.target data->sceneMap.camera.lookatPixelPerfect.target
); );
// Apply pixel perfect offset and camera offset
const float_t camOffset = 0.01f;
const float_t pixelPerfectOffset = tanf(
data->sceneMap.camera.perspective.fov / 2.0f
) * ((float_t)SCREEN.height / 2.0f);
glm_vec3_copy((vec3){
data->sceneMap.camera.lookat.target[0],
data->sceneMap.camera.lookat.target[1] + camOffset,
data->sceneMap.camera.lookat.target[2] + pixelPerfectOffset
}, data->sceneMap.camera.lookat.position);
// TESTING ONLY
camera_t backup = data->sceneMap.camera;
cameraInitOrthographic(&data->sceneMap.camera);
data->sceneMap.camera.projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
glm_vec3_copy((vec3){
RPG_CAMERA.position[0] * TILE_SIZE,
RPG_CAMERA.position[1] * TILE_SIZE,
10.0f
}, data->sceneMap.camera._2d.position);
data->sceneMap.camera.orthographic.left = 0.0f;
data->sceneMap.camera.orthographic.right = SCREEN.width;
data->sceneMap.camera.orthographic.top = 0.0f;
data->sceneMap.camera.orthographic.bottom = SCREEN.height;
data->sceneMap.camera.nearClip = -100.0f;
data->sceneMap.camera.farClip = 100.0f;
// Push camera // Push camera
cameraPushMatrix(&data->sceneMap.camera); cameraPushMatrix(&data->sceneMap.camera);
@@ -82,9 +65,6 @@ void sceneMapRender(scenedata_t *data) {
// Finished, pop back camera. // Finished, pop back camera.
cameraPopMatrix(); cameraPopMatrix();
//END TESTING
data->sceneMap.camera = backup;
} }
void sceneMapRenderEntity(entity_t *entity) { void sceneMapRenderEntity(entity_t *entity) {
@@ -93,8 +73,7 @@ void sceneMapRenderEntity(entity_t *entity) {
if(entity->type == ENTITY_TYPE_NULL) return; if(entity->type == ENTITY_TYPE_NULL) return;
vec3 posMin, posMax; vec3 posMin, posMax;
// glm_vec3_scale(entity->position, TILE_SIZE, posMin); glm_vec3_scale(entity->position, TILE_SIZE, posMin);
posMin[0] = 1, posMin[1] = 1, posMin[2] = 0;
glm_vec3_add(posMin, (vec3){TILE_SIZE, TILE_SIZE, TILE_SIZE }, posMax); glm_vec3_add(posMin, (vec3){TILE_SIZE, TILE_SIZE, TILE_SIZE }, posMax);
vec2 uv0 = { 0.0f, 0.0f }; vec2 uv0 = { 0.0f, 0.0f };

View File

@@ -135,12 +135,14 @@ def processTileset(asset):
data += f" .image = {json.dumps(tilesetData['image']['imagePath'])},\n" data += f" .image = {json.dumps(tilesetData['image']['imagePath'])},\n"
data += f"}};\n" data += f"}};\n"
# Write Header # Write Header
outputFile = os.path.join(args.headers_dir, "display", "tileset", f"tileset_{tilesetName}.h") outputFile = os.path.join(args.headers_dir, "display", "tileset", f"tileset_{tilesetName}.h")
os.makedirs(os.path.dirname(outputFile), exist_ok=True) os.makedirs(os.path.dirname(outputFile), exist_ok=True)
with open(outputFile, 'w') as f: with open(outputFile, 'w') as f:
f.write(data) f.write(data)
print(f"Write header for tileset: {outputFile}")
tileset = { tileset = {
"files": [], "files": [],