├── .gitignore ├── LICENSE ├── MMath.h └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 |  2 | # .gitignore made for use in Visual Studio. 3 | 4 | *.filters 5 | *.lastbuildstate 6 | *.vcxproj 7 | *.log 8 | *.user 9 | 10 | testing/ 11 | Debug/ 12 | Release/ 13 | MMath.wiki/ 14 | MMath.wiki 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Zachary Wells 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MMath.h: -------------------------------------------------------------------------------- 1 | #ifndef MMATH_HEADER_FILE 2 | #define MMATH_HEADER_FILE 3 | 4 | /* MMath.h -- MMath library file 5 | * 6 | * Copyright (C) 2017 Zachary Wells 7 | * 8 | * This software may be modified and distributed under the terms 9 | * of the MIT license. See the LICENSE file for details. 10 | */ 11 | 12 | #include 13 | 14 | #if defined(__cplusplus) 15 | extern "C" { 16 | #endif 17 | 18 | #define MMATH_INLINE static inline 19 | #define MMATH_CONST static const 20 | 21 | //Types 22 | #if defined(MMATH_DOUBLE) 23 | typedef double scalar; 24 | #else 25 | typedef float scalar; 26 | #endif 27 | 28 | typedef struct vec2_s { 29 | union { 30 | scalar data[2]; 31 | struct { scalar x, y; }; 32 | //struct { scalar g, a; }; 33 | }; 34 | } vec2; 35 | typedef struct vec3_s { 36 | union { 37 | scalar data[3]; 38 | struct { scalar x, y, z; }; 39 | struct { scalar r, g, b; }; 40 | }; 41 | } vec3; 42 | typedef struct vec4_s { 43 | union { 44 | scalar data[4]; 45 | struct { scalar x, y, z, w; }; 46 | struct { scalar r, g, b, a; }; 47 | }; 48 | } vec4; 49 | 50 | typedef struct quat_s { 51 | union { 52 | scalar data[4]; 53 | vec4 vec; 54 | vec3 axis; 55 | struct { scalar x, y, z, w; }; 56 | }; 57 | } quat; 58 | 59 | typedef struct mat2_s { 60 | union { 61 | scalar data[2 * 2]; 62 | vec2 row[2]; 63 | struct { 64 | scalar x0, y0; 65 | scalar x1, y1; 66 | }; 67 | struct { 68 | vec2 r0; 69 | vec2 r1; 70 | }; 71 | }; 72 | } mat2; 73 | typedef struct mat3_s { 74 | union { 75 | scalar data[3 * 3]; 76 | vec3 row[3]; 77 | struct { 78 | scalar x0, y0, z0; 79 | scalar x1, y1, z1; 80 | scalar x2, y2, z2; 81 | }; 82 | struct { 83 | vec3 r0; 84 | vec3 r1; 85 | vec3 r2; 86 | }; 87 | }; 88 | } mat3; 89 | typedef struct mat4_s { 90 | union { 91 | scalar data[4 * 4]; 92 | vec4 row[4]; 93 | struct { 94 | scalar x0, y0, z0, w0; 95 | scalar x1, y1, z1, w1; 96 | scalar x2, y2, z2, w2; 97 | scalar x3, y3, z3, w3; 98 | }; 99 | struct { 100 | vec4 r0; 101 | vec4 r1; 102 | vec4 r2; 103 | vec4 r3; 104 | }; 105 | }; 106 | } mat4; 107 | 108 | typedef struct transform_t { 109 | vec3 pos; 110 | vec3 scale; 111 | quat rot; 112 | } transform; 113 | 114 | #if defined(MMATH_DOUBLE) 115 | #define mm_sqrt(var) (sqrt(var)) 116 | #define mm_acos(var) (acos(var)) 117 | #define mm_asin(var) (asin(var)) 118 | #define mm_atan(var) (atan(var)) 119 | #define mm_cos(var) (cos(var)) 120 | #define mm_sin(var) (sin(var)) 121 | #define mm_tan(var) (tan(var)) 122 | #define mm_min(x, y) (fmin(x, y)) 123 | #define mm_max(x, y) (fmax(x, y)) 124 | #define mm_abs(var) (fabs(var)) 125 | #else 126 | #define mm_sqrt(var) (sqrtf(var)) 127 | #define mm_acos(var) (acosf(var)) 128 | #define mm_asin(var) (asinf(var)) 129 | #define mm_atan(var) (atanf(var)) 130 | #define mm_cos(var) (cosf(var)) 131 | #define mm_sin(var) (sinf(var)) 132 | #define mm_tan(var) (tanf(var)) 133 | #define mm_min(x, y) (fminf(x, y)) 134 | #define mm_max(x, y) (fmaxf(x, y)) 135 | #define mm_abs(var) (fabsf(var)) 136 | #endif 137 | 138 | //constants 139 | #define mm_dpi ((scalar)6.283185307179586) //double pi 140 | #define mm_pi ((scalar)3.141592653589793) //pi 141 | #define mm_hpi ((scalar)1.570796326794896) //half pi 142 | 143 | //Functions 144 | MMATH_INLINE scalar radians(scalar degrees) { 145 | return degrees * (scalar)0.0174532925199432; //PI / 180 146 | } 147 | MMATH_INLINE scalar degrees(scalar radians) { 148 | return radians * (scalar)57.295779513082325; //180 / PI 149 | } 150 | 151 | //Vector Math 152 | #define VEC_FOR(integer) for (int i = 0; i < integer; i++) 153 | #define MMATH_GENFUNC_VECNEGATE(integer) \ 154 | MMATH_INLINE vec##integer* vec##integer##Negate(vec##integer *dest, const vec##integer *a) { \ 155 | VEC_FOR(integer) { \ 156 | dest->data[i] = -a->data[i]; \ 157 | } \ 158 | return dest; \ 159 | } 160 | #define MMATH_GENFUNC_VECABS(integer) \ 161 | MMATH_INLINE vec##integer* vec##integer##Abs(vec##integer *dest, const vec##integer *a) { \ 162 | VEC_FOR(integer) { \ 163 | dest->data[i] = mm_abs(a->data[i]); \ 164 | } \ 165 | return dest; \ 166 | } 167 | #define MMATH_GENFUNC_VECADDSCALAR(integer) \ 168 | MMATH_INLINE vec##integer* vec##integer##AddScalar(vec##integer *dest, const vec##integer *a, scalar b) { \ 169 | VEC_FOR(integer) { \ 170 | dest->data[i] = a->data[i] + b; \ 171 | } \ 172 | return dest; \ 173 | } 174 | #define MMATH_GENFUNC_VECSUBSCALAR(integer) \ 175 | MMATH_INLINE vec##integer* vec##integer##SubScalar(vec##integer *dest, const vec##integer *a, scalar b) { \ 176 | VEC_FOR(integer) { \ 177 | dest->data[i] = a->data[i] - b; \ 178 | } \ 179 | return dest; \ 180 | } 181 | #define MMATH_GENFUNC_VECMULSCALAR(integer) \ 182 | MMATH_INLINE vec##integer* vec##integer##MulScalar(vec##integer *dest, const vec##integer *a, scalar b) { \ 183 | VEC_FOR(integer) { \ 184 | dest->data[i] = a->data[i] * b; \ 185 | } \ 186 | return dest; \ 187 | } 188 | #define MMATH_GENFUNC_VECDIVSCALAR(integer) \ 189 | MMATH_INLINE vec##integer* vec##integer##DivScalar(vec##integer *dest, const vec##integer *a, scalar b) { \ 190 | VEC_FOR(integer) { \ 191 | dest->data[i] = a->data[i] / b; \ 192 | } \ 193 | return dest; \ 194 | } 195 | #define MMATH_GENFUNC_VECADD(integer) \ 196 | MMATH_INLINE vec##integer* vec##integer##Add(vec##integer *dest, const vec##integer *a, const vec##integer *b) { \ 197 | VEC_FOR(integer) { \ 198 | dest->data[i] = a->data[i] + b->data[i]; \ 199 | } \ 200 | return dest; \ 201 | } 202 | #define MMATH_GENFUNC_VECSUB(integer) \ 203 | MMATH_INLINE vec##integer* vec##integer##Sub(vec##integer *dest, const vec##integer *a, const vec##integer *b) { \ 204 | VEC_FOR(integer) { \ 205 | dest->data[i] = a->data[i] - b->data[i]; \ 206 | } \ 207 | return dest; \ 208 | } 209 | #define MMATH_GENFUNC_VECMUL(integer) \ 210 | MMATH_INLINE vec##integer* vec##integer##Mul(vec##integer *dest, const vec##integer *a, const vec##integer *b) { \ 211 | VEC_FOR(integer) { \ 212 | dest->data[i] = a->data[i] * b->data[i]; \ 213 | } \ 214 | return dest; \ 215 | } 216 | #define MMATH_GENFUNC_VECDIV(integer) \ 217 | MMATH_INLINE vec##integer* vec##integer##Div(vec##integer *dest, const vec##integer *a, const vec##integer *b) { \ 218 | VEC_FOR(integer) { \ 219 | dest->data[i] = a->data[i] / b->data[i]; \ 220 | } \ 221 | return dest; \ 222 | } 223 | #define MMATH_GENFUNC_VECDOT(integer) \ 224 | MMATH_INLINE scalar vec##integer##Dot(const vec##integer *a, const vec##integer *b) { \ 225 | scalar ret = 0; \ 226 | VEC_FOR(integer) { \ 227 | ret += a->data[i] * b->data[i]; \ 228 | } \ 229 | return ret; \ 230 | } 231 | #define MMATH_GENFUNC_VECLEN(integer) \ 232 | MMATH_INLINE scalar vec##integer##Length(const vec##integer *a) { \ 233 | scalar sum = 0; \ 234 | VEC_FOR(integer) { \ 235 | sum += a->data[i] * a->data[i]; \ 236 | } \ 237 | return mm_sqrt(sum); \ 238 | } 239 | #define MMATH_GENFUNC_VECDIST(integer) \ 240 | MMATH_INLINE scalar vec##integer##Distance(const vec##integer *a, const vec##integer *b) { \ 241 | vec##integer dir; \ 242 | vec##integer##Sub(&dir, b, a); \ 243 | return vec##integer##Length(&dir); \ 244 | } 245 | #define MMATH_GENFUNC_VECNORM(integer) \ 246 | MMATH_INLINE vec##integer* vec##integer##Normalize(vec##integer *dest, const vec##integer *a) { \ 247 | scalar len = vec##integer##Length(a); \ 248 | if (len == 0) { \ 249 | return dest; \ 250 | } \ 251 | len = 1.f / len; \ 252 | VEC_FOR(integer) { \ 253 | dest->data[i] = a->data[i] * len; \ 254 | } \ 255 | return dest; \ 256 | } 257 | #define MMATH_GENFUNC_VECLERP(integer) \ 258 | MMATH_INLINE vec##integer* vec##integer##Lerp(vec##integer *dest, const vec##integer *f, const vec##integer *l, scalar t) { \ 259 | vec##integer temp1; \ 260 | vec##integer##Sub(&temp1, l, f); \ 261 | vec##integer temp2; \ 262 | vec##integer##MulScalar(&temp2, &temp1, t); \ 263 | vec##integer##Add(dest, &temp2, f); \ 264 | return dest; \ 265 | } 266 | #define MMATH_GENFUNC_VECSTANDARD(integer) \ 267 | MMATH_GENFUNC_VECADDSCALAR(integer) \ 268 | MMATH_GENFUNC_VECSUBSCALAR(integer) \ 269 | MMATH_GENFUNC_VECMULSCALAR(integer) \ 270 | MMATH_GENFUNC_VECDIVSCALAR(integer) \ 271 | MMATH_GENFUNC_VECADD(integer) \ 272 | MMATH_GENFUNC_VECSUB(integer) \ 273 | MMATH_GENFUNC_VECMUL(integer) \ 274 | MMATH_GENFUNC_VECDIV(integer) \ 275 | MMATH_GENFUNC_VECDOT(integer) \ 276 | MMATH_GENFUNC_VECLEN(integer) \ 277 | MMATH_GENFUNC_VECDIST(integer) \ 278 | MMATH_GENFUNC_VECNORM(integer) \ 279 | MMATH_GENFUNC_VECLERP(integer) \ 280 | MMATH_GENFUNC_VECNEGATE(integer) \ 281 | MMATH_GENFUNC_VECABS(integer) 282 | 283 | MMATH_GENFUNC_VECSTANDARD(2) 284 | MMATH_CONST vec2 vec2Zero = { 0, 0 }; 285 | MMATH_CONST vec2 vec2Identity = { 1, 1 }; 286 | MMATH_INLINE vec3* vec2ToVec3(vec3 *dest, const vec2 *a, scalar z) { 287 | dest->x = a->x; 288 | dest->y = a->y; 289 | dest->z = z; 290 | return dest; 291 | } 292 | MMATH_INLINE vec4* vec2ToVec4(vec4 *dest, const vec2 *a, scalar z, scalar w) { 293 | dest->x = a->x; 294 | dest->y = a->y; 295 | dest->z = z; 296 | dest->w = w; 297 | return dest; 298 | } 299 | 300 | MMATH_GENFUNC_VECSTANDARD(3) 301 | MMATH_CONST vec3 vec3Zero = { 0, 0, 0 }; 302 | MMATH_CONST vec3 vec3Identity = { 1, 1, 1 }; 303 | MMATH_CONST vec3 vec3XAxis = { 1, 0, 0 }; 304 | MMATH_CONST vec3 vec3YAxis = { 0, 1, 0 }; 305 | MMATH_CONST vec3 vec3ZAxis = { 0, 0, 1 }; 306 | MMATH_INLINE vec2* vec3ToVec2(vec2 *dest, const vec3 *a) { 307 | dest->x = a->x; 308 | dest->y = a->y; 309 | return dest; 310 | } 311 | MMATH_INLINE vec4* vec3ToVec4(vec4 *dest, const vec3 *a, scalar w) { 312 | dest->x = a->x; 313 | dest->y = a->y; 314 | dest->z = a->z; 315 | dest->w = w; 316 | return dest; 317 | } 318 | MMATH_INLINE vec3* vec3Cross(vec3 *dest, const vec3 *a, const vec3 *b) { 319 | dest->x = a->y * b->z - a->z * b->y; 320 | dest->y = a->z * b->x - a->x * b->z; 321 | dest->z = a->x * b->y - a->y * b->x; 322 | return dest; 323 | } 324 | 325 | MMATH_GENFUNC_VECSTANDARD(4) 326 | MMATH_CONST vec4 vec4Zero = { 0, 0, 0, 0 }; 327 | MMATH_CONST vec4 vec4Identity = { 1, 1, 1, 1 }; 328 | MMATH_INLINE vec2* vec4ToVec2(vec2 *dest, const vec4 *a) { 329 | dest->x = a->x; 330 | dest->y = a->y; 331 | return dest; 332 | } 333 | MMATH_INLINE vec3* vec4ToVec3(vec3 *dest, const vec4 *a) { 334 | dest->x = a->x; 335 | dest->y = a->y; 336 | dest->z = a->z; 337 | return dest; 338 | } 339 | MMATH_INLINE vec3* vec4DivW(vec3 *dest, const vec4 *a) { 340 | scalar w = (scalar)1.0 / a->w; 341 | dest->x = a->x * w; 342 | dest->y = a->y * w; 343 | dest->z = a->z * w; 344 | return dest; 345 | } 346 | 347 | //Quaternion Math 348 | MMATH_CONST quat quatIndentity = { 0, 0, 0, 1 }; 349 | MMATH_INLINE scalar quatLength(const quat *a) { 350 | return vec4Length((const vec4*)a); 351 | } 352 | MMATH_INLINE quat* quatNormalize(quat *dest, const quat *a) { 353 | vec4Normalize((vec4*)dest, (const vec4*)a); 354 | return dest; 355 | } 356 | MMATH_INLINE quat* quatAddScalar(quat *dest, const quat *a, scalar b) { 357 | vec4AddScalar((vec4*)dest, (const vec4*)a, b); 358 | return dest; 359 | } 360 | MMATH_INLINE quat* quatMulScalar(quat *dest, const quat *a, scalar b) { 361 | vec4MulScalar((vec4*)dest, (const vec4*)a, b); 362 | return dest; 363 | } 364 | MMATH_INLINE quat* quatAdd(quat *dest, const quat *a, const quat *b) { 365 | vec4Add((vec4*)dest, (const vec4*)a, (const vec4*)b); 366 | return dest; 367 | } 368 | MMATH_INLINE quat* quatMul(quat *dest, const quat *a, const quat *b) { 369 | dest->w = a->w * b->w - vec3Dot(&a->axis, &b->axis); 370 | 371 | vec3 BwAv, AwBv, abv, AxB; 372 | vec3Add(&abv, vec3MulScalar(&BwAv, &a->axis, b->w), 373 | vec3MulScalar(&AwBv, &b->axis, a->w)); 374 | 375 | vec3Add(&dest->axis, &abv, vec3Cross(&AxB, &a->axis, &b->axis)); 376 | return dest; 377 | } 378 | MMATH_INLINE vec3* quatMulVec3(vec3 *dest, const quat *a, const vec3 *b) { 379 | vec3 cross1; 380 | vec3Cross(&cross1, &a->axis, b); 381 | 382 | vec3 t; 383 | vec3MulScalar(&t, &cross1, (scalar)2.0); 384 | 385 | vec3 tw; 386 | vec3MulScalar(&tw, &t, a->w); 387 | 388 | vec3 cross2; 389 | vec3Cross(&cross2, &a->axis, &t); 390 | 391 | vec3 tw_cross; 392 | vec3Add(&tw_cross, &tw, &cross2); 393 | 394 | vec3Add(dest, b, &tw_cross); 395 | return dest; 396 | } 397 | MMATH_INLINE quat* quatNegate(quat *dest, const quat *a) { 398 | dest->x = -a->x; 399 | dest->y = -a->y; 400 | dest->z = -a->z; 401 | dest->w = -a->w; 402 | return dest; 403 | } 404 | MMATH_INLINE quat* quatConjugate(quat *dest, const quat *a) { 405 | dest->x = -a->x; 406 | dest->y = -a->y; 407 | dest->z = -a->z; 408 | dest->w = a->w; 409 | return dest; 410 | } 411 | MMATH_INLINE quat* quatInverse(quat *dest, const quat *a) { 412 | quatConjugate(dest, a); 413 | scalar length = quatLength(a); 414 | if (length - ((scalar)1.0) <= 0.00001) { 415 | scalar l2 = (scalar)1.0 / (length * length); 416 | dest->x *= l2; 417 | dest->y *= l2; 418 | dest->z *= l2; 419 | dest->w *= l2; 420 | } 421 | return dest; 422 | } 423 | //pitch X | yaw Y | roll Z 424 | MMATH_INLINE quat* quatEuler(quat *dest, const vec3 *e) { 425 | scalar cy = mm_cos(e->y * (scalar)0.5); 426 | scalar sy = mm_sin(e->y * (scalar)0.5); 427 | scalar cr = mm_cos(e->z * (scalar)0.5); 428 | scalar sr = mm_sin(e->z * (scalar)0.5); 429 | scalar cp = mm_cos(e->x * (scalar)0.5); 430 | scalar sp = mm_sin(e->x * (scalar)0.5); 431 | 432 | dest->x = cy * sr * cp - sy * cr * sp; 433 | dest->y = cy * cr * sp + sy * sr * cp; 434 | dest->z = sy * cr * cp - cy * sr * sp; 435 | dest->w = cy * cr * cp + sy * sr * sp; 436 | return dest; 437 | } 438 | //MMATH_INLINE void quatToEuler(vec3 *dest, const quat *q) { 439 | //TODO: make this 440 | //} 441 | MMATH_INLINE quat* quatAxisAngle(quat *dest, const vec3 *axis, scalar r) { 442 | scalar a2 = r * (scalar)0.5; 443 | vec3MulScalar(&dest->axis, axis, mm_sin(a2)); 444 | dest->w = mm_cos(a2); 445 | return dest; 446 | } 447 | MMATH_INLINE mat3* quatToMat3(mat3 *dest, const quat *a) { 448 | scalar x2 = a->x * a->x, 449 | y2 = a->y * a->y, 450 | z2 = a->z * a->z, 451 | xy = a->x * a->y, 452 | xz = a->x * a->z, 453 | yz = a->y * a->z, 454 | xw = a->x * a->w, 455 | yw = a->y * a->w, 456 | zw = a->z * a->w; 457 | mat3 ret = { 458 | 1-(2*(y2+z2)), 2*(xy+zw), 2*(xz-yw), 459 | 2*(xy-zw), 1-(2*(x2+z2)), 2*(yz+xw), 460 | 2*(xz+yw), 2*(yz-xw), 1-(2*(x2+y2)) 461 | }; 462 | *dest = ret; 463 | return dest; 464 | } 465 | MMATH_INLINE mat4* mat3ToMat4(mat4 *dest, const mat3 *a); 466 | MMATH_INLINE mat4* quatToMat4(mat4 *dest, const quat *a) { 467 | mat3 ret; 468 | quatToMat3(&ret, a); 469 | mat3ToMat4(dest, &ret); 470 | return dest; 471 | } 472 | MMATH_INLINE quat* quatSlerp(quat *dest, const quat * f, const quat *l, scalar t) { 473 | scalar dot = vec4Dot((const vec4*)f, (const vec4*)l); 474 | 475 | if (dot < (scalar)0.0) { 476 | dot = -dot; 477 | quatInverse(dest, l); 478 | } else { 479 | *dest = *l; 480 | } 481 | 482 | if (dot < (scalar)0.95) { 483 | scalar angle = mm_acos(dot); 484 | quat fp; 485 | quatMulScalar(&fp, f, mm_sin(angle * (1 - t))); 486 | 487 | quat temp; 488 | quatMulScalar(&temp, dest, mm_sin(angle * t)); 489 | quatAdd(dest, &fp, &temp); 490 | quatMulScalar(&temp, dest, (scalar)1.0 / mm_sin(angle)); 491 | *dest = temp; 492 | } else { 493 | quat temp; 494 | vec4Lerp((vec4*)&temp, (const vec4*)f, (const vec4*)dest, t); 495 | *dest = temp; 496 | } 497 | 498 | return dest; 499 | } 500 | 501 | //Matrix Math 502 | #define MAT_FOR_FLAT(integer) for (int i = 0; i < integer * integer; i++) 503 | #define MAT_FOR(integer) for (int x = 0; x < integer; x++) for (int y = 0; y < integer; y++) 504 | #define MMATH_GENFUNC_MATTRPOSE(integer) \ 505 | MMATH_INLINE mat##integer* mat##integer##Transpose(mat##integer * dest, const mat##integer *a) { \ 506 | MAT_FOR(integer) { \ 507 | dest->row[x].data[y] = a->row[y].data[x]; \ 508 | } \ 509 | return dest; \ 510 | } 511 | #define MMATH_GENFUNC_MATDIAG(integer) \ 512 | MMATH_INLINE mat##integer* mat##integer##Diagonal(mat##integer *dest, scalar f) { \ 513 | *dest = (mat##integer) {0}; \ 514 | for (int i = 0; i < integer * integer; i += integer + 1) { \ 515 | dest->data[i] = f; \ 516 | } \ 517 | return dest; \ 518 | } 519 | #define MMATH_GENFUNC_MATADD(integer) \ 520 | MMATH_INLINE mat##integer* mat##integer##Add(mat##integer *dest, const mat##integer *a, const mat##integer *b) { \ 521 | MAT_FOR_FLAT(integer) { \ 522 | dest->data[i] = a->data[i] + b->data[i]; \ 523 | } \ 524 | return dest; \ 525 | } 526 | #define MMATH_GENFUNC_MATSUB(integer) \ 527 | MMATH_INLINE mat##integer* mat##integer##Sub(mat##integer *dest, const mat##integer *a, const mat##integer *b) { \ 528 | MAT_FOR_FLAT(integer) { \ 529 | dest->data[i] = a->data[i] - b->data[i]; \ 530 | } \ 531 | return dest; \ 532 | } 533 | #define MMATH_GENFUNC_MATMUL(integer) \ 534 | MMATH_INLINE mat##integer* mat##integer##Mul(mat##integer *dest, const mat##integer *a, const mat##integer *b) { \ 535 | *dest = (mat##integer){0}; \ 536 | MAT_FOR(integer) { \ 537 | VEC_FOR(integer) { \ 538 | dest->row[x].data[y] += a->row[x].data[i] * b->row[i].data[y]; \ 539 | } \ 540 | } \ 541 | return dest; \ 542 | } 543 | #define MMATH_GENFUNC_MATMULSCALAR(integer) \ 544 | MMATH_INLINE mat##integer* mat##integer##MulScalar(mat##integer *dest, const mat##integer *a, scalar b) { \ 545 | MAT_FOR_FLAT(integer) { \ 546 | dest->data[i] = a->data[i] * b; \ 547 | } \ 548 | return dest; \ 549 | } 550 | #define MMATH_GENFUNC_MATMULVEC(integer) \ 551 | MMATH_INLINE vec##integer* mat##integer##MulVec##integer(vec##integer *dest, const mat##integer *a, const vec##integer *b) { \ 552 | *dest = (vec##integer){0}; \ 553 | VEC_FOR(integer) { \ 554 | for (int c = 0; c < integer; c++) { \ 555 | dest->data[i] += a->row[c].data[i] * b->data[c]; \ 556 | } \ 557 | } \ 558 | return dest; \ 559 | } 560 | #define MMATH_GENFUNC_MATSTANDARD(integer) \ 561 | MMATH_GENFUNC_MATTRPOSE(integer) \ 562 | MMATH_GENFUNC_MATDIAG(integer) \ 563 | MMATH_GENFUNC_MATADD(integer) \ 564 | MMATH_GENFUNC_MATSUB(integer) \ 565 | MMATH_GENFUNC_MATMUL(integer) \ 566 | MMATH_GENFUNC_MATMULSCALAR(integer) \ 567 | MMATH_GENFUNC_MATMULVEC(integer) 568 | 569 | MMATH_GENFUNC_MATSTANDARD(2) 570 | MMATH_CONST mat2 mat2Identity = { 571 | 1, 0, 572 | 0, 1 573 | }; 574 | MMATH_INLINE mat3* mat2ToMat3(mat3 *dest, const mat2 *a) { 575 | mat3 ret = { 576 | a->x0, a->y0, 0, 577 | a->x1, a->y1, 0, 578 | 0, 0, 1 579 | }; 580 | *dest = ret; 581 | return dest; 582 | } 583 | MMATH_INLINE mat4* mat2ToMat4(mat4 *dest, const mat2 *a) { 584 | mat4 ret = { 585 | a->x0, a->y0, 0, 0, 586 | a->x1, a->y1, 0, 0, 587 | 0, 0, 1, 0, 588 | 0, 0, 0, 1 589 | }; 590 | *dest = ret; 591 | return dest; 592 | } 593 | 594 | MMATH_GENFUNC_MATSTANDARD(3) 595 | MMATH_CONST mat3 mat3Identity = { 596 | 1, 0, 0, 597 | 0, 1, 0, 598 | 0, 0, 1 599 | }; 600 | MMATH_INLINE mat2* mat3ToMat2(mat2 *dest, const mat3 *a) { 601 | mat2 ret = { 602 | a->x0, a->y0, 603 | a->x1, a->y1 604 | }; 605 | *dest = ret; 606 | return dest; 607 | } 608 | MMATH_INLINE mat4* mat3ToMat4(mat4 *dest, const mat3 *a) { 609 | mat4 ret = { 610 | a->x0, a->y0, a->z0, 0, 611 | a->x1, a->y1, a->z1, 0, 612 | a->x2, a->y2, a->z2, 0, 613 | 0, 0, 0, 1 614 | }; 615 | *dest = ret; 616 | return dest; 617 | } 618 | //MMATH_INLINE void mat3Inverse(mat3 *dest, const mat3 *a) { 619 | // mat3 ret; TODO: also make this 620 | //} 621 | MMATH_INLINE mat3* mat3RotateX(mat3 *dest, scalar r) { 622 | scalar c = mm_cos(r); 623 | scalar s = mm_sin(r); 624 | mat3 ret = { 625 | 1, 0, 0, 626 | 0, c, s, 627 | 0,-s, c 628 | }; 629 | *dest = ret; 630 | return dest; 631 | } 632 | MMATH_INLINE mat3* mat3RotateY(mat3 *dest, scalar r) { 633 | scalar c = mm_cos(r); 634 | scalar s = mm_sin(r); 635 | mat3 ret = { 636 | c, 0,-s, 637 | 0, 1, 0, 638 | s, 0, c 639 | }; 640 | *dest = ret; 641 | return dest; 642 | } 643 | MMATH_INLINE mat3* mat3RotateZ(mat3 *dest, scalar r) { 644 | scalar c = mm_cos(r); 645 | scalar s = mm_sin(r); 646 | mat3 ret = { 647 | c, s, 0, 648 | -s, c, 0, 649 | 0, 0, 1 650 | }; 651 | *dest = ret; 652 | return dest; 653 | } 654 | 655 | MMATH_GENFUNC_MATSTANDARD(4) 656 | MMATH_CONST mat4 mat4Identity = { 657 | 1, 0, 0, 0, 658 | 0, 1, 0, 0, 659 | 0, 0, 1, 0, 660 | 0, 0, 0, 1 661 | }; 662 | MMATH_INLINE mat4* mat4Scale(mat4 *dest, const vec3 *s) { 663 | mat4 ret = { 664 | s->x, 0, 0, 0, 665 | 0, s->y, 0, 0, 666 | 0, 0, s->z, 0, 667 | 0, 0, 0, 1 668 | }; 669 | *dest = ret; 670 | return dest; 671 | } 672 | MMATH_INLINE mat4* mat4Translate(mat4 *dest, const vec3 *t) { 673 | mat4 ret = { 674 | 1, 0, 0, 0, 675 | 0, 1, 0, 0, 676 | 0, 0, 1, 0, 677 | t->x, t->y, t->z, 1 678 | }; 679 | *dest = ret; 680 | return dest; 681 | } 682 | MMATH_INLINE mat4* mat4Perspective(mat4 *dest, scalar aspect, scalar fovY, scalar zNear, scalar zFar) { 683 | scalar f = (scalar)1.0 / mm_tan(fovY * (scalar)0.5); 684 | scalar nf = (scalar)1.0 / (zNear - zFar); 685 | mat4 ret = { 686 | f/aspect, 0, 0, 0, 687 | 0, f, 0, 0, 688 | 0, 0, (zFar+zNear)*nf, -1, 689 | 0, 0, (2*zFar*zNear)*nf, 0 690 | }; 691 | *dest = ret; 692 | return dest; 693 | } 694 | MMATH_INLINE mat4* mat4Ortho(mat4 *dest, scalar left, scalar right, scalar top, scalar bottom, scalar zNear, scalar zFar) { 695 | scalar tb = top - bottom; 696 | scalar rf = right - left; 697 | scalar fn = zFar - zNear; 698 | mat4 ret = { 699 | 2/rf, 0, 0, 0, 700 | 0, 2/tb, 0, 0, 701 | 0, 0, -2/fn, 0, 702 | -(right + left)/rf, -(top + bottom)/tb, -(zFar + zNear)/fn, 1 703 | }; 704 | *dest = ret; 705 | return dest; 706 | } 707 | MMATH_INLINE mat4* mat4LookAt(mat4 *dest, const vec3 *eye, const vec3 *center, const vec3 *up) { 708 | vec3 temp; 709 | vec3Sub(&temp, center, eye); 710 | 711 | vec3 z; 712 | vec3Normalize(&z, &temp); 713 | 714 | vec3 x; 715 | vec3Cross(&temp, up, &z); 716 | vec3Normalize(&x, &temp); 717 | 718 | vec3 y; 719 | vec3Cross(&temp, &z, &x); 720 | vec3Normalize(&y, &temp); 721 | 722 | scalar n_dot_x = -vec3Dot(&x, eye); 723 | scalar n_dot_y = -vec3Dot(&y, eye); 724 | scalar n_dot_z = -vec3Dot(&z, eye); 725 | 726 | mat4 ret = { 727 | x.x, y.x, z.x, 0, 728 | x.y, y.y, z.y, 0, 729 | x.z, y.z, z.z, 0, 730 | n_dot_x, n_dot_y, n_dot_z, 1 731 | }; 732 | *dest = ret; 733 | return dest; 734 | } 735 | MMATH_INLINE mat2* mat4ToMat2(mat2 *dest, const mat4 *a) { 736 | mat2 ret = { 737 | a->x0, a->y0, 738 | a->x1, a->y1 739 | }; 740 | *dest = ret; 741 | return dest; 742 | } 743 | MMATH_INLINE mat3* mat4ToMat3(mat3 *dest, const mat4 *a) { 744 | mat3 ret = { 745 | a->x0, a->y0, a->z0, 746 | a->x1, a->y1, a->z1, 747 | a->x2, a->y2, a->z2 748 | }; 749 | *dest = ret; 750 | return dest; 751 | } 752 | 753 | //Transformations 754 | MMATH_CONST transform transformIdentity = { {0,0,0}, {1,1,1}, {0,0,0,1} }; 755 | MMATH_INLINE mat4* transformToMat4(mat4 *dest, const transform *t) { 756 | mat4 ret = { 757 | t->scale.x, 0, 0, 0, 758 | 0, t->scale.y, 0, 0, 759 | 0, 0, t->scale.z, 0, 760 | t->pos.x, t->pos.y, t->pos.z, 1 761 | }; 762 | mat4 rotate; 763 | quatToMat4(&rotate, &t->rot); 764 | mat4Mul(dest, &rotate, &ret); 765 | return dest; 766 | } 767 | //TODO: Solve transform inverse (this could mean a lot) 768 | MMATH_INLINE transform* transformMul(transform *dest, const transform *a, const transform *b) { 769 | vec3 pos; 770 | quatMulVec3(&pos, &a->rot, &b->pos); 771 | 772 | vec3 posScale; 773 | vec3Mul(&posScale, &pos, &a->scale); 774 | 775 | vec3Add(&dest->pos, &posScale, &a->pos); 776 | vec3Mul(&dest->scale, &a->scale, &b->scale); 777 | quatMul(&dest->rot, &a->rot, &b->rot); 778 | return dest; 779 | } 780 | MMATH_INLINE transform* transformLerp(transform *dest, const transform *f, const transform *l, scalar t) { 781 | vec3Lerp(&dest->pos, &f->pos, &l->pos, t); 782 | vec3Lerp(&dest->scale, &f->scale, &l->scale, t); 783 | quatSlerp(&dest->rot, &f->rot, &l->rot, t); 784 | return dest; 785 | } 786 | 787 | #if defined(__cplusplus) 788 | } 789 | #endif 790 | 791 | #endif //MMATH_HEADER_FILE 792 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to MMath! 2 | MMath is a single-header math library made in C for use with OpenGL and other similar graphics APIs. 3 | 4 | ###### Quick refernces: 5 | - [Features](#features) 6 | - [On the to-do list](#on-the-to-do-list) 7 | - [License](#license) 8 | - [How to use MMath](#how-to-use-mmath) 9 | 10 | ###### Additional information: 11 | 12 | MMath has been lightly tested with both MSVC and GCC, but problems may still exist. Please report any bugs found in the [issues section](https://github.com/8bitslime/MMath/issues) so they can be dealt with quickly. 13 | 14 | Some documentation is provided in the [wiki](https://github.com/8bitslime/MMath/wiki), but more will be added in the future. 15 | 16 | --- 17 | 18 | ### Features 19 | - Vectors 20 | - Square matrices 21 | - Quaternions 22 | - Transformations 23 | - Easy appending to: 24 | - vectors 25 | - matrices 26 | 27 | --- 28 | 29 | ### On the to-do list 30 | - Rectangular matrices 31 | - SIMD optimizations 32 | - Various profilings 33 | - Renaming the library 34 | 35 | --- 36 | 37 | ### License 38 | MMath is released, free of charge, under the [MIT license](./LICENSE). This means that you are allowed to use MMath for both private and commercial projects as well as modify and redistribute it. You are not obligated to credit MMath in your projects, but it would be greatly appreciated. 39 | 40 | --- 41 | 42 | ### How to use MMath 43 | To add MMath to your project, simply put the [`MMath.h`](./MMath.h) header file in your project's include directory and use `#include "MMath.h"` anywhere math is required. 44 | 45 | If you require *double precision*, add the line `#define MMATH_DOUBLE` before including [`MMath.h`](./MMath.h). 46 | --------------------------------------------------------------------------------