Create linear algebra module
This commit is contained in:
1 parent
74f15dd132
commit
f546f27a42
5 files changed
+165
-144
No files matched your search
+2
-1
@@ -37,8 +37,9 @@ add_shaders(shaders
|
||||
)
|
||||
|
||||
add_executable(demo
|
||||
main.c
|
||||
gpu.c
|
||||
linear_alg.c
|
||||
main.c
|
||||
)
|
||||
configure_target(demo)
|
||||
target_include_directories(demo PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
#ifndef GPU_H
|
||||
#define GPU_H
|
||||
|
||||
#include "linear_alg.h"
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define SWAPCHAIN_IMG_BUFFER_SIZE 4
|
||||
|
||||
typedef struct {
|
||||
float x, y, z;
|
||||
} vec3_t;
|
||||
|
||||
typedef struct {
|
||||
float x, y, z, w;
|
||||
} vec4_t;
|
||||
|
||||
typedef struct {
|
||||
vec4_t x, y, z, w;
|
||||
} mat4_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t position;
|
||||
vec3_t colour;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "linear_alg.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
vec3_t vec3_sub(vec3_t v, vec3_t u)
|
||||
{
|
||||
return (vec3_t) { v.x - u.x, v.y - u.y, v.z - u.z };
|
||||
}
|
||||
|
||||
float vec3_len(vec3_t v)
|
||||
{
|
||||
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
||||
vec3_t vec3_norm(vec3_t v)
|
||||
{
|
||||
const float l = vec3_len(v);
|
||||
return (vec3_t) { v.x / l, v.y / l, v.z / l };
|
||||
}
|
||||
|
||||
float vec3_dot(vec3_t v, vec3_t u)
|
||||
{
|
||||
return v.x * u.x + v.y * u.y + v.z * u.z;
|
||||
}
|
||||
|
||||
vec3_t vec3_cross(vec3_t v, vec3_t u)
|
||||
{
|
||||
return (vec3_t) {
|
||||
v.y * u.z - v.z * u.y,
|
||||
v.z * u.x - v.x * u.z,
|
||||
v.x * u.y - v.y * u.x,
|
||||
};
|
||||
}
|
||||
|
||||
mat4_t mat4_mul(mat4_t m, mat4_t n)
|
||||
{
|
||||
#define ELEM(i, j) m.x.i *n.j.x + m.y.i *n.j.y + m.z.i *n.j.z + m.w.i *n.j.w
|
||||
return (mat4_t) {
|
||||
{ ELEM(x, x), ELEM(y, x), ELEM(z, x), ELEM(w, x) },
|
||||
{ ELEM(x, y), ELEM(y, y), ELEM(z, y), ELEM(w, y) },
|
||||
{ ELEM(x, z), ELEM(y, z), ELEM(z, z), ELEM(w, z) },
|
||||
{ ELEM(x, w), ELEM(y, w), ELEM(z, w), ELEM(w, w) },
|
||||
};
|
||||
#undef ELEM
|
||||
}
|
||||
|
||||
mat4_t mat4_lookat(vec3_t camera, vec3_t target, vec3_t up)
|
||||
{
|
||||
const vec3_t s = vec3_sub(target, camera);
|
||||
const vec3_t s_hat = vec3_norm(s);
|
||||
const vec3_t u_hat = vec3_norm(vec3_cross(up, s_hat));
|
||||
const vec3_t v_hat = vec3_cross(s_hat, u_hat);
|
||||
return (mat4_t) {
|
||||
{ u_hat.x, v_hat.x, s_hat.x, 0 },
|
||||
{ u_hat.y, v_hat.y, s_hat.y, 0 },
|
||||
{ u_hat.z, v_hat.z, s_hat.z, 0 },
|
||||
{
|
||||
-vec3_dot(u_hat, camera),
|
||||
-vec3_dot(v_hat, camera),
|
||||
-vec3_dot(s_hat, camera),
|
||||
1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
mat4_t mat4_perspective(float aspect, float fov, float near, float far)
|
||||
{
|
||||
const float r = 2 * near * tanf(fov / 2);
|
||||
const float t = r * aspect;
|
||||
return (mat4_t) {
|
||||
{ near / t, 0, 0, 0 },
|
||||
{ 0, -near / r, 0, 0 },
|
||||
{ 0, 0, far / (far - near), 1 },
|
||||
{ 0, 0, -far * near / (far - near), 0 },
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifndef LINEAR_ALG_H
|
||||
#define LINEAR_ALG_H
|
||||
|
||||
#define PI 3.14159265358979323846264
|
||||
|
||||
typedef struct {
|
||||
float x, y, z;
|
||||
} vec3_t;
|
||||
|
||||
typedef struct {
|
||||
float x, y, z, w;
|
||||
} vec4_t;
|
||||
|
||||
typedef struct {
|
||||
vec4_t x, y, z, w;
|
||||
} mat4_t;
|
||||
|
||||
#define MAT4_ID \
|
||||
{ \
|
||||
{ 1, 0, 0, 0 }, \
|
||||
{ 0, 1, 0, 0 }, \
|
||||
{ 0, 0, 1, 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define MAT4_SCALE(sf) \
|
||||
{ \
|
||||
{ sf, 0, 0, 0 }, \
|
||||
{ 0, sf, 0, 0 }, \
|
||||
{ 0, 0, sf, 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define MAT4_TRANSLATE(x, y, z) \
|
||||
{ \
|
||||
{ 1, 0, 0, 0 }, \
|
||||
{ 0, 1, 0, 0 }, \
|
||||
{ 0, 0, 1, 0 }, \
|
||||
{ x, y, z, 1 }, \
|
||||
}
|
||||
|
||||
#define MAT4_ROTATE_X(a) \
|
||||
{ \
|
||||
{ 1, 0, 0, 0 }, \
|
||||
{ 0, cosf(a), sinf(a), 0 }, \
|
||||
{ 0, -sinf(a), cosf(a), 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define MAT4_ROTATE_Y(a) \
|
||||
{ \
|
||||
{ cosf(a), 0, -sinf(a), 0 }, \
|
||||
{ 0, 1, 0, 0 }, \
|
||||
{ sinf(a), 0, cosf(a), 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define MAT4_ROTATE_Z(a) \
|
||||
{ \
|
||||
{ cosf(a), sinf(a), 0, 0 }, \
|
||||
{ -sinf(a), cosf(a), 0, 0 }, \
|
||||
{ 0, 0, 1, 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
vec3_t vec3_sub(vec3_t v, vec3_t u);
|
||||
float vec3_len(vec3_t v);
|
||||
vec3_t vec3_norm(vec3_t v);
|
||||
float vec3_dot(vec3_t v, vec3_t u);
|
||||
vec3_t vec3_cross(vec3_t v, vec3_t u);
|
||||
|
||||
mat4_t mat4_mul(mat4_t m, mat4_t n);
|
||||
mat4_t mat4_lookat(vec3_t camera, vec3_t target, vec3_t up);
|
||||
mat4_t mat4_perspective(float aspect, float fov, float near, float far);
|
||||
|
||||
#endif
|
||||
@@ -5,10 +5,6 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979324
|
||||
#endif
|
||||
|
||||
#define W 800
|
||||
#define H 600
|
||||
|
||||
@@ -31,54 +27,6 @@ typedef enum {
|
||||
|
||||
static axis_t rot_axis = AXIS_Y;
|
||||
|
||||
#define ID \
|
||||
{ \
|
||||
{ 1, 0, 0, 0 }, \
|
||||
{ 0, 1, 0, 0 }, \
|
||||
{ 0, 0, 1, 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define SCALE(sf) \
|
||||
{ \
|
||||
{ sf, 0, 0, 0 }, \
|
||||
{ 0, sf, 0, 0 }, \
|
||||
{ 0, 0, sf, 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define TRANSLATE(x, y, z) \
|
||||
{ \
|
||||
{ 1, 0, 0, 0 }, \
|
||||
{ 0, 1, 0, 0 }, \
|
||||
{ 0, 0, 1, 0 }, \
|
||||
{ x, y, z, 1 }, \
|
||||
}
|
||||
|
||||
#define ROT_X(a) \
|
||||
{ \
|
||||
{ 1, 0, 0, 0 }, \
|
||||
{ 0, cosf(a), sinf(a), 0 }, \
|
||||
{ 0, -sinf(a), cosf(a), 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define ROT_Y(a) \
|
||||
{ \
|
||||
{ cosf(a), 0, -sinf(a), 0 }, \
|
||||
{ 0, 1, 0, 0 }, \
|
||||
{ sinf(a), 0, cosf(a), 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
#define ROT_Z(a) \
|
||||
{ \
|
||||
{ cosf(a), sinf(a), 0, 0 }, \
|
||||
{ -sinf(a), cosf(a), 0, 0 }, \
|
||||
{ 0, 0, 1, 0 }, \
|
||||
{ 0, 0, 0, 1 }, \
|
||||
}
|
||||
|
||||
static void
|
||||
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
@@ -106,76 +54,6 @@ key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
||||
}
|
||||
}
|
||||
|
||||
static vec3_t sub(vec3_t v, vec3_t u)
|
||||
{
|
||||
return (vec3_t) { v.x - u.x, v.y - u.y, v.z - u.z };
|
||||
}
|
||||
|
||||
static float len(vec3_t v)
|
||||
{
|
||||
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
||||
static vec3_t norm(vec3_t v)
|
||||
{
|
||||
const float s = len(v);
|
||||
return (vec3_t) { v.x / s, v.y / s, v.z / s };
|
||||
}
|
||||
|
||||
static float dot(vec3_t v, vec3_t u)
|
||||
{
|
||||
return v.x * u.x + v.y * u.y + v.z * u.z;
|
||||
}
|
||||
|
||||
static vec3_t cross(vec3_t v, vec3_t u)
|
||||
{
|
||||
return (vec3_t) {
|
||||
v.y * u.z - v.z * u.y,
|
||||
v.z * u.x - v.x * u.z,
|
||||
v.x * u.y - v.y * u.x,
|
||||
};
|
||||
}
|
||||
|
||||
static mat4_t mul(mat4_t m, mat4_t n)
|
||||
{
|
||||
#define ELEM(i, j) m.x.i *n.j.x + m.y.i *n.j.y + m.z.i *n.j.z + m.w.i *n.j.w
|
||||
return (mat4_t) {
|
||||
{ ELEM(x, x), ELEM(y, x), ELEM(z, x), ELEM(w, x) },
|
||||
{ ELEM(x, y), ELEM(y, y), ELEM(z, y), ELEM(w, y) },
|
||||
{ ELEM(x, z), ELEM(y, z), ELEM(z, z), ELEM(w, z) },
|
||||
{ ELEM(x, w), ELEM(y, w), ELEM(z, w), ELEM(w, w) },
|
||||
};
|
||||
#undef MUL_ELEM
|
||||
}
|
||||
|
||||
static mat4_t lookat(vec3_t cam, vec3_t tgt, vec3_t up)
|
||||
{
|
||||
const vec3_t s = sub(tgt, cam);
|
||||
|
||||
const vec3_t s_hat = norm(s);
|
||||
const vec3_t u_hat = norm(cross(up, s_hat));
|
||||
const vec3_t v_hat = cross(s_hat, u_hat);
|
||||
|
||||
return (mat4_t) {
|
||||
{ u_hat.x, v_hat.x, s_hat.x, 0 },
|
||||
{ u_hat.y, v_hat.y, s_hat.y, 0 },
|
||||
{ u_hat.z, v_hat.z, s_hat.z, 0 },
|
||||
{ -dot(u_hat, cam), -dot(v_hat, cam), -dot(s_hat, cam), 1 },
|
||||
};
|
||||
}
|
||||
|
||||
static mat4_t persp(float aspect, float fov, float ncp, float fcp)
|
||||
{
|
||||
const float r = 2 * ncp * tanf(fov / 2);
|
||||
const float t = r * aspect;
|
||||
return (mat4_t) {
|
||||
{ ncp / t, 0, 0, 0 },
|
||||
{ 0, -ncp / r, 0, 0 },
|
||||
{ 0, 0, fcp / (fcp - ncp), 1 },
|
||||
{ 0, 0, -fcp * ncp / (fcp - ncp), 0 },
|
||||
};
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Set up window
|
||||
@@ -203,27 +81,27 @@ int main()
|
||||
const vec3_t cam = { 2, 2, -2 };
|
||||
const vec3_t tgt = { 0, 0, 0 };
|
||||
mvp_t mvp = {
|
||||
.model = SCALE(2),
|
||||
.view = lookat(cam, tgt, (vec3_t) { 0, 1, 0 }),
|
||||
.proj = persp((float)W / H, M_PI / 6, 0.1, 10.0),
|
||||
.model = MAT4_SCALE(2),
|
||||
.view = mat4_lookat(cam, tgt, (vec3_t) { 0, 1, 0 }),
|
||||
.proj = mat4_perspective((float)W / H, PI / 6, 0.1, 10.0),
|
||||
};
|
||||
|
||||
const mat4_t rotx = ROT_X(M_PI / 128);
|
||||
const mat4_t roty = ROT_Y(M_PI / 128);
|
||||
const mat4_t rotz = ROT_Z(M_PI / 128);
|
||||
const mat4_t rotx = MAT4_ROTATE_X(PI / 128);
|
||||
const mat4_t roty = MAT4_ROTATE_Y(PI / 128);
|
||||
const mat4_t rotz = MAT4_ROTATE_Z(PI / 128);
|
||||
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwPollEvents();
|
||||
|
||||
switch (rot_axis) {
|
||||
case AXIS_X:
|
||||
mvp.model = mul(rotx, mvp.model);
|
||||
mvp.model = mat4_mul(rotx, mvp.model);
|
||||
break;
|
||||
case AXIS_Y:
|
||||
mvp.model = mul(roty, mvp.model);
|
||||
mvp.model = mat4_mul(roty, mvp.model);
|
||||
break;
|
||||
case AXIS_Z:
|
||||
mvp.model = mul(rotz, mvp.model);
|
||||
mvp.model = mat4_mul(rotz, mvp.model);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user