defocus-modules/include/defocus/base.h

278 lines
6.3 KiB
C
Raw Normal View History

#ifndef DEFOCUS_BASE_H
#define DEFOCUS_BASE_H
#include <inttypes.h>
#include <string.h>
2023-05-08 13:28:53 +02:00
#include <immintrin.h>
/** @file base.h
* @brief basic utilities
*/
/** @brief Result codes used throughout the codebase */
typedef enum
{
/** @brief operation successfull */
df_result_success = 0,
/** @brief memory allocation failed */
2023-05-08 13:28:53 +02:00
df_result_out_of_memory = 1,
/** @brief file i/o error */
2023-05-08 13:28:53 +02:00
df_result_io_error = 2,
} df_result;
/** @brief Used to silence warnings about unused variables */
#define DF_UNUSED(x) ((void)sizeof((x)))
/** @brief Evaluates to the number of elements in a static array. */
#define DF_ARRAY_COUNT(a) (sizeof((a)) / sizeof((a)[0]))
/** @brief Zero a memory range */
#define DF_ZERO_MEMORY(ptr, n) memset((ptr), 0, (n))
/** @brief Zero a struct */
#define DF_ZERO_STRUCT(ptr) DF_ZERO_MEMORY(ptr, sizeof(*(ptr)))
/** @brief Zero an array */
#define DF_ZERO_ARRAY(a, n) DF_ZERO_MEMORY(a, sizeof((a)[0]) * (n))
2023-05-09 13:04:14 +02:00
#ifdef _MSC_VER
#ifdef __cplusplus__
#define DF_API extern "C" __declspec(dllexport)
#else
#define DF_API __declspec(dllexport)
#endif /* _MSC_VER && __cplusplus__ */
#else
#ifdef __cplusplus__
#define DF_API extern "C"
#else
#define DF_API
#endif
#endif
/* Simple logging function */
#ifndef DF_ENABLE_LOGGING
#define DF_ENABLE_LOGGING 1
#endif
enum
{
df_log_level_verbose = 0,
df_log_level_info = 1,
df_log_level_warn = 2,
df_log_level_error = 3,
};
#if DF_ENABLE_LOGGING
/** @brief The actual log implementation.
*
* There should be no need to call this directly.
*
* Instead use one of:
* - df_log_verbose()
* - df_log_info()
* - df_log_warn()
* - df_log_error()
* @param level the log level. Used to filter the messages.
* @param file file name of the log location
* @param line line number of the log location
* @param fmt format string of the message.
*/
2023-05-09 13:04:14 +02:00
DF_API void df_log_impl(int level, const char *file, int line, const char *fmt, ...);
#define df_log_verbose(...) df_log_impl(df_log_level_verbose, __FILE__, __LINE__, __VA_ARGS__)
#define df_log_info(...) df_log_impl(df_log_level_info, __FILE__, __LINE__, __VA_ARGS__)
#define df_log_warn(...) df_log_impl(df_log_level_warn, __FILE__, __LINE__, __VA_ARGS__)
#define df_log_error(...) df_log_impl(df_log_level_error, __FILE__, __LINE__, __VA_ARGS__)
#else /* DF_ENABLE_LOGGING = 0 */
#define df_log_verbose(fmt, ...)
#define df_log_info(fmt, ...)
#define df_log_warn(fmt, ...)
#define df_log_error(fmt, ...)
#endif
2023-05-08 13:28:53 +02:00
/* Math constants.
*/
#define DF_PI 3.1415926f
#define DF_PI_OVER_2 1.570796f
#define DF_PI_OVER_4 0.785398f
/* Basic types */
/** @brief RGBA color */
typedef union {
struct
{
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
uint8_t e[4];
} df_color;
/** @brief Linear interpolation between two colors.
*
* @param a first color
* @param b second color
* @param t interpolation factor
* @return a + (b - a) * t
*/
2023-05-09 13:04:14 +02:00
DF_API df_color df_lerp_color(df_color a, df_color b, double t);
/** @brief 2d vector */
typedef union {
struct
{
float x;
float y;
};
struct
{
float u;
float v;
};
float e[2];
} df_v2;
2023-05-08 13:28:53 +02:00
/** @brief Add two 2d vectors */
2023-05-09 13:04:14 +02:00
DF_API df_v2 df_add_v2(df_v2 a, df_v2 b);
2023-05-08 13:28:53 +02:00
/** @brief Subtract two 2d vectors */
2023-05-09 13:04:14 +02:00
DF_API df_v2 df_sub_v2(df_v2 a, df_v2 b);
2023-05-08 13:28:53 +02:00
/** @brief Calculate the dot product of 2d vectors a and b.
*/
2023-05-09 13:04:14 +02:00
DF_API float df_dot_v2(df_v2 a, df_v2 b);
2023-05-08 13:28:53 +02:00
/** @brief Multiply a 2d vector with a scalar.
*/
2023-05-09 13:04:14 +02:00
DF_API df_v2 df_mul_v2(float t, df_v2 v);
2023-05-08 13:28:53 +02:00
/** @brief Returns the normalized version of a 2d vector v
*/
2023-05-09 13:04:14 +02:00
DF_API df_v2 df_normalize_v2(df_v2 v);
2023-05-08 13:28:53 +02:00
/** @brief 3d vector */
typedef union {
struct
{
float x;
float y;
float z;
};
float e[3];
} df_v3;
/** @brief Add two 3d vectors */
2023-05-09 13:04:14 +02:00
DF_API df_v3 df_add_v3(df_v3 a, df_v3 b);
/** @brief Subtract two 3d vectors */
2023-05-09 13:04:14 +02:00
DF_API df_v3 df_sub_v3(df_v3 a, df_v3 b);
/** @brief Calculate the dot product of 3d vectors a and b.
*/
2023-05-09 13:04:14 +02:00
DF_API float df_dot_v3(df_v3 a, df_v3 b);
/** @brief Multiply a 3d vector with a scalar.
*/
2023-05-09 13:04:14 +02:00
DF_API df_v3 df_mul_v3(float t, df_v3 v);
/** @brief Returns the normalized version of a 3d vector v
*/
2023-05-09 13:04:14 +02:00
DF_API df_v3 df_normalize_v3(df_v3 v);
/** @brief A plane in 3d space.
*
* Expressed as the set of all points p for which
* dot((p - base), normal) = 0
*/
typedef struct
{
df_v3 base;
df_v3 normal;
} df_plane;
/** @brief A line in 3d space.
*
* Expressed as the vector equation p = base + t * direction.
*/
typedef struct
{
df_v3 base;
df_v3 direction;
} df_line;
/** @brief The three possible result types of a line-plane intersection test.
*/
typedef enum
{
/** The line and plane intersect in one point */
df_line_plane_intersection_vector,
/** The line is contained in the plane */
df_line_plane_intersection_contained,
/** The line and plane don't intersect (-> they are parallel) */
df_line_plane_intersection_none,
} df_line_plane_intersection_type;
/** @brief Result of a line-plane intersection test.
* The contained vector is only valid if @c type = @c df_line_plane_intersection_vector.
*/
typedef struct
{
df_line_plane_intersection_type type;
df_v3 vec;
} df_line_plane_intersection;
/** @brief Calculate the intersection between a line and a plane in 3d space */
2023-05-09 13:04:14 +02:00
DF_API df_line_plane_intersection df_calc_line_plane_intersection(df_line line, df_plane plane);
2023-05-08 13:28:53 +02:00
/** @brief A 4x4 matrix.
*
* Stored in row major order.
*/
typedef struct df_m4
{
_Alignas(16) union {
float e[16];
__m128 vec[4];
};
} df_m4;
/** Accesses the element at the given row and column of a 4x4 matrix */
#define DF_M4_AT(m, row, col) ((m).e[(row)*4 + (col)])
/** @brief Matrix multiply 4x4 matrix a and b */
2023-05-09 13:04:14 +02:00
DF_API df_m4 df_mul_m4(df_m4 a, df_m4 b);
2023-05-08 13:28:53 +02:00
/** @brief Get a scale matrix */
2023-05-09 13:04:14 +02:00
DF_API df_m4 df_scale(float x, float y, float z);
2023-05-08 13:28:53 +02:00
2023-05-09 13:04:14 +02:00
DF_API df_m4 df_translate(float x, float y, float z);
2023-05-08 13:28:53 +02:00
/** @brief Transform (i.e. multiply) a 3d vector v by the transformation matrix T */
2023-05-09 13:04:14 +02:00
DF_API df_v3 df_transform_v3(df_m4 T, df_v3 v);
2023-05-08 13:28:53 +02:00
/** @brief Calculate the inverse of a non-scaling transform matrix.
*
* Special fast case.
*/
2023-05-09 13:04:14 +02:00
DF_API df_m4 df_inverse_transform_no_scale(df_m4 M);
2023-05-08 13:28:53 +02:00
/** @brief Calculate the inverse of a transform matrix */
2023-05-09 13:04:14 +02:00
DF_API df_m4 df_inverse_transform(df_m4 M);
/** @brief Calculate the inverse of a general (invertible) 4x4 matrix */
DF_API df_m4 df_inverse(df_m4 M);
#endif