separation to vec.h, generic vector ops, camera class and its usage for spatial rendering
This commit is contained in:
parent
86d135281e
commit
ff077c5d0d
@ -36,16 +36,16 @@ set(SOURCE_FILES
|
|||||||
third-party/stb/stb_vorbis.c
|
third-party/stb/stb_vorbis.c
|
||||||
third-party/glad/src/glad.c
|
third-party/glad/src/glad.c
|
||||||
|
|
||||||
src/config.h
|
|
||||||
src/context.h
|
|
||||||
src/context.c
|
|
||||||
src/main.c
|
src/main.c
|
||||||
src/audio.c
|
src/config.h
|
||||||
|
src/context.c src/context.h
|
||||||
|
src/audio.c src/audio.h
|
||||||
src/util.c src/util.h
|
src/util.c src/util.h
|
||||||
src/rendering.c src/rendering.h
|
src/rendering.c src/rendering.h
|
||||||
src/textures.c src/textures.h
|
src/textures.c src/textures.h
|
||||||
src/input.c src/input.h
|
src/input.c src/input.h
|
||||||
src/text.c src/text.h
|
src/text.c src/text.h
|
||||||
|
src/camera.c src/camera.h
|
||||||
src/game_api.h
|
src/game_api.h
|
||||||
|
|
||||||
src/game/game.c src/game/game.h
|
src/game/game.c src/game/game.h
|
||||||
|
27
src/camera.c
Normal file
27
src/camera.c
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "camera.h"
|
||||||
|
|
||||||
|
t_matrix4 camera_look_at(const t_camera *const camera) {
|
||||||
|
/* from cglm */
|
||||||
|
const t_fvec3 f = m_vec_norm(m_vec_sub(camera->pos, camera->target));
|
||||||
|
const t_fvec3 r = m_vec_norm(m_vec_cross(f, camera->up));
|
||||||
|
const t_fvec3 u = m_vec_cross(f, r);
|
||||||
|
|
||||||
|
t_matrix4 result;
|
||||||
|
|
||||||
|
result.row[0].x = r.x;
|
||||||
|
result.row[0].y = u.x;
|
||||||
|
result.row[0].z =-f.x;
|
||||||
|
result.row[1].x = r.y;
|
||||||
|
result.row[1].y = u.y;
|
||||||
|
result.row[1].z =-f.y;
|
||||||
|
result.row[2].x = r.z;
|
||||||
|
result.row[2].y = u.z;
|
||||||
|
result.row[2].z =-f.z;
|
||||||
|
result.row[3].x =-m_vec_dot(r, camera->pos);
|
||||||
|
result.row[3].y =-m_vec_dot(u, camera->pos);
|
||||||
|
result.row[3].z = m_vec_dot(f, camera->pos);
|
||||||
|
result.row[0].w = result.row[1].w = result.row[2].w = 0.0f;
|
||||||
|
result.row[3].w = 1.0f;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
15
src/camera.h
Normal file
15
src/camera.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef CAMERA_H
|
||||||
|
#define CAMERA_H
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/* first person camera class */
|
||||||
|
typedef struct camera {
|
||||||
|
t_fvec3 pos; /* eye position */
|
||||||
|
t_fvec3 target; /* target point */
|
||||||
|
t_fvec3 up; /* normalized up vector */
|
||||||
|
} t_camera;
|
||||||
|
|
||||||
|
t_matrix4 camera_look_at(const t_camera *camera);
|
||||||
|
|
||||||
|
#endif
|
@ -11,6 +11,15 @@ static void ingame_tick(struct state *state) {
|
|||||||
world_drawdef(scn->world);
|
world_drawdef(scn->world);
|
||||||
player_calc(scn->player);
|
player_calc(scn->player);
|
||||||
|
|
||||||
|
static t_camera cam = { .pos = { 0 }, .target = { 0, 0, -1 }, .up = { 0, -1, 0 } };
|
||||||
|
|
||||||
|
if (input_is_action_pressed(&ctx.input, "player_left"))
|
||||||
|
cam.pos.x -= 0.01f;
|
||||||
|
if (input_is_action_pressed(&ctx.input, "player_right"))
|
||||||
|
cam.pos.x += 0.01f;
|
||||||
|
|
||||||
|
push_camera(&cam);
|
||||||
|
|
||||||
push_sprite_ex((t_frect){ .x = 32, .y = 64, .w = 64, .h = 64 }, (t_push_sprite_args){
|
push_sprite_ex((t_frect){ .x = 32, .y = 64, .w = 64, .h = 64 }, (t_push_sprite_args){
|
||||||
.path = "/assets/light.png",
|
.path = "/assets/light.png",
|
||||||
.color = (t_color){255, 0, 0, 255}, });
|
.color = (t_color){255, 0, 0, 255}, });
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
#include <tgmath.h>
|
#include <tgmath.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: have a default initialized one */
|
||||||
|
static t_matrix4 camera_projection;
|
||||||
|
|
||||||
|
|
||||||
void render_queue_clear(void) {
|
void render_queue_clear(void) {
|
||||||
/* since i don't intend to free the queues, */
|
/* since i don't intend to free the queues, */
|
||||||
/* it's faster and simpler to just "start over" */
|
/* it's faster and simpler to just "start over" */
|
||||||
@ -160,7 +164,7 @@ void render(void) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadMatrixf(&camera_projection.row[0].x);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
@ -168,6 +172,9 @@ void render(void) {
|
|||||||
render_space();
|
render_space();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: only do it when transition between spaces is needed */
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
{
|
{
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
@ -181,3 +188,8 @@ void render(void) {
|
|||||||
|
|
||||||
SDL_GL_SwapWindow(ctx.window);
|
SDL_GL_SwapWindow(ctx.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_camera(const t_camera *const camera) {
|
||||||
|
/* TODO: skip recaulculating if it's the same? */
|
||||||
|
camera_projection = camera_look_at(camera);
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define RENDERING_H
|
#define RENDERING_H
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "camera.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
@ -63,6 +64,9 @@ void unfurl_triangle(const char *path,
|
|||||||
// t_fvec2 scaling,
|
// t_fvec2 scaling,
|
||||||
// t_frect uvs);
|
// t_frect uvs);
|
||||||
|
|
||||||
|
/* pushes a camera state to be used for all future unfurl_* commands */
|
||||||
|
void push_camera(const t_camera *camera);
|
||||||
|
|
||||||
/* renders the background, then the primitives in all render queues */
|
/* renders the background, then the primitives in all render queues */
|
||||||
void render(void);
|
void render(void);
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
#define CIRCLES_H
|
#define CIRCLES_H
|
||||||
|
|
||||||
#include "../util.h"
|
#include "../util.h"
|
||||||
#include "internal_api.h"
|
|
||||||
#include "../context.h"
|
#include "../context.h"
|
||||||
|
#include "internal_api.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "../context.h"
|
#include "../context.h"
|
||||||
#include "../util.h"
|
#include "../util.h"
|
||||||
#include "quad_element_buffer.h"
|
#include "quad_element_buffer.h"
|
||||||
|
#include "internal_api.h"
|
||||||
|
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "../textures.h"
|
#include "../textures.h"
|
||||||
#include "../context.h"
|
#include "../context.h"
|
||||||
|
#include "internal_api.h"
|
||||||
|
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
|
|
||||||
@ -66,6 +67,8 @@ static void draw_uncolored_space_traingle_batch(struct mesh_batch *batch,
|
|||||||
t_rect srcrect = textures_get_srcrect(&ctx.texture_cache, texture_key);
|
t_rect srcrect = textures_get_srcrect(&ctx.texture_cache, texture_key);
|
||||||
t_rect dims = textures_get_dims(&ctx.texture_cache, texture_key);
|
t_rect dims = textures_get_dims(&ctx.texture_cache, texture_key);
|
||||||
|
|
||||||
|
/* TODO: fast path for uvs mapped directly on srcrect corners? */
|
||||||
|
|
||||||
const float wr = (float)srcrect.w / (float)dims.w;
|
const float wr = (float)srcrect.w / (float)dims.w;
|
||||||
const float hr = (float)srcrect.h / (float)dims.h;
|
const float hr = (float)srcrect.h / (float)dims.h;
|
||||||
const float xr = (float)srcrect.x / (float)dims.w;
|
const float xr = (float)srcrect.x / (float)dims.w;
|
||||||
|
15
src/util.c
15
src/util.c
@ -194,21 +194,6 @@ t_fvec2 frect_center(t_frect rect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
t_fvec2 fvec2_from_vec2(t_vec2 vec) {
|
|
||||||
return (t_fvec2) {
|
|
||||||
.x = (float)vec.x,
|
|
||||||
.y = (float)vec.y,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
t_fvec2 fvec2_from_shvec2(t_shvec2 vec) {
|
|
||||||
return (t_fvec2) {
|
|
||||||
.x = (float)vec.x,
|
|
||||||
.y = (float)vec.y,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void tick_timer(int *value) {
|
void tick_timer(int *value) {
|
||||||
*value = MAX(*value - 1, 0);
|
*value = MAX(*value - 1, 0);
|
||||||
}
|
}
|
||||||
|
50
src/util.h
50
src/util.h
@ -1,6 +1,7 @@
|
|||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
|
#include "vec.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <physfs.h>
|
#include <physfs.h>
|
||||||
@ -78,40 +79,13 @@ _Alignas(4)
|
|||||||
} t_color;
|
} t_color;
|
||||||
|
|
||||||
|
|
||||||
/* a point in some space (integer) */
|
|
||||||
typedef struct vec2 {
|
|
||||||
int x, y;
|
|
||||||
} t_vec2;
|
|
||||||
|
|
||||||
|
|
||||||
/* a point in some space (floating point) */
|
|
||||||
typedef struct fvec2 {
|
|
||||||
_Alignas(8)
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
} t_fvec2;
|
|
||||||
|
|
||||||
|
|
||||||
/* a point in some three dimension space (floating point) */
|
|
||||||
/* y goes up, x goes to the right */
|
|
||||||
typedef struct fvec3 {
|
|
||||||
_Alignas(8)
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
} t_fvec3;
|
|
||||||
|
|
||||||
|
|
||||||
/* a point in some space (short) */
|
|
||||||
typedef struct shvec2 {
|
|
||||||
short x, y;
|
|
||||||
} t_shvec2;
|
|
||||||
|
|
||||||
|
|
||||||
/* a rectangle with the origin at the upper left (integer) */
|
/* a rectangle with the origin at the upper left (integer) */
|
||||||
typedef struct rect {
|
typedef struct rect {
|
||||||
int x, y;
|
_Alignas(16)
|
||||||
int w, h;
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
int32_t w;
|
||||||
|
int32_t h;
|
||||||
} t_rect;
|
} t_rect;
|
||||||
|
|
||||||
|
|
||||||
@ -135,15 +109,9 @@ t_frect to_frect(t_rect rect);
|
|||||||
t_fvec2 frect_center(t_frect rect);
|
t_fvec2 frect_center(t_frect rect);
|
||||||
|
|
||||||
|
|
||||||
/* aren't macros to prevent double evaluation with side effects */
|
typedef struct matrix4 {
|
||||||
/* maybe could be inlined? i hope LTO will resolve this */
|
t_fvec4 row[4];
|
||||||
t_fvec2 fvec2_from_vec2(t_vec2 vec);
|
} t_matrix4;
|
||||||
t_fvec2 fvec2_from_shvec2(t_shvec2 vec);
|
|
||||||
|
|
||||||
#define m_to_fvec2(p_any_vec2) (_Generic((p_any_vec2), \
|
|
||||||
t_vec2: fvec2_from_vec2, \
|
|
||||||
t_shvec2: fvec2_from_shvec2 \
|
|
||||||
)(p_any_vec2))
|
|
||||||
|
|
||||||
|
|
||||||
/* decrements an lvalue (which should be an int), stopping at 0 */
|
/* decrements an lvalue (which should be an int), stopping at 0 */
|
||||||
|
121
src/vec.h
Normal file
121
src/vec.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#ifndef VEC_H
|
||||||
|
#define VEC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* a point in some space (integer) */
|
||||||
|
typedef struct vec2 {
|
||||||
|
_Alignas(8)
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
} t_vec2;
|
||||||
|
|
||||||
|
|
||||||
|
/* a point in some space (floating point) */
|
||||||
|
typedef struct fvec2 {
|
||||||
|
_Alignas(8)
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} t_fvec2;
|
||||||
|
|
||||||
|
|
||||||
|
/* a point in some three dimension space (floating point) */
|
||||||
|
/* y goes up, x goes to the right */
|
||||||
|
typedef struct fvec3 {
|
||||||
|
_Alignas(16)
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} t_fvec3;
|
||||||
|
|
||||||
|
|
||||||
|
/* a point in some three dimension space (floating point) */
|
||||||
|
/* y goes up, x goes to the right */
|
||||||
|
typedef struct fvec4 {
|
||||||
|
_Alignas(16)
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float w;
|
||||||
|
} t_fvec4;
|
||||||
|
|
||||||
|
|
||||||
|
/* a point in some space (short) */
|
||||||
|
typedef struct shvec2 {
|
||||||
|
_Alignas(4)
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
|
} t_shvec2;
|
||||||
|
|
||||||
|
|
||||||
|
/* aren't macros to prevent double evaluation with side effects */
|
||||||
|
/* maybe could be inlined? i hope LTO will resolve this */
|
||||||
|
static inline t_fvec2 fvec2_from_vec2(t_vec2 vec) {
|
||||||
|
return (t_fvec2) {
|
||||||
|
.x = (float)vec.x,
|
||||||
|
.y = (float)vec.y,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline t_fvec2 fvec2_from_shvec2(t_shvec2 vec) {
|
||||||
|
return (t_fvec2) {
|
||||||
|
.x = (float)vec.x,
|
||||||
|
.y = (float)vec.y,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline t_fvec3 fvec3_sub(t_fvec3 a, t_fvec3 b) {
|
||||||
|
return (t_fvec3) { a.x - b.x, a.y - b.y, a.z - b.z };
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline t_fvec3 fvec3_scale(t_fvec3 a, float s) {
|
||||||
|
return (t_fvec3) { a.x * s, a.y * s, a.z * s };
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float fvec3_dot(t_fvec3 a, t_fvec3 b) {
|
||||||
|
return a.x * b.x + a.x * b.x + a.z * b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline t_fvec3 fvec3_cross(t_fvec3 a, t_fvec3 b) {
|
||||||
|
return (t_fvec3) {
|
||||||
|
a.y * b.z - a.z * b.y,
|
||||||
|
a.z * b.x - a.x * b.z,
|
||||||
|
a.x * b.y - a.y * b.x,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: fast_sqrt version? */
|
||||||
|
static inline t_fvec3 fvec3_norm(t_fvec3 a) {
|
||||||
|
const float n = sqrtf(fvec3_dot(a, a));
|
||||||
|
/* TODO: do we need truncating over epsilon as cglm does? */
|
||||||
|
return fvec3_scale(a, 1.0f / n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define m_to_fvec2(p_any_vec2) (_Generic((p_any_vec2), \
|
||||||
|
t_vec2: fvec2_from_vec2, \
|
||||||
|
t_shvec2: fvec2_from_shvec2 \
|
||||||
|
)(p_any_vec2))
|
||||||
|
|
||||||
|
#define m_vec_sub(p_any_vec0, p_any_vec1) (_Generic((p_any_vec0), \
|
||||||
|
t_fvec3: fvec3_sub \
|
||||||
|
)(p_any_vec0, p_any_vec1))
|
||||||
|
|
||||||
|
#define m_vec_scale(p_any_vec, p_any_scalar) (_Generic((p_any_vec), \
|
||||||
|
t_fvec3: fvec3_scale \
|
||||||
|
)(p_any_vec, p_any_scalar))
|
||||||
|
|
||||||
|
#define m_vec_dot(p_any_vec0, p_any_vec1) (_Generic((p_any_vec0), \
|
||||||
|
t_fvec3: fvec3_dot \
|
||||||
|
)(p_any_vec0, p_any_vec1))
|
||||||
|
|
||||||
|
#define m_vec_cross(p_any_vec0, p_any_vec1) (_Generic((p_any_vec0), \
|
||||||
|
t_fvec3: fvec3_cross \
|
||||||
|
)(p_any_vec0, p_any_vec1))
|
||||||
|
|
||||||
|
#define m_vec_norm(p_any_vec) (_Generic((p_any_vec), \
|
||||||
|
t_fvec3: fvec3_norm \
|
||||||
|
)(p_any_vec))
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user