1 /* gph-cmath - C graphics math library
2 * Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
4 * This program is free software. Feel free to use, modify, and/or redistribute
5 * it under the terms of the MIT/X11 license. See LICENSE for details.
6 * If you intend to redistribute parts of the code without the LICENSE file
7 * replace this paragraph with the full contents of the LICENSE file.
9 static CGM_INLINE void cgm_vcons(cgm_vec3 *v, float x, float y, float z)
16 static CGM_INLINE cgm_vec3 cgm_vvec(float x, float y, float z)
25 static CGM_INLINE void cgm_vneg(cgm_vec3 *v)
32 static CGM_INLINE void cgm_vadd(cgm_vec3 *a, const cgm_vec3 *b)
39 static CGM_INLINE void cgm_vadd_scaled(cgm_vec3 *a, const cgm_vec3 *b, float s)
46 static CGM_INLINE void cgm_vsub(cgm_vec3 *a, const cgm_vec3 *b)
53 static CGM_INLINE void cgm_vsub_scaled(cgm_vec3 *a, const cgm_vec3 *b, float s)
60 static CGM_INLINE void cgm_vmul(cgm_vec3 *a, const cgm_vec3 *b)
67 static CGM_INLINE void cgm_vscale(cgm_vec3 *v, float s)
74 static CGM_INLINE void cgm_vmul_m4v3(cgm_vec3 *v, const float *m)
76 float x = v->x * m[0] + v->y * m[4] + v->z * m[8] + m[12];
77 float y = v->x * m[1] + v->y * m[5] + v->z * m[9] + m[13];
78 v->z = v->x * m[2] + v->y * m[6] + v->z * m[10] + m[14];
83 static CGM_INLINE void cgm_vmul_v3m4(cgm_vec3 *v, const float *m)
85 float x = v->x * m[0] + v->y * m[1] + v->z * m[2] + m[3];
86 float y = v->x * m[4] + v->y * m[5] + v->z * m[6] + m[7];
87 v->z = v->x * m[8] + v->y * m[9] + v->z * m[10] + m[11];
92 static CGM_INLINE void cgm_vmul_m3v3(cgm_vec3 *v, const float *m)
94 float x = v->x * m[0] + v->y * m[4] + v->z * m[8];
95 float y = v->x * m[1] + v->y * m[5] + v->z * m[9];
96 v->z = v->x * m[2] + v->y * m[6] + v->z * m[10];
101 static CGM_INLINE void cgm_vmul_v3m3(cgm_vec3 *v, const float *m)
103 float x = v->x * m[0] + v->y * m[1] + v->z * m[2];
104 float y = v->x * m[4] + v->y * m[5] + v->z * m[6];
105 v->z = v->x * m[8] + v->y * m[9] + v->z * m[10];
110 static CGM_INLINE float cgm_vdot(const cgm_vec3 *a, const cgm_vec3 *b)
112 return a->x * b->x + a->y * b->y + a->z * b->z;
115 static CGM_INLINE void cgm_vcross(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b)
117 res->x = a->y * b->z - a->z * b->y;
118 res->y = a->z * b->x - a->x * b->z;
119 res->z = a->x * b->y - a->y * b->x;
122 static CGM_INLINE float cgm_vlength(const cgm_vec3 *v)
124 return sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
127 static CGM_INLINE float cgm_vlength_sq(const cgm_vec3 *v)
129 return v->x * v->x + v->y * v->y + v->z * v->z;
132 static CGM_INLINE float cgm_vdist(const cgm_vec3 *a, const cgm_vec3 *b)
134 float dx = a->x - b->x;
135 float dy = a->y - b->y;
136 float dz = a->z - b->z;
137 return sqrt(dx * dx + dy * dy + dz * dz);
140 static CGM_INLINE float cgm_vdist_sq(const cgm_vec3 *a, const cgm_vec3 *b)
142 float dx = a->x - b->x;
143 float dy = a->y - b->y;
144 float dz = a->z - b->z;
145 return dx * dx + dy * dy + dz * dz;
148 static CGM_INLINE void cgm_vnormalize(cgm_vec3 *v)
150 float len = cgm_vlength(v);
152 float s = 1.0f / len;
159 static CGM_INLINE void cgm_vreflect(cgm_vec3 *v, const cgm_vec3 *n)
161 float ndotv2 = cgm_vdot(v, n) * 2.0f;
162 v->x -= n->x * ndotv2;
163 v->y -= n->y * ndotv2;
164 v->z -= n->z * ndotv2;
167 static CGM_INLINE void cgm_vrefract(cgm_vec3 *v, const cgm_vec3 *n, float ior)
169 float ndotv = cgm_vdot(v, n);
170 float k = 1.0f - ior * ior * (1.0f - ndotv * ndotv);
172 cgm_vreflect(v, n); /* TIR */
174 float sqrt_k = sqrt(k);
175 v->x = ior * v->x - (ior * ndotv + sqrt_k) * n->x;
176 v->y = ior * v->y - (ior * ndotv + sqrt_k) * n->y;
177 v->z = ior * v->z - (ior * ndotv + sqrt_k) * n->z;
181 static CGM_INLINE void cgm_vrotate_quat(cgm_vec3 *v, const cgm_quat *q)
183 cgm_quat vq, inv_q = *q, tmp_q = *q;
185 cgm_qcons(&vq, v->x, v->y, v->z, 0.0f);
187 cgm_qmul(&tmp_q, &vq);
188 cgm_qmul(&tmp_q, &inv_q);
189 cgm_vcons(v, tmp_q.x, tmp_q.y, tmp_q.z);
192 static CGM_INLINE void cgm_vrotate_axis(cgm_vec3 *v, int axis, float angle)
195 cgm_mrotation_axis(m, axis, angle);
199 static CGM_INLINE void cgm_vrotate(cgm_vec3 *v, float angle, float x, float y, float z)
202 cgm_mrotation(m, angle, x, y, z);
206 static CGM_INLINE void cgm_vrotate_euler(cgm_vec3 *v, float a, float b, float c, enum cgm_euler_mode mode)
209 cgm_mrotation_euler(m, a, b, c, mode);
213 static CGM_INLINE void cgm_vlerp(cgm_vec3 *res, const cgm_vec3 *a, const cgm_vec3 *b, float t)
215 res->x = a->x + (b->x - a->x) * t;
216 res->y = a->y + (b->y - a->y) * t;
217 res->z = a->z + (b->z - a->z) * t;