Nimbin2git.christianimmanuel.de / Games / strichmaennchen / camera.c

strichmaennchen git · main

git clone https://git.christianimmanuel.de/games/strichmaennchen.gitwget https://git.christianimmanuel.de/games/strichmaennchen/archive/strichmaennchen.tar.gz
camera.c 3 KB · 99 lines raw
#include "camera.h"
#include "human.h"
#include "renderer.h"

#include <math.h>
#define M_PI 3.14159265358979323846
#define DEG2RAD(x) ((x) * (3.14159265358979323846f / 180.0f))


float cosf(float x);
float sinf(float x);
float sqrtf(float x);


void Camera_init(Camera* cam, Vec3 position, float yaw, float pitch, float fov) {
    cam->position = position;
    cam->yaw = yaw;
    cam->pitch = pitch;
    cam->up = vec3(0.0f, 1.0f, 0.0f);
    cam->fov = fov;

    // calculate initial front
    Vec3 front;
    front.x = cosf(DEG2RAD(yaw)) * cosf(DEG2RAD(pitch));
    front.y = sinf(DEG2RAD(pitch));
    front.z = sinf(DEG2RAD(yaw)) * cosf(DEG2RAD(pitch));

    float len = sqrtf(front.x*front.x + front.y*front.y + front.z*front.z);
    cam->front.x = front.x / len;
    cam->front.y = front.y / len;
    cam->front.z = front.z / len;
}



void Camera_rotate(Camera* cam, float yaw_delta, float pitch_delta) {
    cam->yaw += yaw_delta;
    cam->pitch += pitch_delta;

    if (cam->pitch > 89.0f)  cam->pitch = 89.0f;
    if (cam->pitch < -89.0f) cam->pitch = -89.0f;
}

void Camera_update(Camera* cam, Renderer* renderer) {
    // Compute front vector
    Vec3 front;
    front.x = cosf(DEG2RAD(cam->yaw)) * cosf(DEG2RAD(cam->pitch));
    front.y = sinf(DEG2RAD(cam->pitch));
    front.z = sinf(DEG2RAD(cam->yaw)) * cosf(DEG2RAD(cam->pitch));

    // Normalize
    float len = sqrtf(front.x*front.x + front.y*front.y + front.z*front.z);
    cam->front.x = front.x / len;
    cam->front.y = front.y / len;
    cam->front.z = front.z / len;

    // Recompute right and up
    Vec3 world_up = {0,1,0};
    cam->right = vec3_normalize(vec3_cross(cam->front, world_up));
    cam->up    = vec3_normalize(vec3_cross(cam->right, cam->front));

    cam->projection = mat4_perspective(cam->fov,
                                       (float)renderer->width / renderer->height,
                                       0.1f, 100.0f);

    cam->view = mat4_lookAt(cam->position,
                            vec3_add(cam->position, cam->front),
                            cam->up);
}

void Camera_move(Camera* cam, Userinput* input, float dt) {
    // Flattened forward for walking
    Vec3 flatFront = cam->front;
    flatFront.y = 0.0f;
    flatFront = vec3_normalize(flatFront);

    Vec3 move = vec3_scale(flatFront, input->move_forward);
    move = vec3_add(move, vec3_scale(cam->right, input->move_sideway));

    // Normalize to prevent faster diagonal movement
    float len = sqrtf(move.x*move.x + move.y*move.y + move.z*move.z);
    if (len > 0.0f) move = vec3_scale(move, 1.0f / len);

    float speed = 5.0f * dt;
    cam->position = vec3_add(cam->position, vec3_scale(move, speed));
}


void Camera_followPlayer(Camera *cam, Human *player) {
    cam->position = vec3_add(player->object->position, (Vec3){0, 1.6f, 0}); // eye height
}



Mat4 Camera_getViewMatrix(Camera* cam) {
    // Simple LookAt: pos, target=pos+front, up
    Vec3 target = vec3_add(cam->position, cam->front);
    return mat4_lookAt(cam->position, target, cam->up);
}