gb.h v0.26d, gb_math.h v0.07

This commit is contained in:
Ginger Bill 2016-10-16 12:30:47 +01:00
parent 4e7b07c9a7
commit 4778aa6bf0
3 changed files with 259 additions and 70 deletions

View File

@ -4,8 +4,8 @@ gb single-file public domain libraries for C & C++
library | latest version | category | description
----------------|----------------|----------|-------------
**gb.h** | 0.25 | misc | Helper library (Standard library _improvement_)
**gb_math.h** | 0.06h | math | Vector math library geared towards game development
**gb.h** | 0.26d | misc | Helper library (Standard library _improvement_)
**gb_math.h** | 0.07 | math | Vector math library geared towards game development
**gb_gl.h** | 0.05 | graphics | OpenGL Helper Library
**gb_string.h** | 0.95a | strings | A better string library (this is built into gb.h too with custom allocator support!)
**gb_ini.h** | 0.93 | misc | Simple ini file loader library

171
gb.h
View File

@ -1,4 +1,4 @@
/* gb.h - v0.26c - Ginger Bill's C Helper Library - public domain
/* gb.h - v0.26d - Ginger Bill's C Helper Library - public domain
- no warranty implied; use at your own risk
This is a single header file with a bunch of useful stuff
@ -58,6 +58,7 @@ TODOS
- More date & time functions
VERSION HISTORY
0.26d - Minor changes to how gbFile works
0.26c - gb_str_to_f* fix
0.26b - Minor fixes
0.26a - gbString Fix
@ -702,6 +703,10 @@ extern "C++" {
#define gb_is_between(x, lower, upper) (((x) >= (lower)) && ((x) <= (upper)))
#endif
#ifndef gb_abs
#define gb_abs(x) ((x) < 0 ? -(x) : (x))
#endif
/* NOTE(bill): Very useful bit setting */
#ifndef GB_MASK_SET
#define GB_MASK_SET(var, set, mask) do { \
@ -1370,6 +1375,7 @@ GB_DEF u8 * gb_ucs2_to_utf8_buf(u16 const *str); // NOTE(bill): Uses locally per
// NOTE(bill): Returns size of codepoint in bytes
GB_DEF isize gb_utf8_decode (u8 const *str, isize str_len, Rune *codepoint);
GB_DEF isize gb_utf8_codepoint_size(u8 const *str, isize str_len);
GB_DEF isize gb_utf8_encode_rune (u8 buf[4], Rune r);
////////////////////////////////////////////////////////////////
//
@ -1923,7 +1929,7 @@ typedef union gbFileDescriptor {
typedef struct gbFileOperations gbFileOperations;
#define GB_FILE_OPEN_PROC(name) gbFileError name(gbFileDescriptor *fd, gbFileOperations const **ops, gbFileMode mode, char const *filename)
#define GB_FILE_OPEN_PROC(name) gbFileError name(gbFileDescriptor *fd, gbFileOperations *ops, gbFileMode mode, char const *filename)
#define GB_FILE_READ_AT_PROC(name) b32 name(gbFileDescriptor fd, void *buffer, isize size, i64 offset, isize *bytes_read)
#define GB_FILE_WRITE_AT_PROC(name) b32 name(gbFileDescriptor fd, void const *buffer, isize size, i64 offset, isize *bytes_written)
#define GB_FILE_SEEK_PROC(name) b32 name(gbFileDescriptor fd, i64 offset, gbSeekWhenceType whence, i64 *new_offset)
@ -1953,11 +1959,11 @@ extern gbFileOperations const gbDefaultFileOperations;
typedef u64 gbFileTime;
typedef struct gbFile {
gbFileOperations const *ops;
gbFileDescriptor fd;
char const * filename;
gbFileTime last_write_time;
// gbDirInfo * dir_info; // TODO(bill): Get directory info
gbFileOperations ops;
gbFileDescriptor fd;
char const * filename;
gbFileTime last_write_time;
// gbDirInfo * dir_info; // TODO(bill): Get directory info
} gbFile;
// TODO(bill): gbAsyncFile
@ -1975,7 +1981,7 @@ GB_DEF gbFile *const gb_file_get_standard(gbFileStandardType std);
GB_DEF gbFileError gb_file_create (gbFile *file, char const *filename);
GB_DEF gbFileError gb_file_open (gbFile *file, char const *filename);
GB_DEF gbFileError gb_file_open_mode (gbFile *file, gbFileMode mode, char const *filename);
GB_DEF gbFileError gb_file_new (gbFile *file, gbFileDescriptor fd, gbFileOperations const *ops, char const *filename);
GB_DEF gbFileError gb_file_new (gbFile *file, gbFileDescriptor fd, gbFileOperations ops, char const *filename);
GB_DEF b32 gb_file_read_at_check (gbFile *file, void *buffer, isize size, i64 offset, isize *bytes_read);
GB_DEF b32 gb_file_write_at_check(gbFile *file, void const *buffer, isize size, i64 offset, isize *bytes_written);
GB_DEF b32 gb_file_read_at (gbFile *file, void *buffer, isize size, i64 offset);
@ -2963,8 +2969,6 @@ extern "C" {
DWORD dwFlags;
} MONITORINFO;
#define INFINITE 0xffffffffl
#define INVALID_HANDLE_VALUE ((void *)(intptr)(-1))
@ -2984,7 +2988,6 @@ extern "C" {
GB_DLL_IMPORT void WINAPI RaiseException (DWORD, DWORD, DWORD, ULONG_PTR const *);
GB_DLL_IMPORT BOOL WINAPI GetLogicalProcessorInformation(SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buffer, DWORD *return_length);
GB_DLL_IMPORT DWORD_PTR WINAPI SetThreadAffinityMask(HANDLE thread, DWORD_PTR check_mask);
GB_DLL_IMPORT HANDLE WINAPI GetCurrentThread(void);
@ -3618,9 +3621,9 @@ gb_inline void gb_zero_size(void *ptr, isize size) { gb_memset(ptr, 0, size); }
gb_inline void *gb_memcopy(void *dest, void const *source, isize n) {
#if defined(_MSC_VER)
// TODO(bill): Is this good enough?
__movsb(cast(u8 *gb_restrict)dest, cast(u8 *gb_restrict)source, n);
__movsb(cast(u8 *)dest, cast(u8 *)source, n);
#elif defined(GB_CPU_X86)
__asm__ __volatile__("rep movsb" : "+D"(cast(u8 *gb_restrict)dest), "+S"(cast(u8 *gb_restrict)source), "+c"(n) : : "memory");
__asm__ __volatile__("rep movsb" : "+D"(cast(u8 *)dest), "+S"(cast(u8 *)source), "+c"(n) : : "memory");
#else
u8 *d = cast(u8 *)dest;
u8 const *s = cast(u8 const *)source;
@ -3946,7 +3949,7 @@ void const *gb_memrchr(void const *data, u8 c, isize n) {
gb_inline void *gb_alloc_align (gbAllocator a, isize size, isize alignment) { return a.proc(a.data, gbAllocation_Alloc, size, alignment, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void *gb_alloc (gbAllocator a, isize size) { return gb_alloc_align(a, size, GB_DEFAULT_MEMORY_ALIGNMENT); }
gb_inline void gb_free (gbAllocator a, void *ptr) { a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void gb_free (gbAllocator a, void *ptr) { if (ptr != NULL) a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void gb_free_all (gbAllocator a) { a.proc(a.data, gbAllocation_FreeAll, 0, 0, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void *gb_resize (gbAllocator a, void *ptr, isize old_size, isize new_size) { return gb_resize_align(a, ptr, old_size, new_size, GB_DEFAULT_MEMORY_ALIGNMENT); }
gb_inline void *gb_resize_align(gbAllocator a, void *ptr, isize old_size, isize new_size, isize alignment) { return a.proc(a.data, gbAllocation_Resize, new_size, alignment, ptr, old_size, GB_DEFAULT_ALLOCATOR_FLAGS); }
@ -4696,7 +4699,7 @@ void gb_thread_set_name(gbThread *t, char const *name) {
tn.flags = 0;
__try {
RaiseException(0x406d1388, 0, gb_size_of(tn)/4, cast(usize *)&tn);
RaiseException(0x406d1388, 0, gb_size_of(tn)/4, cast(ULONG_PTR *)&tn);
} __except(1 /*EXCEPTION_EXECUTE_HANDLER*/) {
}
@ -5755,7 +5758,7 @@ void gb_sort(void *base_, isize count, isize size, gbCompareProc cmp) {
Type radix_piece = (radix_value >> byte_index) & 0xff; \
dest[offsets[radix_piece]++] = source[i]; \
} \
gb_swap(Type *gb_restrict, source, dest); \
gb_swap(Type *, source, dest); \
} \
}
@ -5871,7 +5874,7 @@ gb_inline i32 gb_hex_digit_to_int(char c) {
return c - 'a' + 10;
else if (gb_is_between(c, 'A', 'F'))
return c - 'A' + 10;
return 0;
return -1;
}
@ -5919,21 +5922,36 @@ gb_inline isize gb_strnlen(char const *str, isize max_len) {
}
gb_inline isize gb_utf8_strlen(u8 const *str) {
isize result = 0;
for (; *str; str++) {
if ((*str & 0xc0) != 0x80)
result++;
isize count = 0;
for (; *str; count++) {
u8 c = *str;
isize inc = 0;
if (c < 0x80) inc = 1;
else if ((c & 0xe0) == 0xc0) inc = 2;
else if ((c & 0xf0) == 0xe0) inc = 3;
else if ((c & 0xf8) == 0xf0) inc = 4;
else return -1;
str += inc;
}
return result;
return count;
}
gb_inline isize gb_utf8_strnlen(u8 const *str, isize max_len) {
isize result = 0;
for (; *str && result < max_len; str++) {
if ((*str & 0xc0) != 0x80)
result++;
isize count = 0;
for (; *str && max_len > 0; count++) {
u8 c = *str;
isize inc = 0;
if (c < 0x80) inc = 1;
else if ((c & 0xe0) == 0xc0) inc = 2;
else if ((c & 0xf0) == 0xe0) inc = 3;
else if ((c & 0xf8) == 0xf0) inc = 4;
else return -1;
str += inc;
max_len -= inc;
}
return result;
return count;
}
@ -6352,16 +6370,17 @@ gb_inline void gb_string_clear(gbString str) { gb__set_string_length(str, 0); st
gb_inline gbString gb_string_append(gbString str, gbString const other) { return gb_string_append_length(str, other, gb_string_length(other)); }
gbString gb_string_append_length(gbString str, void const *other, isize other_len) {
isize curr_len = gb_string_length(str);
if (other_len > 0) {
isize curr_len = gb_string_length(str);
str = gb_string_make_space_for(str, other_len);
if (str == NULL)
return NULL;
gb_memcopy(str + curr_len, other, other_len);
str[curr_len + other_len] = '\0';
gb__set_string_length(str, curr_len + other_len);
str = gb_string_make_space_for(str, other_len);
if (str == NULL)
return NULL;
gb_memcopy(str + curr_len, other, other_len);
str[curr_len + other_len] = '\0';
gb__set_string_length(str, curr_len + other_len);
}
return str;
}
@ -6623,6 +6642,8 @@ gb_global gbUtf8AcceptRange const gb__utf8_accept_ranges[] = {
isize gb_utf8_decode(u8 const *str, isize str_len, Rune *codepoint_out) {
isize width = 0;
Rune codepoint = GB_RUNE_INVALID;
@ -6637,6 +6658,11 @@ isize gb_utf8_decode(u8 const *str, isize str_len, Rune *codepoint_out) {
width = 1;
goto end;
}
if (s0 < 0x80) {
codepoint = s0;
width = 1;
goto end;
}
sz = x&7;
accept = gb__utf8_accept_ranges[x>>4];
@ -6690,6 +6716,43 @@ isize gb_utf8_codepoint_size(u8 const *str, isize str_len) {
return i+1;
}
isize gb_utf8_encode_rune(u8 buf[4], Rune r) {
u32 i = cast(u32)r;
u8 mask = 0x3f;
if (i <= (1<<7)-1) {
buf[0] = cast(u8)r;
return 1;
}
if (i <= (1<<11)-1) {
buf[0] = 0xc0 | cast(u8)(r>>6);
buf[1] = 0x80 | (cast(u8)(r)&mask);
return 2;
}
// Invalid or Surrogate range
if (i > GB_RUNE_MAX ||
gb_is_between(i, 0xd800, 0xdfff)) {
r = GB_RUNE_INVALID;
buf[0] = 0xe0 | cast(u8)(r>>12);
buf[1] = 0x80 | (cast(u8)(r>>6)&mask);
buf[2] = 0x80 | (cast(u8)(r)&mask);
return 3;
}
if (i <= (1<<16)-1) {
buf[0] = 0xe0 | cast(u8)(r>>12);
buf[1] = 0x80 | (cast(u8)(r>>6)&mask);
buf[2] = 0x80 | (cast(u8)(r)&mask);
return 3;
}
buf[0] = 0xf0 | cast(u8)(r>>18);
buf[1] = 0x80 | (cast(u8)(r>>12)&mask);
buf[2] = 0x80 | (cast(u8)(r>>6)&mask);
buf[3] = 0x80 | (cast(u8)(r)&mask);
return 4;
}
@ -7237,7 +7300,7 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) {
}
fd->p = handle;
*ops = &gbDefaultFileOperations;
*ops = gbDefaultFileOperations;
return gbFileError_None;
}
@ -7319,7 +7382,7 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) {
return gbFileError_Invalid;
}
*ops = &gbDefaultFileOperations;
*ops = gbDefaultFileOperations;
return gbFileError_None;
}
@ -7327,7 +7390,7 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) {
gbFileError gb_file_new(gbFile *f, gbFileDescriptor fd, gbFileOperations const *ops, char const *filename) {
gbFileError gb_file_new(gbFile *f, gbFileDescriptor fd, gbFileOperations ops, char const *filename) {
gbFileError err = gbFileError_None;
f->ops = ops;
@ -7366,20 +7429,20 @@ gbFileError gb_file_close(gbFile *f) {
return gbFileError_Invalid;
#endif
if (!f->ops) f->ops = &gbDefaultFileOperations;
f->ops->close(f->fd);
if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
f->ops.close(f->fd);
return gbFileError_None;
}
gb_inline b32 gb_file_read_at_check(gbFile *f, void *buffer, isize size, i64 offset, isize *bytes_read) {
if (!f->ops) f->ops = &gbDefaultFileOperations;
return f->ops->read_at(f->fd, buffer, size, offset, bytes_read);
if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
return f->ops.read_at(f->fd, buffer, size, offset, bytes_read);
}
gb_inline b32 gb_file_write_at_check(gbFile *f, void const *buffer, isize size, i64 offset, isize *bytes_written) {
if (!f->ops) f->ops = &gbDefaultFileOperations;
return f->ops->write_at(f->fd, buffer, size, offset, bytes_written);
if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
return f->ops.write_at(f->fd, buffer, size, offset, bytes_written);
}
@ -7393,30 +7456,30 @@ gb_inline b32 gb_file_write_at(gbFile *f, void const *buffer, isize size, i64 of
gb_inline i64 gb_file_seek(gbFile *f, i64 offset) {
i64 new_offset = 0;
if (!f->ops) f->ops = &gbDefaultFileOperations;
f->ops->seek(f->fd, offset, gbSeekWhence_Begin, &new_offset);
if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
f->ops.seek(f->fd, offset, gbSeekWhence_Begin, &new_offset);
return new_offset;
}
gb_inline i64 gb_file_seek_to_end(gbFile *f) {
i64 new_offset = 0;
if (!f->ops) f->ops = &gbDefaultFileOperations;
f->ops->seek(f->fd, 0, gbSeekWhence_End, &new_offset);
if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
f->ops.seek(f->fd, 0, gbSeekWhence_End, &new_offset);
return new_offset;
}
// NOTE(bill): Skips a certain amount of bytes
gb_inline i64 gb_file_skip(gbFile *f, i64 bytes) {
i64 new_offset = 0;
if (!f->ops) f->ops = &gbDefaultFileOperations;
f->ops->seek(f->fd, bytes, gbSeekWhence_Current, &new_offset);
if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
f->ops.seek(f->fd, bytes, gbSeekWhence_Current, &new_offset);
return new_offset;
}
gb_inline i64 gb_file_tell(gbFile *f) {
i64 new_offset = 0;
if (!f->ops) f->ops = &gbDefaultFileOperations;
f->ops->seek(f->fd, 0, gbSeekWhence_Current, &new_offset);
if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
f->ops.seek(f->fd, 0, gbSeekWhence_Current, &new_offset);
return new_offset;
}
gb_inline b32 gb_file_read (gbFile *f, void *buffer, isize size) { return gb_file_read_at(f, buffer, size, gb_file_tell(f)); }
@ -7454,7 +7517,7 @@ gb_global gbFile gb__std_files[gbFileStandard_Count] = {{0}};
gb_inline gbFile *const gb_file_get_standard(gbFileStandardType std) {
if (!gb__std_file_set) {
#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.p = v; gb__std_files[type].ops = &gbDefaultFileOperations
#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.p = v; gb__std_files[type].ops = gbDefaultFileOperations
GB__SET_STD_FILE(gbFileStandard_Input, GetStdHandle(STD_INPUT_HANDLE));
GB__SET_STD_FILE(gbFileStandard_Output, GetStdHandle(STD_OUTPUT_HANDLE));
GB__SET_STD_FILE(gbFileStandard_Error, GetStdHandle(STD_ERROR_HANDLE));
@ -7493,7 +7556,7 @@ b32 gb_file_exists(char const *name) {
gb_inline gbFile *const gb_file_get_standard(gbFileStandardType std) {
if (!gb__std_file_set) {
#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.i = v; gb__std_files[type].ops = &gbDefaultFileOperations
#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.i = v; gb__std_files[type].ops = gbDefaultFileOperations
GB__SET_STD_FILE(gbFileStandard_Input, 0);
GB__SET_STD_FILE(gbFileStandard_Output, 1);
GB__SET_STD_FILE(gbFileStandard_Error, 2);

154
gb_math.h
View File

@ -1,8 +1,9 @@
/* gb_math.h - v0.06h - public domain C math library - no warranty implied; use at your own risk
/* gb_math.h - v0.07 - public domain C math library - no warranty implied; use at your own risk
A C math library geared towards game development
use '#define GB_MATH_IMPLEMENTATION' before including to create the implementation in _ONE_ file
Version History:
0.07 - Better Mat4 procedures
0.06h - Ignore silly warnings
0.06g - Remove memzero
0.06f - Remove warning on MSVC
@ -338,9 +339,11 @@ GB_MATH_DEF float gb_vec2_aspect_ratio(gbVec2 v);
GB_MATH_DEF void gb_mat2_identity (gbMat2 *m);
GB_MATH_DEF void gb_float22_identity(float m[2][2]);
GB_MATH_DEF void gb_mat2_transpose(gbMat2 *m);
GB_MATH_DEF void gb_mat2_mul (gbMat2 *out, gbMat2 *m1, gbMat2 *m2);
GB_MATH_DEF void gb_mat2_mul_vec2 (gbVec2 *out, gbMat2 *m, gbVec2 in);
GB_MATH_DEF void gb_mat2_transpose (gbMat2 *m);
GB_MATH_DEF void gb_mat2_mul (gbMat2 *out, gbMat2 *m1, gbMat2 *m2);
GB_MATH_DEF void gb_mat2_mul_vec2 (gbVec2 *out, gbMat2 *m, gbVec2 in);
GB_MATH_DEF void gb_mat2_inverse (gbMat2 *out, gbMat2 *in);
GB_MATH_DEF float gb_mat2_determinate(gbMat2 *m);
GB_MATH_DEF gbMat2 *gb_mat2_v(gbVec2 m[2]);
GB_MATH_DEF gbMat2 *gb_mat2_f(float m[2][2]);
@ -356,9 +359,12 @@ GB_MATH_DEF void gb_float22_mul_vec2 (gbVec2 *out, float m[2][2], gbVec2 in);
GB_MATH_DEF void gb_mat3_identity (gbMat3 *m);
GB_MATH_DEF void gb_float33_identity(float m[3][3]);
GB_MATH_DEF void gb_mat3_transpose(gbMat3 *m);
GB_MATH_DEF void gb_mat3_mul (gbMat3 *out, gbMat3 *m1, gbMat3 *m2);
GB_MATH_DEF void gb_mat3_mul_vec3 (gbVec3 *out, gbMat3 *m, gbVec3 in);
GB_MATH_DEF void gb_mat3_transpose (gbMat3 *m);
GB_MATH_DEF void gb_mat3_mul (gbMat3 *out, gbMat3 *m1, gbMat3 *m2);
GB_MATH_DEF void gb_mat3_mul_vec3 (gbVec3 *out, gbMat3 *m, gbVec3 in);
GB_MATH_DEF void gb_mat3_inverse (gbMat3 *out, gbMat3 *in);
GB_MATH_DEF float gb_mat3_determinate(gbMat3 *m);
GB_MATH_DEF gbMat3 *gb_mat3_v(gbVec3 m[3]);
GB_MATH_DEF gbMat3 *gb_mat3_f(float m[3][3]);
@ -374,9 +380,10 @@ GB_MATH_DEF void gb_float33_mul_vec3 (gbVec3 *out, float m[3][3], gbVec3 in);
GB_MATH_DEF void gb_mat4_identity (gbMat4 *m);
GB_MATH_DEF void gb_float44_identity(float m[4][4]);
GB_MATH_DEF void gb_mat4_transpose(gbMat4 *m);
GB_MATH_DEF void gb_mat4_mul (gbMat4 *out, gbMat4 *m1, gbMat4 *m2);
GB_MATH_DEF void gb_mat4_mul_vec4 (gbVec4 *out, gbMat4 *m, gbVec4 in);
GB_MATH_DEF void gb_mat4_transpose (gbMat4 *m);
GB_MATH_DEF void gb_mat4_mul (gbMat4 *out, gbMat4 *m1, gbMat4 *m2);
GB_MATH_DEF void gb_mat4_mul_vec4 (gbVec4 *out, gbMat4 *m, gbVec4 in);
GB_MATH_DEF void gb_mat4_inverse (gbMat4 *out, gbMat4 *in);
GB_MATH_DEF gbMat4 *gb_mat4_v(gbVec4 m[4]);
GB_MATH_DEF gbMat4 *gb_mat4_f(float m[4][4]);
@ -1342,6 +1349,23 @@ void gb_float22_mul_vec2(gbVec2 *out, float m[2][2], gbVec2 v) {
out->y = m[1][0]*v.x + m[1][1]*v.y;
}
float gb_mat2_determinate(gbMat2 *m) {
gbFloat2 *e = gb_float22_m(m);
return e[0][0]*e[1][1] - e[1][0]*e[0][1];
}
void gb_mat2_inverse(gbMat2 *out, gbMat2 *in) {
gbFloat2 *o = gb_float22_m(out);
gbFloat2 *i = gb_float22_m(in);
float ood = 1.0f / gb_mat2_determinate(in);
o[0][0] = +i[1][1] * ood;
o[0][1] = -i[0][1] * ood;
o[1][0] = -i[1][0] * ood;
o[1][1] = +i[0][0] * ood;
}
@ -1399,6 +1423,35 @@ void gb_float33_mul_vec3(gbVec3 *out, float m[3][3], gbVec3 v) {
float gb_mat3_determinate(gbMat3 *m) {
gbFloat3 *e = gb_float33_m(m);
float d = +e[0][0] * (e[1][1] * e[2][2] - e[1][2] * e[2][1])
-e[0][1] * (e[1][0] * e[2][2] - e[1][2] * e[2][0])
+e[0][2] * (e[1][0] * e[2][1] - e[1][1] * e[2][0]);
return d;
}
void gb_mat3_inverse(gbMat3 *out, gbMat3 *in) {
gbFloat3 *o = gb_float33_m(out);
gbFloat3 *i = gb_float33_m(in);
float ood = 1.0f / gb_mat3_determinate(in);
o[0][0] = +(i[1][1] * i[2][2] - i[2][1] * i[1][2]) * ood;
o[0][1] = -(i[1][0] * i[2][2] - i[2][0] * i[1][2]) * ood;
o[0][2] = +(i[1][0] * i[2][1] - i[2][0] * i[1][1]) * ood;
o[1][0] = -(i[0][1] * i[2][2] - i[2][1] * i[0][2]) * ood;
o[1][1] = +(i[0][0] * i[2][2] - i[2][0] * i[0][2]) * ood;
o[1][2] = -(i[0][0] * i[2][1] - i[2][0] * i[0][1]) * ood;
o[2][0] = +(i[0][1] * i[1][2] - i[1][1] * i[0][2]) * ood;
o[2][1] = -(i[0][0] * i[1][2] - i[1][0] * i[0][2]) * ood;
o[2][2] = +(i[0][0] * i[1][1] - i[1][0] * i[0][1]) * ood;
}
@ -1454,12 +1507,85 @@ void gb_float44_mul(float (*out)[4], float (*mat1)[4], float (*mat2)[4]) {
}
void gb_float44_mul_vec4(gbVec4 *out, float m[4][4], gbVec4 v) {
out->x = m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3]*v.w;
out->y = m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3]*v.w;
out->z = m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3]*v.w;
out->w = m[3][0]*v.x + m[3][1]*v.y + m[3][2]*v.z + m[3][3]*v.w;
out->x = m[0][0]*v.x + m[1][0]*v.y + m[2][0]*v.z + m[3][0]*v.w;
out->y = m[0][1]*v.x + m[1][1]*v.y + m[2][1]*v.z + m[3][1]*v.w;
out->z = m[0][2]*v.x + m[1][2]*v.y + m[2][2]*v.z + m[3][2]*v.w;
out->w = m[0][3]*v.x + m[1][3]*v.y + m[2][3]*v.z + m[3][3]*v.w;
}
void gb_mat4_inverse(gbMat4 *out, gbMat4 *in) {
gbFloat4 *o = gb_float44_m(out);
gbFloat4 *m = gb_float44_m(in);
float ood;
float sf00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
float sf01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
float sf02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
float sf03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
float sf04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
float sf05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
float sf06 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
float sf07 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
float sf08 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
float sf09 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
float sf10 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
float sf11 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
float sf12 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
float sf13 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
float sf14 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
float sf15 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
float sf16 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
float sf17 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
float sf18 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
o[0][0] = +(m[1][1] * sf00 - m[1][2] * sf01 + m[1][3] * sf02);
o[0][1] = -(m[1][0] * sf00 - m[1][2] * sf03 + m[1][3] * sf04);
o[0][2] = +(m[1][0] * sf01 - m[1][1] * sf03 + m[1][3] * sf05);
o[0][3] = -(m[1][0] * sf02 - m[1][1] * sf04 + m[1][2] * sf05);
o[1][0] = -(m[0][1] * sf00 - m[0][2] * sf01 + m[0][3] * sf02);
o[1][1] = +(m[0][0] * sf00 - m[0][2] * sf03 + m[0][3] * sf04);
o[1][2] = -(m[0][0] * sf01 - m[0][1] * sf03 + m[0][3] * sf05);
o[1][3] = +(m[0][0] * sf02 - m[0][1] * sf04 + m[0][2] * sf05);
o[2][0] = +(m[0][1] * sf06 - m[0][2] * sf07 + m[0][3] * sf08);
o[2][1] = -(m[0][0] * sf06 - m[0][2] * sf09 + m[0][3] * sf10);
o[2][2] = +(m[0][0] * sf11 - m[0][1] * sf09 + m[0][3] * sf12);
o[2][3] = -(m[0][0] * sf08 - m[0][1] * sf10 + m[0][2] * sf12);
o[3][0] = -(m[0][1] * sf13 - m[0][2] * sf14 + m[0][3] * sf15);
o[3][1] = +(m[0][0] * sf13 - m[0][2] * sf16 + m[0][3] * sf17);
o[3][2] = -(m[0][0] * sf14 - m[0][1] * sf16 + m[0][3] * sf18);
o[3][3] = +(m[0][0] * sf15 - m[0][1] * sf17 + m[0][2] * sf18);
ood = 1.0f / (m[0][0] * o[0][0]
m[0][1] * o[0][1]
m[0][2] * o[0][2]
m[0][3] * o[0][3]);
o[0][0] *= ood;
o[0][1] *= ood;
o[0][2] *= ood;
o[0][3] *= ood;
o[1][0] *= ood;
o[1][1] *= ood;
o[1][2] *= ood;
o[1][3] *= ood;
o[2][0] *= ood;
o[2][1] *= ood;
o[2][2] *= ood;
o[2][3] *= ood;
o[3][0] *= ood;
o[3][1] *= ood;
o[3][2] *= ood;
o[3][3] *= ood;
}
void gb_mat4_translate(gbMat4 *out, gbVec3 v) {