From: John Tsiombikas Date: Sun, 6 Dec 2020 18:01:50 +0000 (+0200) Subject: added cgmath X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=0b24071f728b7c8550daa1b7aa7c4012cb70ef4c;p=demo_prior added cgmath --- diff --git a/Makefile b/Makefile index d1389f2..7669326 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ bin = demo warn = -pedantic -Wall -g def = -DMINIGLUT_USE_LIBC -incpath = -Ilibs/glew -Ilibs/treestore/src +incpath = -Ilibs/glew -Ilibs/treestore/src -Ilibs/cgmath libpath = -Llibs/glew -Llibs/treestore CFLAGS = $(warn) $(def) $(incpath) -MMD diff --git a/libs/cgmath/LICENSE b/libs/cgmath/LICENSE new file mode 100644 index 0000000..536e666 --- /dev/null +++ b/libs/cgmath/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2016 John Tsiombikas + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/libs/cgmath/README.md b/libs/cgmath/README.md new file mode 100644 index 0000000..119aa4a --- /dev/null +++ b/libs/cgmath/README.md @@ -0,0 +1,29 @@ +gph-cmath: C math library for graphics +====================================== + +About +----- +gph-cmath is a C math library for graphics programs. It provides a plethora of +operations on vectors, matrices and quaternions, among other things. + +It's conceptually a companion to my C++ math library +[gph-math](http://github.com/jtsiomb/gph-math), but where gph-math is designed +with intuitiveness and ease of use as the main priority, this C version is +designed to be as low-overhead as possible, making it more suitable for more +resource-constrained target systems. +For instance most functions modify their first argument, instead of doing an +extra copy to provide a more natural 3 operand interface. Leaving the copy to +the user for the cases where it's necessary. + +License +------- +Copyright (C) 2016 John Tsiombikas + +This program is free software. Feel free to use, modify, and/or redistribute it +under the terms of the MIT/X11 license. See LICENSE for details. + +How to use +---------- +There's nothing to build. All functions are static inline, defined in the header +files. Either type `make install` to install them system-wide, or just copy all +files under `src/` to your project source tree. diff --git a/libs/cgmath/cgmath.h b/libs/cgmath/cgmath.h new file mode 100644 index 0000000..db0db5a --- /dev/null +++ b/libs/cgmath/cgmath.h @@ -0,0 +1,257 @@ +/* gph-cmath - C graphics math library + * Copyright (C) 2018 John Tsiombikas + * + * This program is free software. Feel free to use, modify, and/or redistribute + * it under the terms of the MIT/X11 license. See LICENSE for details. + * If you intend to redistribute parts of the code without the LICENSE file + * replace this paragraph with the full contents of the LICENSE file. + * + * Function prefixes signify the data type of their operand(s): + * - cgm_v... functions are operations on cgm_vec3 vectors + * - cgm_w... functions are operations on cgm_vec4 vectors + * - cgm_q... functions are operations on cgm_quat quaternions (w + xi + yj + zk) + * - cgm_m... functions are operations on 4x4 matrices (stored as linear 16 float arrays) + * - cgm_r... functions are operations on cgm_ray rays + * + * NOTE: *ALL* matrix arguments are pointers to 16 floats. Even the functions + * which operate on 3x3 matrices, actually use the upper 3x3 of a 4x4 matrix, + * and still expect an array of 16 floats. + * + * NOTE: matrices are treated by all operations as column-major, to match OpenGL + * conventions, so everything is pretty much transposed. +*/ +#ifndef CGMATH_H_ +#define CGMATH_H_ + +#include +#include + +typedef struct { + float x, y; +} cgm_vec2; + +typedef struct { + float x, y, z; +} cgm_vec3; + +typedef struct { + float x, y, z, w; +} cgm_vec4, cgm_quat; + +typedef struct { + cgm_vec3 origin, dir; +} cgm_ray; + +typedef enum cgm_euler_mode { + CGM_EULER_XYZ, + CGM_EULER_XZY, + CGM_EULER_YXZ, + CGM_EULER_YZX, + CGM_EULER_ZXY, + CGM_EULER_ZYX, + CGM_EULER_ZXZ, + CGM_EULER_ZYZ, + CGM_EULER_YXY, + CGM_EULER_YZY, + CGM_EULER_XYX, + CGM_EULER_XZX +} cgm_euler_mode; + +#ifdef __cplusplus +extern "C" { +#endif + +/* --- operations on cgm_vec3 --- */ +static inline void cgm_vcons(cgm_vec3 *v, float x, float y, float z); + +static inline void cgm_vadd(cgm_vec3 *a, const cgm_vec3 *b); +static inline void cgm_vsub(cgm_vec3 *a, const cgm_vec3 *b); +static inline void cgm_vmul(cgm_vec3 *a, const cgm_vec3 *b); +static inline void cgm_vscale(cgm_vec3 *v, float s); +static inline void cgm_vmul_m4v3(cgm_vec3 *v, const float *m); /* m4x4 * v */ +static inline void cgm_vmul_v3m4(cgm_vec3 *v, const float *m); /* v * m4x4 */ +static inline void cgm_vmul_m3v3(cgm_vec3 *v, const float *m); /* m3x3 * v (m still 16 floats) */ +static inline void cgm_vmul_v3m3(cgm_vec3 *v, const float *m); /* v * m3x3 (m still 16 floats) */ + +static inline float cgm_vdot(const cgm_vec3 *a, const cgm_vec3 *b); +static inline void cgm_vcross(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b); +static inline float cgm_vlength(const cgm_vec3 *v); +static inline float cgm_vlength_sq(const cgm_vec3 *v); +static inline float cgm_vdist(const cgm_vec3 *a, const cgm_vec3 *b); +static inline float cgm_vdist_sq(const cgm_vec3 *a, const cgm_vec3 *b); +static inline void cgm_vnormalize(cgm_vec3 *v); + +static inline void cgm_vreflect(cgm_vec3 *v, const cgm_vec3 *n); +static inline void cgm_vrefract(cgm_vec3 *v, const cgm_vec3 *n, float ior); + +static inline void cgm_vrotate_quat(cgm_vec3 *v, const cgm_quat *q); +static inline void cgm_vrotate_axis(cgm_vec3 *v, int axis, float angle); +static inline void cgm_vrotate(cgm_vec3 *v, float angle, float x, float y, float z); +static inline void cgm_vrotate_euler(cgm_vec3 *v, float a, float b, float c, enum cgm_euler_mode mode); + +static inline void cgm_vlerp(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b, float t); + +#define cgm_velem(vptr, idx) ((&(vptr)->x)[idx]) + +/* --- operations on cgm_vec4 --- */ +static inline void cgm_wcons(cgm_vec4 *v, float x, float y, float z, float w); + +static inline void cgm_wadd(cgm_vec4 *a, const cgm_vec4 *b); +static inline void cgm_wsub(cgm_vec4 *a, const cgm_vec4 *b); +static inline void cgm_wmul(cgm_vec4 *a, const cgm_vec4 *b); +static inline void cgm_wscale(cgm_vec4 *v, float s); + +static inline void cgm_wmul_m4v4(cgm_vec4 *v, const float *m); +static inline void cgm_wmul_v4m4(cgm_vec4 *v, const float *m); +static inline void cgm_wmul_m34v4(cgm_vec4 *v, const float *m); /* doesn't affect w */ +static inline void cgm_wmul_v4m43(cgm_vec4 *v, const float *m); /* doesn't affect w */ +static inline void cgm_wmul_m3v4(cgm_vec4 *v, const float *m); /* (m still 16 floats) */ +static inline void cgm_wmul_v4m3(cgm_vec4 *v, const float *m); /* (m still 16 floats) */ + +static inline float cgm_wdot(const cgm_vec4 *a, const cgm_vec4 *b); + +static inline float cgm_wlength(const cgm_vec4 *v); +static inline float cgm_wlength_sq(const cgm_vec4 *v); +static inline float cgm_wdist(const cgm_vec4 *a, const cgm_vec4 *b); +static inline float cgm_wdist_sq(const cgm_vec4 *a, const cgm_vec4 *b); +static inline void cgm_wnormalize(cgm_vec4 *v); + +static inline void cgm_wlerp(cgm_vec4 *res, const cgm_vec4 *a, const cgm_vec4 *b, float t); + +#define cgm_welem(vptr, idx) ((&(vptr)->x)[idx]) + +/* --- operations on quaternions --- */ +static inline void cgm_qcons(cgm_quat *q, float x, float y, float z, float w); + +static inline void cgm_qneg(cgm_quat *q); +static inline void cgm_qadd(cgm_quat *a, const cgm_quat *b); +static inline void cgm_qsub(cgm_quat *a, const cgm_quat *b); +static inline void cgm_qmul(cgm_quat *a, const cgm_quat *b); + +static inline float cgm_qlength(const cgm_quat *q); +static inline float cgm_qlength_sq(const cgm_quat *q); +static inline void cgm_qnormalize(cgm_quat *q); +static inline void cgm_qconjugate(cgm_quat *q); +static inline void cgm_qinvert(cgm_quat *q); + +static inline void cgm_qrotation(cgm_quat *q, float angle, float x, float y, float z); +static inline void cgm_qrotate(cgm_quat *q, float angle, float x, float y, float z); + +static inline void cgm_qslerp(cgm_quat *res, const cgm_quat *a, const cgm_quat *b, float t); +static inline void cgm_qlerp(cgm_quat *res, const cgm_quat *a, const cgm_quat *b, float t); + +#define cgm_qelem(qptr, idx) ((&(qptr)->x)[idx]) + +/* --- operations on matrices --- */ +static inline void cgm_mcopy(float *dest, const float *src); +static inline void cgm_mzero(float *m); +static inline void cgm_midentity(float *m); + +static inline void cgm_mmul(float *a, const float *b); +static inline void cgm_mpremul(float *a, const float *b); + +static inline void cgm_msubmatrix(float *m, int row, int col); +static inline void cgm_mupper3(float *m); +static inline float cgm_msubdet(const float *m, int row, int col); +static inline float cgm_mcofactor(const float *m, int row, int col); +static inline float cgm_mdet(const float *m); +static inline void cgm_mtranspose(float *m); +static inline void cgm_mcofmatrix(float *m); +static inline int cgm_minverse(float *m); /* returns 0 on success, -1 for singular */ + +static inline void cgm_mtranslation(float *m, float x, float y, float z); +static inline void cgm_mscaling(float *m, float sx, float sy, float sz); +static inline void cgm_mrotation_x(float *m, float angle); +static inline void cgm_mrotation_y(float *m, float angle); +static inline void cgm_mrotation_z(float *m, float angle); +static inline void cgm_mrotation_axis(float *m, int idx, float angle); +static inline void cgm_mrotation(float *m, float angle, float x, float y, float z); +static inline void cgm_mrotation_euler(float *m, float a, float b, float c, int mode); +static inline void cgm_mrotation_quat(float *m, const cgm_quat *q); + +static inline void cgm_mtranslate(float *m, float x, float y, float z); +static inline void cgm_mscale(float *m, float sx, float sy, float sz); +static inline void cgm_mrotate_x(float *m, float angle); +static inline void cgm_mrotate_y(float *m, float angle); +static inline void cgm_mrotate_z(float *m, float angle); +static inline void cgm_mrotate_axis(float *m, int idx, float angle); +static inline void cgm_mrotate(float *m, float angle, float x, float y, float z); +static inline void cgm_mrotate_euler(float *m, float a, float b, float c, int mode); +static inline void cgm_mrotate_quat(float *m, const cgm_quat *q); + +static inline void cgm_mpretranslate(float *m, float x, float y, float z); +static inline void cgm_mprescale(float *m, float sx, float sy, float sz); +static inline void cgm_mprerotate_x(float *m, float angle); +static inline void cgm_mprerotate_y(float *m, float angle); +static inline void cgm_mprerotate_z(float *m, float angle); +static inline void cgm_mprerotate_axis(float *m, int idx, float angle); +static inline void cgm_mprerotate(float *m, float angle, float x, float y, float z); +static inline void cgm_mprerotate_euler(float *m, float a, float b, float c, int mode); +static inline void cgm_mprerotate_quat(float *m, const cgm_quat *q); + +static inline void cgm_mget_translation(const float *m, cgm_vec3 *res); +static inline void cgm_mget_rotation(const float *m, cgm_quat *res); +static inline void cgm_mget_scaling(const float *m, cgm_vec3 *res); +static inline void cgm_mget_frustum_plane(const float *m, int p, cgm_vec4 *res); + +static inline void cgm_mlookat(float *m, const cgm_vec3 *pos, const cgm_vec3 *targ, + const cgm_vec3 *up); +static inline void cgm_minv_lookat(float *m, const cgm_vec3 *pos, const cgm_vec3 *targ, + const cgm_vec3 *up); +static inline void cgm_mortho(float *m, float left, float right, float bot, float top, + float znear, float zfar); +static inline void cgm_mfrustum(float *m, float left, float right, float bot, float top, + float znear, float zfar); +static inline void cgm_mperspective(float *m, float vfov, float aspect, float znear, float zfar); + +static inline void cgm_mmirror(float *m, float a, float b, float c, float d); + +/* --- operations on rays --- */ +static inline void cgm_rcons(cgm_ray *r, float x, float y, float z, float dx, float dy, float dz); + +static inline void cgm_rmul_mr(cgm_ray *ray, const float *m); /* m4x4 * ray */ +static inline void cgm_rmul_rm(cgm_ray *ray, const float *m); /* ray * m4x4 */ + +static inline void cgm_rreflect(cgm_ray *ray, const cgm_vec3 *n); +static inline void cgm_rrefract(cgm_ray *ray, const cgm_vec3 *n, float ior); + +/* --- miscellaneous utility functions --- */ +static inline float cgm_deg_to_rad(float deg); +static inline float cgm_rad_to_deg(float rad); + +static inline float cgm_smoothstep(float a, float b, float x); +static inline float cgm_lerp(float a, float b, float t); +static inline float cgm_bezier(float a, float b, float c, float d, float t); +static inline float cgm_bspline(float a, float b, float c, float d, float t); +static inline float cgm_spline(float a, float b, float c, float d, float t); + +static inline void cgm_discrand(cgm_vec3 *v, float rad); +static inline void cgm_sphrand(cgm_vec3 *v, float rad); + +static inline void cgm_unproject(cgm_vec3 *res, const cgm_vec3 *norm_scrpos, + const float *inv_viewproj); +static inline void cgm_glu_unproject(float winx, float winy, float winz, + const float *view, const float *proj, const int *vp, + float *objx, float *objy, float *objz); + +static inline void cgm_pick_ray(cgm_ray *ray, float nx, float ny, + const float *viewmat, const float *projmat); + +static inline void cgm_raypos(cgm_vec3 *p, const cgm_ray *ray, float t); + +/* calculate barycentric coordinates of point pt in triangle (a, b, c) */ +static inline void cgm_bary(cgm_vec3 *bary, const cgm_vec3 *a, + const cgm_vec3 *b, const cgm_vec3 *c, const cgm_vec3 *pt); + +#include "cgmvec3.inl" +#include "cgmvec4.inl" +#include "cgmquat.inl" +#include "cgmmat.inl" +#include "cgmray.inl" +#include "cgmmisc.inl" + +#ifdef __cplusplus +} +#endif + +#endif /* CGMATH_H_ */ diff --git a/libs/cgmath/cgmmat.inl b/libs/cgmath/cgmmat.inl new file mode 100644 index 0000000..2eb4519 --- /dev/null +++ b/libs/cgmath/cgmmat.inl @@ -0,0 +1,623 @@ +/* gph-cmath - C graphics math library + * Copyright (C) 2018 John Tsiombikas + * + * This program is free software. Feel free to use, modify, and/or redistribute + * it under the terms of the MIT/X11 license. See LICENSE for details. + * If you intend to redistribute parts of the code without the LICENSE file + * replace this paragraph with the full contents of the LICENSE file. + */ +static inline void cgm_mcopy(float *dest, const float *src) +{ + memcpy(dest, src, 16 * sizeof(float)); +} + +static inline void cgm_mzero(float *m) +{ + static float z[16]; + cgm_mcopy(m, z); +} + +static inline void cgm_midentity(float *m) +{ + static float id[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; + cgm_mcopy(m, id); +} + +static inline void cgm_mmul(float *a, const float *b) +{ + int i, j; + float res[16]; + float *resptr = res; + float *arow = a; + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + *resptr++ = arow[0] * b[j] + arow[1] * b[4 + j] + + arow[2] * b[8 + j] + arow[3] * b[12 + j]; + } + arow += 4; + } + cgm_mcopy(a, res); +} + +static inline void cgm_mpremul(float *a, const float *b) +{ + int i, j; + float res[16]; + float *resptr = res; + const float *brow = b; + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + *resptr++ = brow[0] * a[j] + brow[1] * a[4 + j] + + brow[2] * a[8 + j] + brow[3] * a[12 + j]; + } + brow += 4; + } + cgm_mcopy(a, res); +} + +static inline void cgm_msubmatrix(float *m, int row, int col) +{ + float orig[16]; + int i, j, subi, subj; + + cgm_mcopy(orig, m); + + subi = 0; + for(i=0; i<4; i++) { + if(i == row) continue; + + subj = 0; + for(j=0; j<4; j++) { + if(j == col) continue; + + m[subi * 4 + subj++] = orig[i * 4 + j]; + } + subi++; + } + + cgm_mupper3(m); +} + +static inline void cgm_mupper3(float *m) +{ + m[3] = m[7] = m[11] = m[12] = m[13] = m[14] = 0.0f; + m[15] = 1.0f; +} + +static inline float cgm_msubdet(const float *m, int row, int col) +{ + float tmp[16]; + float subdet00, subdet01, subdet02; + + cgm_mcopy(tmp, m); + cgm_msubmatrix(tmp, row, col); + + subdet00 = tmp[5] * tmp[10] - tmp[6] * tmp[9]; + subdet01 = tmp[4] * tmp[10] - tmp[6] * tmp[8]; + subdet02 = tmp[4] * tmp[9] - tmp[5] * tmp[8]; + + return tmp[0] * subdet00 - tmp[1] * subdet01 + tmp[2] * subdet02; +} + +static inline float cgm_mcofactor(const float *m, int row, int col) +{ + float min = cgm_msubdet(m, row, col); + return (row + col) & 1 ? -min : min; +} + +static inline float cgm_mdet(const float *m) +{ + return m[0] * cgm_msubdet(m, 0, 0) - m[1] * cgm_msubdet(m, 0, 1) + + m[2] * cgm_msubdet(m, 0, 2) - m[3] * cgm_msubdet(m, 0, 3); +} + +static inline void cgm_mtranspose(float *m) +{ + int i, j; + for(i=0; i<4; i++) { + for(j=0; jx * q->x; + float ysq2 = 2.0f * q->y * q->y; + float zsq2 = 2.0f * q->z * q->z; + float sx = 1.0f - ysq2 - zsq2; + float sy = 1.0f - xsq2 - zsq2; + float sz = 1.0f - xsq2 - ysq2; + + m[3] = m[7] = m[11] = m[12] = m[13] = m[14] = 0.0f; + m[15] = 1.0f; + + m[0] = sx; + m[1] = 2.0f * q->x * q->y + 2.0f * q->w * q->z; + m[2] = 2.0f * q->z * q->x - 2.0f * q->w * q->y; + m[4] = 2.0f * q->x * q->y - 2.0f * q->w * q->z; + m[5] = sy; + m[6] = 2.0f * q->y * q->z + 2.0f * q->w * q->x; + m[8] = 2.0f * q->z * q->x + 2.0f * q->w * q->y; + m[9] = 2.0f * q->y * q->z - 2.0f * q->w * q->x; + m[10] = sz; +} + +static inline void cgm_mtranslate(float *m, float x, float y, float z) +{ + float tm[16]; + cgm_mtranslation(tm, x, y, z); + cgm_mmul(m, tm); +} + +static inline void cgm_mscale(float *m, float sx, float sy, float sz) +{ + float sm[16]; + cgm_mscaling(sm, sx, sy, sz); + cgm_mmul(m, sm); +} + +static inline void cgm_mrotate_x(float *m, float angle) +{ + float rm[16]; + cgm_mrotation_x(rm, angle); + cgm_mmul(m, rm); +} + +static inline void cgm_mrotate_y(float *m, float angle) +{ + float rm[16]; + cgm_mrotation_y(rm, angle); + cgm_mmul(m, rm); +} + +static inline void cgm_mrotate_z(float *m, float angle) +{ + float rm[16]; + cgm_mrotation_z(rm, angle); + cgm_mmul(m, rm); +} + +static inline void cgm_mrotate_axis(float *m, int idx, float angle) +{ + float rm[16]; + cgm_mrotation_axis(rm, idx, angle); + cgm_mmul(m, rm); +} + +static inline void cgm_mrotate(float *m, float angle, float x, float y, float z) +{ + float rm[16]; + cgm_mrotation(rm, angle, x, y, z); + cgm_mmul(m, rm); +} + +static inline void cgm_mrotate_euler(float *m, float a, float b, float c, int mode) +{ + float rm[16]; + cgm_mrotation_euler(rm, a, b, c, mode); + cgm_mmul(m, rm); +} + +static inline void cgm_mrotate_quat(float *m, const cgm_quat *q) +{ + float rm[16]; + cgm_mrotation_quat(rm, q); + cgm_mmul(m, rm); +} + + +static inline void cgm_mpretranslate(float *m, float x, float y, float z) +{ + float tm[16]; + cgm_mtranslation(tm, x, y, z); + cgm_mpremul(m, tm); +} + +static inline void cgm_mprescale(float *m, float sx, float sy, float sz) +{ + float sm[16]; + cgm_mscaling(sm, sx, sy, sz); + cgm_mpremul(m, sm); +} + +static inline void cgm_mprerotate_x(float *m, float angle) +{ + float rm[16]; + cgm_mrotation_x(rm, angle); + cgm_mpremul(m, rm); +} + +static inline void cgm_mprerotate_y(float *m, float angle) +{ + float rm[16]; + cgm_mrotation_y(rm, angle); + cgm_mpremul(m, rm); +} + +static inline void cgm_mprerotate_z(float *m, float angle) +{ + float rm[16]; + cgm_mrotation_z(rm, angle); + cgm_mpremul(m, rm); +} + +static inline void cgm_mprerotate_axis(float *m, int idx, float angle) +{ + float rm[16]; + cgm_mrotation_axis(rm, idx, angle); + cgm_mpremul(m, rm); +} + +static inline void cgm_mprerotate(float *m, float angle, float x, float y, float z) +{ + float rm[16]; + cgm_mrotation(rm, angle, x, y, z); + cgm_mpremul(m, rm); +} + +static inline void cgm_mprerotate_euler(float *m, float a, float b, float c, int mode) +{ + float rm[16]; + cgm_mrotation_euler(rm, a, b, c, mode); + cgm_mpremul(m, rm); +} + +static inline void cgm_mprerotate_quat(float *m, const cgm_quat *q) +{ + float rm[16]; + cgm_mrotation_quat(rm, q); + cgm_mpremul(m, rm); +} + + +static inline void cgm_mget_translation(const float *m, cgm_vec3 *res) +{ + res->x = m[12]; + res->y = m[13]; + res->z = m[14]; +} + +/* Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes + * article "Quaternion Calculus and Fast Animation". + * adapted from: http://www.geometrictools.com/LibMathematics/Algebra/Wm5Quaternion.inl + */ +static inline void cgm_mget_rotation(const float *m, cgm_quat *res) +{ + static const int next[3] = {1, 2, 0}; + float quat[4]; + int i, j, k; + + float trace = m[0] + m[5] + m[10]; + float root; + + if(trace > 0.0f) { + /* |w| > 1/2 */ + root = sqrt(trace + 1.0f); /* 2w */ + res->w = 0.5f * root; + root = 0.5f / root; /* 1 / 4w */ + res->x = (m[6] - m[9]) * root; + res->y = (m[8] - m[2]) * root; + res->z = (m[1] - m[4]) * root; + } else { + /* |w| <= 1/2 */ + i = 0; + if(m[5] > m[0]) { + i = 1; + } + if(m[10] > m[i * 4 + i]) { + i = 2; + } + j = next[i]; + k = next[j]; + + root = sqrt(m[i * 4 + i] - m[j * 4 + j] - m[k * 4 + k] + 1.0f); + quat[i + 1] = 0.5f * root; + root = 0.5f / root; + quat[0] = (m[j + 4 + k] - m[k * 4 + j]) * root; + quat[j + 1] = (m[i * 4 + j] - m[j * 4 + i]) * root; + quat[k + 1] = (m[i * 4 + k] - m[k * 4 + i]) * root; + res->w = quat[0]; + res->x = quat[1]; + res->y = quat[2]; + res->z = quat[3]; + } +} + +static inline void cgm_mget_scaling(const float *m, cgm_vec3 *res) +{ + res->x = sqrt(m[0] * m[0] + m[4] * m[4] + m[8] * m[8]); + res->y = sqrt(m[1] * m[1] + m[5] * m[5] + m[9] * m[9]); + res->z = sqrt(m[2] * m[2] + m[6] * m[6] + m[10] * m[10]); +} + +static inline void cgm_mget_frustum_plane(const float *m, int p, cgm_vec4 *res) +{ + int row = p >> 1; + const float *rowptr = m + row * 4; + + if((p & 1) == 0) { + res->x = m[12] + rowptr[0]; + res->y = m[13] + rowptr[1]; + res->z = m[14] + rowptr[2]; + res->w = m[15] + rowptr[3]; + } else { + res->x = m[12] - rowptr[0]; + res->y = m[13] - rowptr[1]; + res->z = m[14] - rowptr[2]; + res->w = m[15] - rowptr[3]; + } +} + +static inline void cgm_mlookat(float *m, const cgm_vec3 *pos, const cgm_vec3 *targ, + const cgm_vec3 *up) +{ + float trans[16]; + cgm_vec3 dir = *targ, right, vup; + + cgm_vsub(&dir, pos); + cgm_vnormalize(&dir); + cgm_vcross(&right, &dir, up); + cgm_vnormalize(&right); + cgm_vcross(&vup, &right, &dir); + cgm_vnormalize(&vup); + + cgm_midentity(m); + m[0] = right.x; + m[1] = right.y; + m[2] = right.z; + m[4] = vup.x; + m[5] = vup.y; + m[6] = vup.z; + m[8] = -dir.x; + m[9] = -dir.y; + m[10] = -dir.z; + + cgm_mtranslation(trans, pos->x, pos->y, pos->z); + cgm_mmul(m, trans); +} + +static inline void cgm_minv_lookat(float *m, const cgm_vec3 *pos, const cgm_vec3 *targ, + const cgm_vec3 *up) +{ + float rot[16]; + cgm_vec3 dir = *targ, right, vup; + + cgm_vsub(&dir, pos); + cgm_vnormalize(&dir); + cgm_vcross(&right, &dir, up); + cgm_vnormalize(&right); + cgm_vcross(&vup, &right, &dir); + cgm_vnormalize(&vup); + + cgm_midentity(rot); + rot[0] = right.x; + rot[4] = right.y; + rot[8] = right.z; + rot[1] = vup.x; + rot[5] = vup.y; + rot[9] = vup.z; + rot[2] = -dir.x; + rot[6] = -dir.y; + rot[10] = -dir.z; + + cgm_mtranslation(m, -pos->x, -pos->y, -pos->z); + cgm_mmul(m, rot); +} + +static inline void cgm_mortho(float *m, float left, float right, float bot, float top, + float znear, float zfar) +{ + float dx = right - left; + float dy = top - bot; + float dz = zfar - znear; + + cgm_midentity(m); + m[0] = 2.0f / dx; + m[5] = 2.0f / dy; + m[10] = -2.0f / dz; + m[12] = -(right + left) / dx; + m[13] = -(top + bot) / dy; + m[14] = -(zfar + znear) / dz; +} + +static inline void cgm_mfrustum(float *m, float left, float right, float bot, float top, + float znear, float zfar) +{ + float dx = right - left; + float dy = top - bot; + float dz = zfar - znear; + + cgm_mzero(m); + m[0] = 2.0f * znear / dx; + m[5] = 2.0f * znear / dy; + m[8] = (right + left) / dx; + m[9] = (top + bot) / dy; + m[10] = -(zfar + znear) / dz; + m[14] = -2.0f * zfar * znear / dz; + m[11] = -1.0f; +} + +static inline void cgm_mperspective(float *m, float vfov, float aspect, float znear, float zfar) +{ + float s = 1.0f / (float)tan(vfov / 2.0f); + float range = znear - zfar; + + cgm_mzero(m); + m[0] = s / aspect; + m[5] = s; + m[10] = (znear + zfar) / range; + m[14] = 2.0f * znear * zfar / range; + m[11] = -1.0f; +} + +static inline void cgm_mmirror(float *m, float a, float b, float c, float d) +{ + m[0] = 1.0f - 2.0f * a * a; + m[5] = 1.0f - 2.0f * b * b; + m[10] = 1.0f - 2.0f * c * c; + m[15] = 1.0f; + + m[1] = m[4] = -2.0f * a * b; + m[2] = m[8] = -2.0f * a * c; + m[6] = m[9] = -2.0f * b * c; + + m[12] = -2.0f * a * d; + m[13] = -2.0f * b * d; + m[14] = -2.0f * c * d; + + m[3] = m[7] = m[11] = 0.0f; +} diff --git a/libs/cgmath/cgmmisc.inl b/libs/cgmath/cgmmisc.inl new file mode 100644 index 0000000..e4360f6 --- /dev/null +++ b/libs/cgmath/cgmmisc.inl @@ -0,0 +1,190 @@ +/* gph-cmath - C graphics math library + * Copyright (C) 2018 John Tsiombikas + * + * This program is free software. Feel free to use, modify, and/or redistribute + * it under the terms of the MIT/X11 license. See LICENSE for details. + * If you intend to redistribute parts of the code without the LICENSE file + * replace this paragraph with the full contents of the LICENSE file. + */ +#include + +static inline float cgm_deg_to_rad(float deg) +{ + return M_PI * deg / 180.0f; +} + +static inline float cgm_rad_to_deg(float rad) +{ + return 180.0f * rad / M_PI; +} + +static inline float cgm_smoothstep(float a, float b, float x) +{ + if(x < a) return 0.0f; + if(x >= b) return 1.0f; + + x = (x - a) / (b - a); + return x * x * (3.0f - 2.0f * x); +} + +static inline float cgm_lerp(float a, float b, float t) +{ + return a + (b - a) * t; +} + +static inline float cgm_bezier(float a, float b, float c, float d, float t) +{ + float omt, omt3, t3, f; + t3 = t * t * t; + omt = 1.0f - t; + omt3 = omt * omt * omt; + f = 3.0f * t * omt; + + return (a * omt3) + (b * f * omt) + (c * f * t) + (d * t3); +} + +static inline float cgm_bspline(float a, float b, float c, float d, float t) +{ + static const float mat[] = { + -1, 3, -3, 1, + 3, -6, 0, 4, + -3, 3, 3, 1, + 1, 0, 0, 0 + }; + cgm_vec4 tmp, qfact; + float tsq = t * t; + + cgm_wcons(&qfact, tsq * t, tsq, t, 1.0f); + cgm_wcons(&tmp, a, b, c, d); + cgm_wmul_m4v4(&tmp, mat); + cgm_wscale(&tmp, 1.0f / 6.0f); + return cgm_wdot(&tmp, &qfact); +} + +static inline float cgm_spline(float a, float b, float c, float d, float t) +{ + static const float mat[] = { + -1, 2, -1, 0, + 3, -5, 0, 2, + -3, 4, 1, 0, + 1, -1, 0, 0 + }; + cgm_vec4 tmp, qfact; + float tsq = t * t; + + cgm_wcons(&qfact, tsq * t, tsq, t, 1.0f); + cgm_wcons(&tmp, a, b, c, d); + cgm_wmul_m4v4(&tmp, mat); + cgm_wscale(&tmp, 1.0f / 6.0f); + return cgm_wdot(&tmp, &qfact); +} + +static inline void cgm_discrand(cgm_vec3 *pt, float rad) +{ + float theta = 2.0f * M_PI * (float)rand() / RAND_MAX; + float r = sqrt((float)rand() / RAND_MAX) * rad; + pt->x = cos(theta) * r; + pt->y = sin(theta) * r; + pt->z = 0.0f; +} + +static inline void cgm_sphrand(cgm_vec3 *pt, float rad) +{ + float u, v, theta, phi; + + u = (float)rand() / RAND_MAX; + v = (float)rand() / RAND_MAX; + + theta = 2.0f * M_PI * u; + phi = acos(2.0f * v - 1.0f); + + pt->x = cos(theta) * sin(phi) * rad; + pt->y = sin(theta) * sin(phi) * rad; + pt->z = cos(phi) * rad; +} + +static inline void cgm_unproject(cgm_vec3 *res, const cgm_vec3 *norm_scrpos, + const float *inv_viewproj) +{ + cgm_vec4 pos; + + pos.x = 2.0f * norm_scrpos->x - 1.0f; + pos.y = 2.0f * norm_scrpos->y - 1.0f; + pos.z = 2.0f * norm_scrpos->z - 1.0f; + pos.w = 1.0f; + + cgm_wmul_m4v4(&pos, inv_viewproj); + + res->x = pos.x / pos.w; + res->y = pos.y / pos.w; + res->z = pos.z / pos.w; +} + +static inline void cgm_glu_unproject(float winx, float winy, float winz, + const float *view, const float *proj, const int *vp, + float *objx, float *objy, float *objz) +{ + cgm_vec3 npos, res; + float inv_pv[16]; + + cgm_mcopy(inv_pv, proj); + cgm_mmul(inv_pv, view); + + npos.x = (winx - vp[0]) / vp[2]; + npos.y = (winy - vp[1]) / vp[4]; + npos.z = winz; + + cgm_unproject(&res, &npos, inv_pv); + + *objx = res.x; + *objy = res.y; + *objz = res.z; +} + +static inline void cgm_pick_ray(cgm_ray *ray, float nx, float ny, + const float *viewmat, const float *projmat) +{ + cgm_vec3 npos, farpt; + float inv_pv[16]; + + cgm_mcopy(inv_pv, projmat); + cgm_mmul(inv_pv, viewmat); + + cgm_vcons(&npos, nx, ny, 0.0f); + cgm_unproject(&ray->origin, &npos, inv_pv); + npos.z = 1.0f; + cgm_unproject(&farpt, &npos, inv_pv); + + ray->dir.x = farpt.x - ray->origin.x; + ray->dir.y = farpt.y - ray->origin.y; + ray->dir.z = farpt.z - ray->origin.z; +} + +static inline void cgm_raypos(cgm_vec3 *p, const cgm_ray *ray, float t) +{ + p->x = ray->origin.x + ray->dir.x * t; + p->y = ray->origin.y + ray->dir.y * t; + p->z = ray->origin.z + ray->dir.z * t; +} + +static inline void cgm_bary(cgm_vec3 *bary, const cgm_vec3 *a, + const cgm_vec3 *b, const cgm_vec3 *c, const cgm_vec3 *pt) +{ + float d00, d01, d11, d20, d21, denom; + cgm_vec3 v0 = *b, v1 = *c, v2 = *pt; + + cgm_vsub(&v0, a); + cgm_vsub(&v1, a); + cgm_vsub(&v2, a); + + d00 = cgm_vdot(&v0, &v0); + d01 = cgm_vdot(&v0, &v1); + d11 = cgm_vdot(&v1, &v1); + d20 = cgm_vdot(&v2, &v0); + d21 = cgm_vdot(&v2, &v1); + denom = d00 * d11 - d01 * d01; + + bary->y = (d11 * d20 - d01 * d21) / denom; + bary->z = (d00 * d21 - d01 * d20) / denom; + bary->x = 1.0f - bary->y - bary->z; +} diff --git a/libs/cgmath/cgmquat.inl b/libs/cgmath/cgmquat.inl new file mode 100644 index 0000000..743d818 --- /dev/null +++ b/libs/cgmath/cgmquat.inl @@ -0,0 +1,159 @@ +/* gph-cmath - C graphics math library + * Copyright (C) 2018 John Tsiombikas + * + * This program is free software. Feel free to use, modify, and/or redistribute + * it under the terms of the MIT/X11 license. See LICENSE for details. + * If you intend to redistribute parts of the code without the LICENSE file + * replace this paragraph with the full contents of the LICENSE file. + */ +static inline void cgm_qcons(cgm_quat *q, float x, float y, float z, float w) +{ + q->x = x; + q->y = y; + q->z = z; + q->w = w; +} + + +static inline void cgm_qneg(cgm_quat *q) +{ + q->x = -q->x; + q->y = -q->y; + q->z = -q->z; + q->w = -q->w; +} + +static inline void cgm_qadd(cgm_quat *a, const cgm_quat *b) +{ + a->x += b->x; + a->y += b->y; + a->z += b->z; + a->w += b->w; +} + +static inline void cgm_qsub(cgm_quat *a, const cgm_quat *b) +{ + a->x -= b->x; + a->y -= b->y; + a->z -= b->z; + a->w -= b->w; +} + +static inline void cgm_qmul(cgm_quat *a, const cgm_quat *b) +{ + float x, y, z, dot; + cgm_vec3 cross; + + dot = a->x * b->x + a->y * b->y + a->z * b->z; + cgm_vcross(&cross, (cgm_vec3*)a, (cgm_vec3*)b); + + x = a->w * b->x + b->w * a->x + cross.x; + y = a->w * b->y + b->w * a->y + cross.y; + z = a->w * b->z + b->w * a->z + cross.z; + a->w = a->w * b->w - dot; + a->x = x; + a->y = y; + a->z = z; +} + +static inline float cgm_qlength(const cgm_quat *q) +{ + return sqrt(q->x * q->x + q->y * q->y + q->z * q->z + q->w * q->w); +} + +static inline float cgm_qlength_sq(const cgm_quat *q) +{ + return q->x * q->x + q->y * q->y + q->z * q->z + q->w * q->w; +} + +static inline void cgm_qnormalize(cgm_quat *q) +{ + float len = cgm_qlength(q); + if(len != 0.0f) { + float s = 1.0f / len; + q->x *= s; + q->y *= s; + q->z *= s; + q->w *= s; + } +} + +static inline void cgm_qconjugate(cgm_quat *q) +{ + q->x = -q->x; + q->y = -q->y; + q->z = -q->z; +} + +static inline void cgm_qinvert(cgm_quat *q) +{ + float len_sq = cgm_qlength_sq(q); + cgm_qconjugate(q); + if(len_sq != 0.0f) { + float s = 1.0f / len_sq; + q->x *= s; + q->y *= s; + q->z *= s; + q->w *= s; + } +} + +static inline void cgm_qrotation(cgm_quat *q, float angle, float x, float y, float z) +{ + float hangle = angle * 0.5f; + float sin_ha = sin(hangle); + q->w = cos(hangle); + q->x = x * sin_ha; + q->y = y * sin_ha; + q->z = z * sin_ha; +} + +static inline void cgm_qrotate(cgm_quat *q, float angle, float x, float y, float z) +{ + cgm_quat qrot; + cgm_qrotation(&qrot, angle, x, y, z); + cgm_qmul(q, &qrot); +} + +static inline void cgm_qslerp(cgm_quat *res, const cgm_quat *quat1, const cgm_quat *q2, float t) +{ + float angle, dot, a, b, sin_angle; + cgm_quat q1 = *quat1; + + dot = quat1->x * q2->x + quat1->y * q2->y + quat1->z * q2->z + quat1->w * q2->w; + if(dot < 0.0f) { + /* make sure we inteprolate across the shortest arc */ + cgm_qneg(&q1); + dot = -dot; + } + + /* clamp dot to [-1, 1] in order to avoid domain errors in acos due to + * floating point imprecisions + */ + if(dot < -1.0f) dot = -1.0f; + if(dot > 1.0f) dot = 1.0f; + angle = acos(dot); + + sin_angle = sin(angle); + if(sin_angle == 0.0f) { + /* use linear interpolation to avoid div/zero */ + a = 1.0f; + b = t; + } else { + a = sin((1.0f - t) * angle) / sin_angle; + b = sin(t * angle) / sin_angle; + } + + res->x = q1.x * a + q2->x * b; + res->y = q1.y * a + q2->y * b; + res->z = q1.z * a + q2->z * b; + res->w = q1.w * a + q2->w * b; +} + +static inline void cgm_qlerp(cgm_quat *res, const cgm_quat *a, const cgm_quat *b, float t) +{ + res->x = a->x + (b->x - a->x) * t; + res->y = a->y + (b->y - a->y) * t; + res->z = a->z + (b->z - a->z) * t; + res->w = a->w + (b->w - a->w) * t; +} diff --git a/libs/cgmath/cgmray.inl b/libs/cgmath/cgmray.inl new file mode 100644 index 0000000..063a7e0 --- /dev/null +++ b/libs/cgmath/cgmray.inl @@ -0,0 +1,39 @@ +/* gph-cmath - C graphics math library + * Copyright (C) 2018 John Tsiombikas + * + * This program is free software. Feel free to use, modify, and/or redistribute + * it under the terms of the MIT/X11 license. See LICENSE for details. + * If you intend to redistribute parts of the code without the LICENSE file + * replace this paragraph with the full contents of the LICENSE file. + */ +static inline void cgm_rcons(cgm_ray *r, float x, float y, float z, float dx, float dy, float dz) +{ + r->origin.x = x; + r->origin.y = y; + r->origin.z = z; + r->dir.x = dx; + r->dir.y = dy; + r->dir.z = dz; +} + +static inline void cgm_rmul_mr(cgm_ray *ray, const float *m) +{ + cgm_vmul_m4v3(&ray->origin, m); + cgm_vmul_m3v3(&ray->dir, m); +} + +static inline void cgm_rmul_rm(cgm_ray *ray, const float *m) +{ + cgm_vmul_v3m4(&ray->origin, m); + cgm_vmul_v3m3(&ray->dir, m); +} + +static inline void cgm_rreflect(cgm_ray *ray, const cgm_vec3 *n) +{ + cgm_vreflect(&ray->dir, n); +} + +static inline void cgm_rrefract(cgm_ray *ray, const cgm_vec3 *n, float ior) +{ + cgm_vrefract(&ray->dir, n, ior); +} diff --git a/libs/cgmath/cgmvec3.inl b/libs/cgmath/cgmvec3.inl new file mode 100644 index 0000000..3747029 --- /dev/null +++ b/libs/cgmath/cgmvec3.inl @@ -0,0 +1,188 @@ +/* gph-cmath - C graphics math library + * Copyright (C) 2018 John Tsiombikas + * + * This program is free software. Feel free to use, modify, and/or redistribute + * it under the terms of the MIT/X11 license. See LICENSE for details. + * If you intend to redistribute parts of the code without the LICENSE file + * replace this paragraph with the full contents of the LICENSE file. + */ +static inline void cgm_vcons(cgm_vec3 *v, float x, float y, float z) +{ + v->x = x; + v->y = y; + v->z = z; +} + +static inline void cgm_vadd(cgm_vec3 *a, const cgm_vec3 *b) +{ + a->x += b->x; + a->y += b->y; + a->z += b->z; +} + +static inline void cgm_vsub(cgm_vec3 *a, const cgm_vec3 *b) +{ + a->x -= b->x; + a->y -= b->y; + a->z -= b->z; +} + +static inline void cgm_vmul(cgm_vec3 *a, const cgm_vec3 *b) +{ + a->x *= b->x; + a->y *= b->y; + a->z *= b->z; +} + +static inline void cgm_vscale(cgm_vec3 *v, float s) +{ + v->x *= s; + v->y *= s; + v->z *= s; +} + +static inline void cgm_vmul_m4v3(cgm_vec3 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[4] + v->z * m[8] + m[12]; + float y = v->x * m[1] + v->y * m[5] + v->z * m[9] + m[13]; + v->z = v->x * m[2] + v->y * m[6] + v->z * m[10] + m[14]; + v->x = x; + v->y = y; +} + +static inline void cgm_vmul_v3m4(cgm_vec3 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[1] + v->z * m[2] + m[3]; + float y = v->x * m[4] + v->y * m[5] + v->z * m[6] + m[7]; + v->z = v->x * m[8] + v->y * m[9] + v->z * m[10] + m[11]; + v->x = x; + v->y = y; +} + +static inline void cgm_vmul_m3v3(cgm_vec3 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[4] + v->z * m[8]; + float y = v->x * m[1] + v->y * m[5] + v->z * m[9]; + v->z = v->x * m[2] + v->y * m[6] + v->z * m[10]; + v->x = x; + v->y = y; +} + +static inline void cgm_vmul_v3m3(cgm_vec3 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[1] + v->z * m[2]; + float y = v->x * m[4] + v->y * m[5] + v->z * m[6]; + v->z = v->x * m[8] + v->y * m[9] + v->z * m[10]; + v->x = x; + v->y = y; +} + +static inline float cgm_vdot(const cgm_vec3 *a, const cgm_vec3 *b) +{ + return a->x * b->x + a->y * b->y + a->z * b->z; +} + +static inline void cgm_vcross(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b) +{ + res->x = a->y * b->z - a->z * b->y; + res->y = a->z * b->x - a->x * b->z; + res->z = a->x * b->y - a->y * b->x; +} + +static inline float cgm_vlength(const cgm_vec3 *v) +{ + return sqrt(v->x * v->x + v->y * v->y + v->z * v->z); +} + +static inline float cgm_vlength_sq(const cgm_vec3 *v) +{ + return v->x * v->x + v->y * v->y + v->z * v->z; +} + +static inline float cgm_vdist(const cgm_vec3 *a, const cgm_vec3 *b) +{ + float dx = a->x - b->x; + float dy = a->y - b->y; + float dz = a->z - b->z; + return sqrt(dx * dx + dy * dy + dz * dz); +} + +static inline float cgm_vdist_sq(const cgm_vec3 *a, const cgm_vec3 *b) +{ + float dx = a->x - b->x; + float dy = a->y - b->y; + float dz = a->z - b->z; + return dx * dx + dy * dy + dz * dz; +} + +static inline void cgm_vnormalize(cgm_vec3 *v) +{ + float len = cgm_vlength(v); + if(len != 0.0f) { + float s = 1.0f / len; + v->x *= s; + v->y *= s; + v->z *= s; + } +} + +static inline void cgm_vreflect(cgm_vec3 *v, const cgm_vec3 *n) +{ + float ndotv2 = cgm_vdot(v, n) * 2.0f; + v->x -= n->x * ndotv2; + v->y -= n->y * ndotv2; + v->z -= n->z * ndotv2; +} + +static inline void cgm_vrefract(cgm_vec3 *v, const cgm_vec3 *n, float ior) +{ + float ndotv = cgm_vdot(v, n); + float k = 1.0f - ior * ior * (1.0f - ndotv * ndotv); + if(k < 0.0f) { + cgm_vreflect(v, n); /* TIR */ + } else { + float sqrt_k = sqrt(k); + v->x = ior * v->x - (ior * ndotv + sqrt_k) * n->x; + v->y = ior * v->y - (ior * ndotv + sqrt_k) * n->y; + v->z = ior * v->z - (ior * ndotv + sqrt_k) * n->z; + } +} + +static inline void cgm_vrotate_quat(cgm_vec3 *v, const cgm_quat *q) +{ + cgm_quat vq, inv_q = *q, tmp_q = *q; + + cgm_qcons(&vq, v->x, v->y, v->z, 0.0f); + cgm_qinvert(&inv_q); + cgm_qmul(&tmp_q, &vq); + cgm_qmul(&tmp_q, &inv_q); + cgm_vcons(v, tmp_q.x, tmp_q.y, tmp_q.z); +} + +static inline void cgm_vrotate_axis(cgm_vec3 *v, int axis, float angle) +{ + float m[16]; + cgm_mrotation_axis(m, axis, angle); + cgm_vmul_m3v3(v, m); +} + +static inline void cgm_vrotate(cgm_vec3 *v, float angle, float x, float y, float z) +{ + float m[16]; + cgm_mrotation(m, angle, x, y, z); + cgm_vmul_m3v3(v, m); +} + +static inline void cgm_vrotate_euler(cgm_vec3 *v, float a, float b, float c, enum cgm_euler_mode mode) +{ + float m[16]; + cgm_mrotation_euler(m, a, b, c, mode); + cgm_vmul_m3v3(v, m); +} + +static inline void cgm_vlerp(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b, float t) +{ + res->x = a->x + (b->x - a->x) * t; + res->y = a->y + (b->y - a->y) * t; + res->z = a->z + (b->z - a->z) * t; +} diff --git a/libs/cgmath/cgmvec4.inl b/libs/cgmath/cgmvec4.inl new file mode 100644 index 0000000..b68856c --- /dev/null +++ b/libs/cgmath/cgmvec4.inl @@ -0,0 +1,158 @@ +/* gph-cmath - C graphics math library + * Copyright (C) 2018 John Tsiombikas + * + * This program is free software. Feel free to use, modify, and/or redistribute + * it under the terms of the MIT/X11 license. See LICENSE for details. + * If you intend to redistribute parts of the code without the LICENSE file + * replace this paragraph with the full contents of the LICENSE file. + */ +static inline void cgm_wcons(cgm_vec4 *v, float x, float y, float z, float w) +{ + v->x = x; + v->y = y; + v->z = z; + v->w = w; +} + +static inline void cgm_wadd(cgm_vec4 *a, const cgm_vec4 *b) +{ + a->x += b->x; + a->y += b->y; + a->z += b->z; + a->w += b->w; +} + +static inline void cgm_wsub(cgm_vec4 *a, const cgm_vec4 *b) +{ + a->x -= b->x; + a->y -= b->y; + a->z -= b->z; + a->w -= b->w; +} + +static inline void cgm_wmul(cgm_vec4 *a, const cgm_vec4 *b) +{ + a->x *= b->x; + a->y *= b->y; + a->z *= b->z; + a->w *= b->w; +} + +static inline void cgm_wscale(cgm_vec4 *v, float s) +{ + v->x *= s; + v->y *= s; + v->z *= s; + v->w *= s; +} + +static inline void cgm_wmul_m4v4(cgm_vec4 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[4] + v->z * m[8] + v->w * m[12]; + float y = v->x * m[1] + v->y * m[5] + v->z * m[9] + v->w * m[13]; + float z = v->x * m[2] + v->y * m[6] + v->z * m[10] + v->w * m[14]; + v->w = v->x * m[3] + v->y * m[7] + v->z * m[11] + v->w * m[15]; + v->x = x; + v->y = y; + v->z = z; +} + +static inline void cgm_wmul_v4m4(cgm_vec4 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[1] + v->z * m[2] + v->w * m[3]; + float y = v->x * m[4] + v->y * m[5] + v->z * m[6] + v->w * m[7]; + float z = v->x * m[8] + v->y * m[9] + v->z * m[10] + v->w * m[11]; + v->w = v->x * m[12] + v->y * m[13] + v->z * m[14] + v->w * m[15]; + v->x = x; + v->y = y; + v->z = z; +} + +static inline void cgm_wmul_m34v4(cgm_vec4 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[4] + v->z * m[8] + v->w * m[12]; + float y = v->x * m[1] + v->y * m[5] + v->z * m[9] + v->w * m[13]; + v->z = v->x * m[2] + v->y * m[6] + v->z * m[10] + v->w * m[14]; + v->x = x; + v->y = y; +} + +static inline void cgm_wmul_v4m43(cgm_vec4 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[1] + v->z * m[2] + v->w * m[3]; + float y = v->x * m[4] + v->y * m[5] + v->z * m[6] + v->w * m[7]; + v->z = v->x * m[8] + v->y * m[9] + v->z * m[10] + v->w * m[11]; + v->x = x; + v->y = y; +} + +static inline void cgm_wmul_m3v4(cgm_vec4 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[4] + v->z * m[8]; + float y = v->x * m[1] + v->y * m[5] + v->z * m[9]; + v->z = v->x * m[2] + v->y * m[6] + v->z * m[10]; + v->x = x; + v->y = y; +} + +static inline void cgm_wmul_v4m3(cgm_vec4 *v, const float *m) +{ + float x = v->x * m[0] + v->y * m[1] + v->z * m[2]; + float y = v->x * m[4] + v->y * m[5] + v->z * m[6]; + v->z = v->x * m[8] + v->y * m[9] + v->z * m[10]; + v->x = x; + v->y = y; +} + +static inline float cgm_wdot(const cgm_vec4 *a, const cgm_vec4 *b) +{ + return a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w; +} + +static inline float cgm_wlength(const cgm_vec4 *v) +{ + return sqrt(v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w); +} + +static inline float cgm_wlength_sq(const cgm_vec4 *v) +{ + return v->x * v->x + v->y * v->y + v->z * v->z + v->w * v->w; +} + +static inline float cgm_wdist(const cgm_vec4 *a, const cgm_vec4 *b) +{ + float dx = a->x - b->x; + float dy = a->y - b->y; + float dz = a->z - b->z; + float dw = a->w - b->w; + return sqrt(dx * dx + dy * dy + dz * dz + dw * dw); +} + +static inline float cgm_wdist_sq(const cgm_vec4 *a, const cgm_vec4 *b) +{ + float dx = a->x - b->x; + float dy = a->y - b->y; + float dz = a->z - b->z; + float dw = a->w - b->w; + return dx * dx + dy * dy + dz * dz + dw * dw; +} + +static inline void cgm_wnormalize(cgm_vec4 *v) +{ + float len = cgm_wlength(v); + if(len != 0.0f) { + float s = 1.0f / len; + v->x *= s; + v->y *= s; + v->z *= s; + v->w *= s; + } +} + +static inline void cgm_wlerp(cgm_vec4 *res, const cgm_vec4 *a, const cgm_vec4 *b, float t) +{ + res->x = a->x + (b->x - a->x) * t; + res->y = a->y + (b->y - a->y) * t; + res->z = a->z + (b->z - a->z) * t; + res->w = a->w + (b->w - a->w) * t; +}