refactor camera into its own directory

This commit is contained in:
Freya Murphy 2023-04-26 20:18:41 -04:00
parent 7585a93491
commit 0294878dda
8 changed files with 156 additions and 132 deletions

76
src/camera.c Normal file
View file

@ -0,0 +1,76 @@
#include "camera.h"
#include <math.h>
void init_camera(Camera* camera) {
camera->pos.x = 3;
camera->pos.y = 3;
camera->angle = PI / 4;
camera->fov = PI / 4;
}
#define MOVE_SPEED 1
#define ROTATE_SPEED PI / 2
#define FOV_CHANGE_SPEED .5
#define PLAYER_SIZE .1
void update_camera(Camera* camera, Screen* screen) {
double rotate = 0;
if (key_down(KEY_LEFT))
rotate -= ROTATE_SPEED;
if (key_down(KEY_RIGHT))
rotate += ROTATE_SPEED;
rotate *= screen->delta;
rotate += camera->angle;
while (rotate >= PI2) rotate -= PI2;
while (rotate < 0) rotate += PI2;
camera->angle = rotate;
v2 forward = { cos(camera->angle), sin(camera->angle) };
v2 left = { forward.y, -forward.x };
v2 move = { 0, 0 };
if (key_down(KEY_W)) {
move.x += forward.x;
move.y += forward.y;
}
if (key_down(KEY_S)) {
move.x -= forward.x;
move.y -= forward.y;
}
if (key_down(KEY_A)) {
move.x += left.x;
move.y += left.y;
}
if (key_down(KEY_D)) {
move.x -= left.x;
move.y -= left.y;
}
if (key_down(KEY_EQUALS)) {
camera->fov += FOV_CHANGE_SPEED * screen->delta;
}
if (key_down(KEY_MINUS)) {
camera->fov -= FOV_CHANGE_SPEED * screen->delta;
}
v2 hit_pos;
bool movex, movey;
cast_ray(camera->pos, sign(move.x) == 1 ? 0 : PI, &hit_pos);
movex = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE;
cast_ray(camera->pos, sign(move.y) == 1 ? PIH : -PIH, &hit_pos);
movey = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE;
if (movex) camera->pos.x += move.x * MOVE_SPEED * screen->delta;
if (movey) camera->pos.y += move.y * MOVE_SPEED * screen->delta;
}

14
src/camera.h Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "screen.h"
#include "ray.h"
typedef struct {
v2 pos;
float angle;
float fov;
} Camera;
void init_camera(Camera* camera);
void update_camera(Camera* camera, Screen* screeen);

View file

@ -13,7 +13,7 @@ static void signal_handler() {
int main (void) { int main (void) {
Screen screen; Screen screen;
init_screen(&screen, 2160, 1440, "Raycaster"); init_screen(&screen, 2160, 1440, "Raycaster", 60);
Camera camera; Camera camera;
init_camera(&camera); init_camera(&camera);

View file

@ -2,6 +2,18 @@
#include <stdint.h> #include <stdint.h>
// #define MAP_SIZE 8
// static uint8_t MAPDATA[MAP_SIZE * MAP_SIZE] = {
// 1, 1, 1, 1, 1, 1, 1, 1,
// 1, 0, 0, 0, 0, 0, 0, 1,
// 1, 0, 0, 0, 0, 3, 0, 1,
// 1, 0, 0, 0, 0, 0, 0, 1,
// 1, 0, 2, 0, 4, 4, 0, 1,
// 1, 0, 0, 0, 4, 0, 0, 1,
// 1, 0, 3, 0, 0, 0, 0, 1,
// 1, 1, 1, 1, 1, 1, 1, 1,
// };
#define MAP_SIZE 8 #define MAP_SIZE 8
static uint8_t MAPDATA[MAP_SIZE * MAP_SIZE] = { static uint8_t MAPDATA[MAP_SIZE * MAP_SIZE] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,

View file

@ -3,90 +3,13 @@
#include "ray.h" #include "ray.h"
#include <math.h> #include <math.h>
#include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
void init_camera(Camera* camera) {
camera->pos.x = 3;
camera->pos.y = 3;
camera->angle = PI / 4;
}
static double fov = PI / 4;
#define MOVE_SPEED 1
#define ROTATE_SPEED PI / 2
#define FOV_CHANGE_SPEED 1
#define PLAYER_SIZE .1
void update_camera(Camera* camera, Screen* screen) {
double rotate = 0;
if (key_down(KEY_LEFT))
rotate -= ROTATE_SPEED;
if (key_down(KEY_RIGHT))
rotate += ROTATE_SPEED;
rotate *= screen->delta;
rotate += camera->angle;
while (rotate >= PI2) rotate -= PI2;
while (rotate < 0) rotate += PI2;
camera->angle = rotate;
v2 forward = { cos(camera->angle), sin(camera->angle) };
v2 left = { forward.y, -forward.x };
v2 move = { 0, 0 };
if (key_down(KEY_W)) {
move.x += forward.x;
move.y += forward.y;
}
if (key_down(KEY_S)) {
move.x -= forward.x;
move.y -= forward.y;
}
if (key_down(KEY_A)) {
move.x += left.x;
move.y += left.y;
}
if (key_down(KEY_D)) {
move.x -= left.x;
move.y -= left.y;
}
if (key_down(KEY_EQUALS)) {
fov += FOV_CHANGE_SPEED * screen->delta;
}
if (key_down(KEY_MINUS)) {
fov -= FOV_CHANGE_SPEED * screen->delta;
}
v2 hit_pos;
bool movex, movey;
cast_ray(camera->pos, sign(move.x) == 1 ? 0 : PI, &hit_pos);
movex = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE;
cast_ray(camera->pos, sign(move.y) == 1 ? PIH : -PIH, &hit_pos);
movey = v2_dist(hit_pos, camera->pos) > PLAYER_SIZE;
if (movex) camera->pos.x += move.x * MOVE_SPEED * screen->delta;
if (movey) camera->pos.y += move.y * MOVE_SPEED * screen->delta;
}
static void verline(Swapchain* swapchain, int x, int y0, int y1, uint32_t color) { static void verline(Swapchain* swapchain, int x, int y0, int y1, uint32_t color) {
for (int y = y0; y <= y1; y++) { for (int y = y0; y <= y1; y++) {
swapchain->images[swapchain->image_current][(y * swapchain->width) + x] = color; swapchain->images[swapchain->image_current][(y * swapchain->width) + x] = color;
} }
} }
void render(Screen* screen, const Camera* camera) { void render(Screen* screen, const Camera* camera) {
@ -103,7 +26,7 @@ void render(Screen* screen, const Camera* camera) {
for (int x = 0; x < screen->swapchain.width; x++) { for (int x = 0; x < screen->swapchain.width; x++) {
const float xcam = (2 * (x / (float) (swapchain->width))) - 1; const float xcam = (2 * (x / (float) (swapchain->width))) - 1;
const float change = fov * atan(xcam); const float change = camera->fov * atan(xcam);
const float theta = camera->angle + change; const float theta = camera->angle + change;
v2 hit_pos; v2 hit_pos;

View file

@ -1,14 +1,6 @@
#pragma once #pragma once
#include "screen.h" #include "screen.h"
#include "ray.h" #include "camera.h"
typedef struct {
v2 pos;
float angle;
} Camera;
void init_camera(Camera* camera);
void update_camera(Camera* camera, Screen* screeen);
void render(Screen* screen, const Camera* camera); void render(Screen* screen, const Camera* camera);

View file

@ -5,10 +5,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h>
#include <signal.h>
#define XLIB_ILLEGAL_ACCESS #define XLIB_ILLEGAL_ACCESS
#include <X11/X.h> #include <X11/X.h>
@ -33,6 +30,8 @@ typedef struct {
XImage** images; XImage** images;
pthread_t update_thread; pthread_t update_thread;
pthread_mutex_t recreate_lock; pthread_mutex_t recreate_lock;
pthread_mutex_t lock;
uint16_t update_rate;
} WindowState; } WindowState;
static void init_x() { static void init_x() {
@ -173,7 +172,6 @@ void swapchain_next(Swapchain* swapchain) {
next += 1; next += 1;
next %= 3; next %= 3;
} }
swapchain->image_current = next; swapchain->image_current = next;
pthread_mutex_unlock(&swapchain->lock); pthread_mutex_unlock(&swapchain->lock);
} }
@ -184,28 +182,54 @@ void swapchain_submit(Swapchain* swapchain) {
pthread_mutex_unlock(&swapchain->lock); pthread_mutex_unlock(&swapchain->lock);
} }
static long get_time() {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
return round(spec.tv_nsec / 1.0e6) + spec.tv_sec * 1000;
}
static void update_delta(float* delta, long* last) {
long now = get_time();
if (*last == 0) {
*delta = 0;
} else {
*delta = (now - *last) / 1000.0;
}
*last = now;
}
static void* swapchain_thread(void* arg) { static void* swapchain_thread(void* arg) {
struct Screen* screen = (struct Screen*) arg; struct Screen* screen = (struct Screen*) arg;
WindowState* state = (WindowState*) screen->internal; WindowState* state = (WindowState*) screen->internal;
long last = get_time();
float delta;
while (1) { while (1) {
if (screen->swapchain.images == NULL) { if (screen->swapchain.images == NULL) {
return NULL; return NULL;
} }
long now = last;
update_delta(&delta, &now);
if (delta < 1.0 / state->update_rate) {
continue;
} else {
last = now;
}
pthread_mutex_lock(&state->recreate_lock); pthread_mutex_lock(&state->recreate_lock);
pthread_mutex_lock(&screen->swapchain.lock); pthread_mutex_lock(&screen->swapchain.lock);
int index = screen->swapchain.image_recent; screen->swapchain.image_front = screen->swapchain.image_recent;
screen->swapchain.image_front = index;
pthread_mutex_unlock(&screen->swapchain.lock); pthread_mutex_unlock(&screen->swapchain.lock);
XPutImage( XPutImage(
dpy, dpy,
state->window, state->window,
state->graphics_ctx, state->graphics_ctx,
state->images[index], state->images[screen->swapchain.image_front],
0, 0, 0, 0, 0, 0, 0, 0,
screen->swapchain.width, screen->swapchain.width,
screen->swapchain.height screen->swapchain.height
@ -213,8 +237,6 @@ static void* swapchain_thread(void* arg) {
XSync(dpy, 0); XSync(dpy, 0);
pthread_mutex_unlock(&state->recreate_lock); pthread_mutex_unlock(&state->recreate_lock);
usleep(1000 * 1000 / 60);
} }
return NULL; return NULL;
@ -222,7 +244,7 @@ static void* swapchain_thread(void* arg) {
#define FRAMES 3 #define FRAMES 3
void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const char* title) { void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const char* title, uint16_t update_rate) {
if (dpy == NULL) { if (dpy == NULL) {
init_x(); init_x();
@ -233,6 +255,7 @@ void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const c
WindowState* state = malloc(sizeof(WindowState)); WindowState* state = malloc(sizeof(WindowState));
state->window = window; state->window = window;
state->update_rate = update_rate;
screen->swapchain = create_swapchain(width, height, FRAMES, bit_depth, state); screen->swapchain = create_swapchain(width, height, FRAMES, bit_depth, state);
pthread_create(&state->update_thread, NULL, &swapchain_thread, screen); pthread_create(&state->update_thread, NULL, &swapchain_thread, screen);
@ -242,23 +265,6 @@ void init_screen(struct Screen* screen, uint16_t width, uint16_t height, const c
count++; count++;
} }
static long get_time() {
struct timespec spec;
clock_gettime(CLOCK_MONOTONIC, &spec);
return round(spec.tv_nsec / 1.0e6) + spec.tv_sec * 1000;
}
static long last = 0;
static void update_delta(struct Screen* screen) {
long now = get_time();
if (last == 0) {
screen->delta = 0;
} else {
screen->delta = (now - last) / 1000.0;
}
last = now;
}
static void handle_event(struct Screen* screen) { static void handle_event(struct Screen* screen) {
XEvent event; XEvent event;
@ -291,11 +297,11 @@ static void handle_event(struct Screen* screen) {
} }
bool poll_screen(struct Screen* screen) { bool poll_screen(struct Screen* screen) {
while (XPending(dpy)) while (XPending(dpy))
handle_event(screen); handle_event(screen);
update_delta(screen); static long last = 0;
update_delta(&screen->delta, &last);
return true; return true;
} }
@ -320,13 +326,15 @@ void free_screen(struct Screen* screen) {
} }
} }
bool key_pressed(int keycode) { bool key_pressed(int code) {
int keycode = code - dpy->min_keycode;
if (key_checked[keycode]) return false; if (key_checked[keycode]) return false;
if (!key_state[keycode]) return false; if (!key_state[keycode]) return false;
key_checked[keycode] = true; key_checked[keycode] = true;
return true; return true;
} }
bool key_down(int keycode) { bool key_down(int code) {
int keycode = code - dpy->min_keycode;
return key_state[keycode]; return key_state[keycode];
} }

View file

@ -2,7 +2,6 @@
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
// #define _POSIX_C_SOURCE 200809L
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <pthread.h> #include <pthread.h>
@ -29,19 +28,19 @@ struct Screen {
#define Screen struct Screen #define Screen struct Screen
#define KEY_W 17 #define KEY_W 25
#define KEY_A 30 #define KEY_A 38
#define KEY_S 31 #define KEY_S 39
#define KEY_D 32 #define KEY_D 40
#define KEY_UP 103 #define KEY_UP 111
#define KEY_DOWN 108 #define KEY_DOWN 116
#define KEY_LEFT 105 #define KEY_LEFT 113
#define KEY_RIGHT 106 #define KEY_RIGHT 114
#define KEY_MINUS 12 #define KEY_MINUS 20
#define KEY_EQUALS 13 #define KEY_EQUALS 21
#define KEY_ESC 1 #define KEY_ESC 9
void init_screen(Screen* screen, uint16_t width, uint16_t height, const char* title); void init_screen(Screen* screen, uint16_t width, uint16_t height, const char* title, uint16_t update_rate);
bool poll_screen(Screen* screen); bool poll_screen(Screen* screen);
void free_screen(Screen* screen); void free_screen(Screen* screen);