2023-04-06 18:54:30 +02:00
|
|
|
#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>
|
|
|
|
|
2023-04-06 18:54:30 +02:00
|
|
|
/** @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,
|
2023-04-06 18:54:30 +02:00
|
|
|
|
|
|
|
/** @brief file i/o error */
|
2023-05-08 13:28:53 +02:00
|
|
|
df_result_io_error = 2,
|
2023-04-06 18:54:30 +02:00
|
|
|
} 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))
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
|
|
|
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
|
|
|
|
|
2023-04-06 18:54:30 +02:00
|
|
|
/* 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
|
|
|
|
*/
|
|
|
|
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 */
|
|
|
|
df_v2 df_add_v2(df_v2 a, df_v2 b);
|
|
|
|
|
|
|
|
/** @brief Subtract two 2d vectors */
|
|
|
|
df_v2 df_sub_v2(df_v2 a, df_v2 b);
|
|
|
|
|
|
|
|
/** @brief Calculate the dot product of 2d vectors a and b.
|
|
|
|
*/
|
|
|
|
float df_dot_v2(df_v2 a, df_v2 b);
|
|
|
|
|
|
|
|
/** @brief Multiply a 2d vector with a scalar.
|
|
|
|
*/
|
|
|
|
df_v2 df_mul_v2(float t, df_v2 v);
|
|
|
|
|
|
|
|
/** @brief Returns the normalized version of a 2d vector v
|
|
|
|
*/
|
|
|
|
df_v2 df_normalize_v2(df_v2 v);
|
|
|
|
|
2023-04-06 18:54:30 +02:00
|
|
|
/** @brief 3d vector */
|
|
|
|
typedef union {
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
float x;
|
|
|
|
float y;
|
|
|
|
float z;
|
|
|
|
};
|
|
|
|
float e[3];
|
|
|
|
} df_v3;
|
|
|
|
|
|
|
|
/** @brief Add two 3d vectors */
|
|
|
|
df_v3 df_add_v3(df_v3 a, df_v3 b);
|
|
|
|
|
|
|
|
/** @brief Subtract two 3d vectors */
|
|
|
|
df_v3 df_sub_v3(df_v3 a, df_v3 b);
|
|
|
|
|
|
|
|
/** @brief Calculate the dot product of 3d vectors a and b.
|
|
|
|
*/
|
|
|
|
float df_dot_v3(df_v3 a, df_v3 b);
|
|
|
|
|
|
|
|
/** @brief Multiply a 3d vector with a scalar.
|
|
|
|
*/
|
|
|
|
df_v3 df_mul_v3(float t, df_v3 v);
|
|
|
|
|
|
|
|
/** @brief Returns the normalized version of a 3d vector v
|
|
|
|
*/
|
|
|
|
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 */
|
|
|
|
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 */
|
|
|
|
df_m4 df_mul_m4(df_m4 a, df_m4 b);
|
|
|
|
|
|
|
|
/** @brief Get a scale matrix */
|
|
|
|
df_m4 df_scale(float x, float y, float z);
|
|
|
|
|
|
|
|
df_m4 df_translate(float x, float y, float z);
|
|
|
|
|
|
|
|
/** @brief Transform (i.e. multiply) a 3d vector v by the transformation matrix T */
|
|
|
|
df_v3 df_transform_v3(df_m4 T, df_v3 v);
|
|
|
|
|
|
|
|
/** @brief Calculate the inverse of a non-scaling transform matrix.
|
|
|
|
*
|
|
|
|
* Special fast case.
|
|
|
|
*/
|
|
|
|
df_m4 df_inverse_transform_no_scale(df_m4 M);
|
|
|
|
|
|
|
|
/** @brief Calculate the inverse of a transform matrix */
|
|
|
|
df_m4 df_inverse_transform(df_m4 M);
|
2023-04-06 18:54:30 +02:00
|
|
|
#endif
|