townengine/src/vec.h

127 lines
3.3 KiB
C
Raw Normal View History

#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 };
}
2024-07-30 16:36:59 +00:00
static inline t_fvec2 fvec2_scale(t_fvec2 a, float s) {
return (t_fvec2) { a.x * s, a.y * s };
}
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) {
2024-07-30 18:56:23 +00:00
return a.x * b.x + a.y * b.y + 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), \
2024-07-30 16:36:59 +00:00
t_fvec2: fvec2_scale, \
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