comparison third_party/raylib/include/raymath.h @ 276:b55c22cff335

Add interactive infinite canvas prototype
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 16:57:56 -0700
parents f33d9ff8b6e8
children
comparison
equal deleted inserted replaced
274:c9be578316a6 276:b55c22cff335
13 * required code is directly re-implemented inside 13 * required code is directly re-implemented inside
14 * - Functions input parameters are always received by value (2 unavoidable exceptions) 14 * - Functions input parameters are always received by value (2 unavoidable exceptions)
15 * - Functions use always a "result" variable for return (except C++ operators) 15 * - Functions use always a "result" variable for return (except C++ operators)
16 * - Functions are always defined inline 16 * - Functions are always defined inline
17 * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) 17 * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
18 * - No compound literals used to make sure libray is compatible with C++ 18 * - No compound literals used to make sure the library is compatible with C++
19 * 19 *
20 * CONFIGURATION: 20 * CONFIGURATION:
21 * #define RAYMATH_IMPLEMENTATION 21 * #define RAYMATH_IMPLEMENTATION
22 * Generates the implementation of the library into the included file. 22 * Generates the implementation of the library into the included file
23 * If not defined, the library is in header only mode and can be included in other headers 23 * If not defined, the library is in header only mode and can be included in other headers
24 * or source files without problems. But only ONE file should hold the implementation. 24 * or source files without problems. But only ONE file should hold the implementation
25 * 25 *
26 * #define RAYMATH_STATIC_INLINE 26 * #define RAYMATH_STATIC_INLINE
27 * Define static inline functions code, so #include header suffices for use. 27 * Define static inline functions code, so #include header suffices for use
28 * This may use up lots of memory. 28 * This may use up lots of memory
29 * 29 *
30 * #define RAYMATH_DISABLE_CPP_OPERATORS 30 * #define RAYMATH_DISABLE_CPP_OPERATORS
31 * Disables C++ operator overloads for raymath types. 31 * Disables C++ operator overloads for raymath types.
32 * 32 *
33 * #define RAYMATH_USE_SIMD_INTRINSICS 1
34 * Try to enable SIMD intrinsics for MatrixMultiply()
35 * Note that users enabling it must be aware of the target platform where application will
36 * run to support the selected SIMD intrinsic, for now, only SSE is supported
37 *
33 * LICENSE: zlib/libpng 38 * LICENSE: zlib/libpng
34 * 39 *
35 * Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) 40 * Copyright (c) 2015-2026 Ramon Santamaria (@raysan5)
36 * 41 *
37 * This software is provided "as-is", without any express or implied warranty. In no event 42 * This software is provided "as-is", without any express or implied warranty. In no event
38 * will the authors be held liable for any damages arising from the use of this software. 43 * will the authors be held liable for any damages arising from the use of this software.
39 * 44 *
40 * Permission is granted to anyone to use this software for any purpose, including commercial 45 * Permission is granted to anyone to use this software for any purpose, including commercial
59 #endif 64 #endif
60 65
61 // Function specifiers definition 66 // Function specifiers definition
62 #if defined(RAYMATH_IMPLEMENTATION) 67 #if defined(RAYMATH_IMPLEMENTATION)
63 #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) 68 #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED)
64 #define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll) 69 #define RMAPI __declspec(dllexport) extern inline // Building raylib as a Win32 shared library (.dll)
65 #elif defined(BUILD_LIBTYPE_SHARED) 70 #elif defined(BUILD_LIBTYPE_SHARED)
66 #define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib) 71 #define RMAPI __attribute__((visibility("default"))) // Building raylib as a Unix shared library (.so/.dylib)
67 #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) 72 #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED)
68 #define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) 73 #define RMAPI __declspec(dllimport) // Using raylib as a Win32 shared library (.dll)
69 #else 74 #else
70 #define RMAPI extern inline // Provide external definition 75 #define RMAPI extern inline // Provide external definition
71 #endif 76 #endif
72 #elif defined(RAYMATH_STATIC_INLINE) 77 #elif defined(RAYMATH_STATIC_INLINE)
73 #define RMAPI static inline // Functions may be inlined, no external out-of-line definition 78 #define RMAPI static inline // Functions may be inlined, no external out-of-line definition
77 #else 82 #else
78 #define RMAPI inline // Functions may be inlined or external definition used 83 #define RMAPI inline // Functions may be inlined or external definition used
79 #endif 84 #endif
80 #endif 85 #endif
81 86
82
83 //---------------------------------------------------------------------------------- 87 //----------------------------------------------------------------------------------
84 // Defines and Macros 88 // Defines and Macros
85 //---------------------------------------------------------------------------------- 89 //----------------------------------------------------------------------------------
86 #ifndef PI 90 #ifndef PI
87 #define PI 3.14159265358979323846f 91 #define PI 3.14159265358979323846f
158 } Matrix; 162 } Matrix;
159 #define RL_MATRIX_TYPE 163 #define RL_MATRIX_TYPE
160 #endif 164 #endif
161 165
162 // NOTE: Helper types to be used instead of array return types for *ToFloat functions 166 // NOTE: Helper types to be used instead of array return types for *ToFloat functions
167 #if !defined(RL_FLOAT3_TYPE)
163 typedef struct float3 { 168 typedef struct float3 {
164 float v[3]; 169 float v[3];
165 } float3; 170 } float3;
166 171 #define RL_FLOAT3_TYPE
172 #endif
173
174 #if !defined(RL_FLOAT16_TYPE)
167 typedef struct float16 { 175 typedef struct float16 {
168 float v[16]; 176 float v[16];
169 } float16; 177 } float16;
178 #define RL_FLOAT16_TYPE
179 #endif
170 180
171 #include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabsf() 181 #include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabsf()
182
183 #if RAYMATH_USE_SIMD_INTRINSICS
184 // SIMD is used on the most costly raymath function MatrixMultiply()
185 // NOTE: Only SSE intrinsics support implemented
186 // TODO: Consider support for other SIMD intrinsics:
187 // - SSEx, AVX, AVX2, FMA, NEON, RVV
188 /*
189 #if defined(__SSE4_2__)
190 #include <nmmintrin.h>
191 #define RAYMATH_SSE42_ENABLED
192 #elif defined(__SSE4_1__)
193 #include <smmintrin.h>
194 #define RAYMATH_SSE41_ENABLED
195 #elif defined(__SSSE3__)
196 #include <tmmintrin.h>
197 #define RAYMATH_SSSE3_ENABLED
198 #elif defined(__SSE3__)
199 #include <pmmintrin.h>
200 #define RAYMATH_SSE3_ENABLED
201 #elif defined(__SSE2__) || (defined(_M_AMD64) || defined(_M_X64)) // SSE2 x64
202 #include <emmintrin.h>
203 #define RAYMATH_SSE2_ENABLED
204 #endif
205 */
206 #if defined(__SSE__) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1))
207 #include <xmmintrin.h>
208 #define RAYMATH_SSE_ENABLED
209 #endif
210 #endif
172 211
173 //---------------------------------------------------------------------------------- 212 //----------------------------------------------------------------------------------
174 // Module Functions Definition - Utils math 213 // Module Functions Definition - Utils math
175 //---------------------------------------------------------------------------------- 214 //----------------------------------------------------------------------------------
176 215
302 float result = (v1.x*v2.x + v1.y*v2.y); 341 float result = (v1.x*v2.x + v1.y*v2.y);
303 342
304 return result; 343 return result;
305 } 344 }
306 345
346 // Calculate two vectors cross product
347 RMAPI float Vector2CrossProduct(Vector2 v1, Vector2 v2)
348 {
349 float result = (v1.x*v2.y - v1.y*v2.x);
350
351 return result;
352 }
353
307 // Calculate distance between two vectors 354 // Calculate distance between two vectors
308 RMAPI float Vector2Distance(Vector2 v1, Vector2 v2) 355 RMAPI float Vector2Distance(Vector2 v1, Vector2 v2)
309 { 356 {
310 float result = sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); 357 float result = sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y));
311 358
318 float result = ((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); 365 float result = ((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y));
319 366
320 return result; 367 return result;
321 } 368 }
322 369
323 // Calculate angle between two vectors 370 // Calculate the signed angle from v1 to v2, relative to the origin (0, 0)
324 // NOTE: Angle is calculated from origin point (0, 0) 371 // NOTE: Coordinate system convention: positive X right, positive Y down
372 // positive angles appear clockwise, and negative angles appear counterclockwise
325 RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) 373 RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
326 { 374 {
327 float result = 0.0f; 375 float result = 0.0f;
328 376
329 float dot = v1.x*v2.x + v1.y*v2.y; 377 float dot = v1.x*v2.x + v1.y*v2.y;
517 float length = (v.x*v.x) + (v.y*v.y); 565 float length = (v.x*v.x) + (v.y*v.y);
518 if (length > 0.0f) 566 if (length > 0.0f)
519 { 567 {
520 length = sqrtf(length); 568 length = sqrtf(length);
521 569
522 float scale = 1; // By default, 1 as the neutral element. 570 float scale = 1; // By default, 1 as the neutral element
523 if (length < min) 571 if (length < min) scale = min/length;
524 { 572 else if (length > max) scale = max/length;
525 scale = min/length;
526 }
527 else if (length > max)
528 {
529 scale = max/length;
530 }
531 573
532 result.x = v.x*scale; 574 result.x = v.x*scale;
533 result.y = v.y*scale; 575 result.y = v.y*scale;
534 } 576 }
535 577
551 593
552 // Compute the direction of a refracted ray 594 // Compute the direction of a refracted ray
553 // v: normalized direction of the incoming ray 595 // v: normalized direction of the incoming ray
554 // n: normalized normal vector of the interface of two optical media 596 // n: normalized normal vector of the interface of two optical media
555 // r: ratio of the refractive index of the medium from where the ray comes 597 // r: ratio of the refractive index of the medium from where the ray comes
556 // to the refractive index of the medium on the other side of the surface 598 // to the refractive index of the medium on the other side of the surface
557 RMAPI Vector2 Vector2Refract(Vector2 v, Vector2 n, float r) 599 RMAPI Vector2 Vector2Refract(Vector2 v, Vector2 n, float r)
558 { 600 {
559 Vector2 result = { 0 }; 601 Vector2 result = { 0 };
560 602
561 float dot = v.x*n.x + v.y*n.y; 603 float dot = v.x*n.x + v.y*n.y;
1039 1081
1040 return result; 1082 return result;
1041 } 1083 }
1042 1084
1043 // Projects a Vector3 from screen space into object space 1085 // Projects a Vector3 from screen space into object space
1044 // NOTE: We are avoiding calling other raymath functions despite available 1086 // NOTE: Self-contained function, no other raymath functions are called
1045 RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view) 1087 RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view)
1046 { 1088 {
1047 Vector3 result = { 0 }; 1089 Vector3 result = { 0 };
1048 1090
1049 // Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it 1091 // Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it
1107 (a20*b03 - a21*b01 + a22*b00)*invDet }; 1149 (a20*b03 - a21*b01 + a22*b00)*invDet };
1108 1150
1109 // Create quaternion from source point 1151 // Create quaternion from source point
1110 Quaternion quat = { source.x, source.y, source.z, 1.0f }; 1152 Quaternion quat = { source.x, source.y, source.z, 1.0f };
1111 1153
1112 // Multiply quat point by unprojecte matrix 1154 // Multiply quat point by unprojected matrix
1113 Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv) 1155 Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv)
1114 matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w, 1156 matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w,
1115 matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w, 1157 matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w,
1116 matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w, 1158 matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w,
1117 matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w }; 1159 matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w };
1165 float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z); 1207 float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z);
1166 if (length > 0.0f) 1208 if (length > 0.0f)
1167 { 1209 {
1168 length = sqrtf(length); 1210 length = sqrtf(length);
1169 1211
1170 float scale = 1; // By default, 1 as the neutral element. 1212 float scale = 1; // By default, 1 as the neutral element
1171 if (length < min) 1213 if (length < min) scale = min/length;
1172 { 1214 else if (length > max) scale = max/length;
1173 scale = min/length;
1174 }
1175 else if (length > max)
1176 {
1177 scale = max/length;
1178 }
1179 1215
1180 result.x = v.x*scale; 1216 result.x = v.x*scale;
1181 result.y = v.y*scale; 1217 result.y = v.y*scale;
1182 result.z = v.z*scale; 1218 result.z = v.z*scale;
1183 } 1219 }
1201 1237
1202 // Compute the direction of a refracted ray 1238 // Compute the direction of a refracted ray
1203 // v: normalized direction of the incoming ray 1239 // v: normalized direction of the incoming ray
1204 // n: normalized normal vector of the interface of two optical media 1240 // n: normalized normal vector of the interface of two optical media
1205 // r: ratio of the refractive index of the medium from where the ray comes 1241 // r: ratio of the refractive index of the medium from where the ray comes
1206 // to the refractive index of the medium on the other side of the surface 1242 // to the refractive index of the medium on the other side of the surface
1207 RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r) 1243 RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r)
1208 { 1244 {
1209 Vector3 result = { 0 }; 1245 Vector3 result = { 0 };
1210 1246
1211 float dot = v.x*n.x + v.y*n.y + v.z*n.z; 1247 float dot = v.x*n.x + v.y*n.y + v.z*n.z;
1226 1262
1227 1263
1228 //---------------------------------------------------------------------------------- 1264 //----------------------------------------------------------------------------------
1229 // Module Functions Definition - Vector4 math 1265 // Module Functions Definition - Vector4 math
1230 //---------------------------------------------------------------------------------- 1266 //----------------------------------------------------------------------------------
1231 1267 // Get vector zero
1232 RMAPI Vector4 Vector4Zero(void) 1268 RMAPI Vector4 Vector4Zero(void)
1233 { 1269 {
1234 Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f }; 1270 Vector4 result = { 0.0f, 0.0f, 0.0f, 0.0f };
1235 return result; 1271 return result;
1236 } 1272 }
1237 1273
1274 // Get vector one
1238 RMAPI Vector4 Vector4One(void) 1275 RMAPI Vector4 Vector4One(void)
1239 { 1276 {
1240 Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f }; 1277 Vector4 result = { 1.0f, 1.0f, 1.0f, 1.0f };
1241 return result; 1278 return result;
1242 } 1279 }
1243 1280
1281 // Add two vectors
1244 RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2) 1282 RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2)
1245 { 1283 {
1246 Vector4 result = { 1284 Vector4 result = {
1247 v1.x + v2.x, 1285 v1.x + v2.x,
1248 v1.y + v2.y, 1286 v1.y + v2.y,
1250 v1.w + v2.w 1288 v1.w + v2.w
1251 }; 1289 };
1252 return result; 1290 return result;
1253 } 1291 }
1254 1292
1293 // Add value to vector components
1255 RMAPI Vector4 Vector4AddValue(Vector4 v, float add) 1294 RMAPI Vector4 Vector4AddValue(Vector4 v, float add)
1256 { 1295 {
1257 Vector4 result = { 1296 Vector4 result = {
1258 v.x + add, 1297 v.x + add,
1259 v.y + add, 1298 v.y + add,
1261 v.w + add 1300 v.w + add
1262 }; 1301 };
1263 return result; 1302 return result;
1264 } 1303 }
1265 1304
1305 // Substract vectors
1266 RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2) 1306 RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2)
1267 { 1307 {
1268 Vector4 result = { 1308 Vector4 result = {
1269 v1.x - v2.x, 1309 v1.x - v2.x,
1270 v1.y - v2.y, 1310 v1.y - v2.y,
1272 v1.w - v2.w 1312 v1.w - v2.w
1273 }; 1313 };
1274 return result; 1314 return result;
1275 } 1315 }
1276 1316
1317 // Substract value from vector components
1277 RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add) 1318 RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add)
1278 { 1319 {
1279 Vector4 result = { 1320 Vector4 result = {
1280 v.x - add, 1321 v.x - add,
1281 v.y - add, 1322 v.y - add,
1283 v.w - add 1324 v.w - add
1284 }; 1325 };
1285 return result; 1326 return result;
1286 } 1327 }
1287 1328
1329 // Vector length
1288 RMAPI float Vector4Length(Vector4 v) 1330 RMAPI float Vector4Length(Vector4 v)
1289 { 1331 {
1290 float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w)); 1332 float result = sqrtf((v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w));
1291 return result; 1333 return result;
1292 } 1334 }
1293 1335
1336 // Vector square length
1294 RMAPI float Vector4LengthSqr(Vector4 v) 1337 RMAPI float Vector4LengthSqr(Vector4 v)
1295 { 1338 {
1296 float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w); 1339 float result = (v.x*v.x) + (v.y*v.y) + (v.z*v.z) + (v.w*v.w);
1297 return result; 1340 return result;
1298 } 1341 }
1299 1342
1343 // Vectors dot product
1300 RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2) 1344 RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2)
1301 { 1345 {
1302 float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w); 1346 float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w);
1303 return result; 1347 return result;
1304 } 1348 }
1320 (v1.z - v2.z)*(v1.z - v2.z) + (v1.w - v2.w)*(v1.w - v2.w); 1364 (v1.z - v2.z)*(v1.z - v2.z) + (v1.w - v2.w)*(v1.w - v2.w);
1321 1365
1322 return result; 1366 return result;
1323 } 1367 }
1324 1368
1369 // Scale vector components by value (multiply)
1325 RMAPI Vector4 Vector4Scale(Vector4 v, float scale) 1370 RMAPI Vector4 Vector4Scale(Vector4 v, float scale)
1326 { 1371 {
1327 Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale }; 1372 Vector4 result = { v.x*scale, v.y*scale, v.z*scale, v.w*scale };
1328 return result; 1373 return result;
1329 } 1374 }
1457 1502
1458 // Compute matrix determinant 1503 // Compute matrix determinant
1459 RMAPI float MatrixDeterminant(Matrix mat) 1504 RMAPI float MatrixDeterminant(Matrix mat)
1460 { 1505 {
1461 float result = 0.0f; 1506 float result = 0.0f;
1462 1507 /*
1463 // Cache the matrix values (speed optimization) 1508 // Cache the matrix values (speed optimization)
1464 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; 1509 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
1465 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; 1510 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
1466 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; 1511 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
1467 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; 1512 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
1468 1513
1514 // NOTE: It takes 72 multiplication to calculate 4x4 matrix determinant
1469 result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 + 1515 result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
1470 a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 + 1516 a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
1471 a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 + 1517 a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
1472 a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 + 1518 a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
1473 a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 + 1519 a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
1474 a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33; 1520 a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
1521 */
1522 // Using Laplace expansion (https://en.wikipedia.org/wiki/Laplace_expansion),
1523 // previous operation can be simplified to 40 multiplications, decreasing matrix
1524 // size from 4x4 to 2x2 using minors
1525
1526 // Cache the matrix values (speed optimization)
1527 float m0 = mat.m0, m1 = mat.m1, m2 = mat.m2, m3 = mat.m3;
1528 float m4 = mat.m4, m5 = mat.m5, m6 = mat.m6, m7 = mat.m7;
1529 float m8 = mat.m8, m9 = mat.m9, m10 = mat.m10, m11 = mat.m11;
1530 float m12 = mat.m12, m13 = mat.m13, m14 = mat.m14, m15 = mat.m15;
1531
1532 result = (m0*((m5*(m10*m15 - m11*m14) - m9*(m6*m15 - m7*m14) + m13*(m6*m11 - m7*m10))) -
1533 m4*((m1*(m10*m15 - m11*m14) - m9*(m2*m15 - m3*m14) + m13*(m2*m11 - m3*m10))) +
1534 m8*((m1*(m6*m15 - m7*m14) - m5*(m2*m15 - m3*m14) + m13*(m2*m7 - m3*m6))) -
1535 m12*((m1*(m6*m11 - m7*m10) - m5*(m2*m11 - m3*m10) + m9*(m2*m7 - m3*m6))));
1475 1536
1476 return result; 1537 return result;
1477 } 1538 }
1478 1539
1479 // Get the trace of the matrix (sum of the values along the diagonal) 1540 // Get the trace of the matrix (sum of the values along the diagonal)
1621 // NOTE: When multiplying matrices... the order matters! 1682 // NOTE: When multiplying matrices... the order matters!
1622 RMAPI Matrix MatrixMultiply(Matrix left, Matrix right) 1683 RMAPI Matrix MatrixMultiply(Matrix left, Matrix right)
1623 { 1684 {
1624 Matrix result = { 0 }; 1685 Matrix result = { 0 };
1625 1686
1687 #if defined(RAYMATH_SSE_ENABLED)
1688 // Load left side and right side
1689 __m128 c0 = _mm_set_ps(right.m12, right.m8, right.m4, right.m0);
1690 __m128 c1 = _mm_set_ps(right.m13, right.m9, right.m5, right.m1);
1691 __m128 c2 = _mm_set_ps(right.m14, right.m10, right.m6, right.m2);
1692 __m128 c3 = _mm_set_ps(right.m15, right.m11, right.m7, right.m3);
1693
1694 // Transpose so c0..c3 become *rows* of the right matrix in semantic order
1695 _MM_TRANSPOSE4_PS(c0, c1, c2, c3);
1696
1697 float tmp[4] = { 0 };
1698 __m128 row;
1699
1700 // Row 0 of result: [m0, m1, m2, m3]
1701 row = _mm_mul_ps(_mm_set1_ps(left.m0), c0);
1702 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m1), c1));
1703 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m2), c2));
1704 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m3), c3));
1705 _mm_storeu_ps(tmp, row);
1706 result.m0 = tmp[0];
1707 result.m1 = tmp[1];
1708 result.m2 = tmp[2];
1709 result.m3 = tmp[3];
1710
1711 // Row 1 of result: [m4, m5, m6, m7]
1712 row = _mm_mul_ps(_mm_set1_ps(left.m4), c0);
1713 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m5), c1));
1714 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m6), c2));
1715 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m7), c3));
1716 _mm_storeu_ps(tmp, row);
1717 result.m4 = tmp[0];
1718 result.m5 = tmp[1];
1719 result.m6 = tmp[2];
1720 result.m7 = tmp[3];
1721
1722 // Row 2 of result: [m8, m9, m10, m11]
1723 row = _mm_mul_ps(_mm_set1_ps(left.m8), c0);
1724 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m9), c1));
1725 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m10), c2));
1726 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m11), c3));
1727 _mm_storeu_ps(tmp, row);
1728 result.m8 = tmp[0];
1729 result.m9 = tmp[1];
1730 result.m10 = tmp[2];
1731 result.m11 = tmp[3];
1732
1733 // Row 3 of result: [m12, m13, m14, m15]
1734 row = _mm_mul_ps(_mm_set1_ps(left.m12), c0);
1735 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m13), c1));
1736 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m14), c2));
1737 row = _mm_add_ps(row, _mm_mul_ps(_mm_set1_ps(left.m15), c3));
1738 _mm_storeu_ps(tmp, row);
1739 result.m12 = tmp[0];
1740 result.m13 = tmp[1];
1741 result.m14 = tmp[2];
1742 result.m15 = tmp[3];
1743 #else
1626 result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; 1744 result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12;
1627 result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; 1745 result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13;
1628 result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; 1746 result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14;
1629 result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; 1747 result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15;
1630 result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; 1748 result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12;
1637 result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; 1755 result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15;
1638 result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; 1756 result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12;
1639 result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; 1757 result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13;
1640 result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; 1758 result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14;
1641 result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; 1759 result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15;
1760 #endif
1761
1762 return result;
1763 }
1764
1765 // Multiply matrix components by value
1766 RMAPI Matrix MatrixMultiplyValue(Matrix left, float value)
1767 {
1768 Matrix result = {
1769 left.m0*value, left.m4*value, left.m8*value, left.m12*value,
1770 left.m1*value, left.m5*value, left.m9*value, left.m13*value,
1771 left.m2*value, left.m6*value, left.m10*value, left.m14*value,
1772 left.m3*value, left.m7*value, left.m11*value, left.m15*value
1773 };
1642 1774
1643 return result; 1775 return result;
1644 } 1776 }
1645 1777
1646 // Get translation matrix 1778 // Get translation matrix
2245 // Calculate quaternion based on the rotation from one vector to another 2377 // Calculate quaternion based on the rotation from one vector to another
2246 RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) 2378 RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to)
2247 { 2379 {
2248 Quaternion result = { 0 }; 2380 Quaternion result = { 0 };
2249 2381
2250 float cos2Theta = (from.x*to.x + from.y*to.y + from.z*to.z); // Vector3DotProduct(from, to) 2382 float cos2Theta = (from.x*to.x + from.y*to.y + from.z*to.z); // Vector3DotProduct(from, to)
2251 Vector3 cross = { from.y*to.z - from.z*to.y, from.z*to.x - from.x*to.z, from.x*to.y - from.y*to.x }; // Vector3CrossProduct(from, to) 2383 Vector3 cross = { from.y*to.z - from.z*to.y, from.z*to.x - from.x*to.z, from.x*to.y - from.y*to.x }; // Vector3CrossProduct(from, to)
2252 2384
2253 result.x = cross.x; 2385 result.x = cross.x;
2254 result.y = cross.y; 2386 result.y = cross.y;
2255 result.z = cross.z; 2387 result.z = cross.z;
2256 result.w = 1.0f + cos2Theta; 2388 result.w = sqrtf(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z + cos2Theta*cos2Theta) + cos2Theta;
2257 2389
2258 // QuaternionNormalize(q); 2390 // QuaternionNormalize(q);
2259 // NOTE: Normalize to essentially nlerp the original and identity to 0.5 2391 // NOTE: Normalize to essentially nlerp the original and identity to 0.5
2260 Quaternion q = result; 2392 Quaternion q = result;
2261 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 2393 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w);
2371 // NOTE: Angle must be provided in radians 2503 // NOTE: Angle must be provided in radians
2372 RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) 2504 RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle)
2373 { 2505 {
2374 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; 2506 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
2375 2507
2376 float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); 2508 float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z);
2377 2509
2378 if (axisLength != 0.0f) 2510 if (length != 0.0f)
2379 { 2511 {
2380 angle *= 0.5f; 2512 angle *= 0.5f;
2381 2513
2382 float length = 0.0f;
2383 float ilength = 0.0f;
2384
2385 // Vector3Normalize(axis) 2514 // Vector3Normalize(axis)
2386 length = axisLength; 2515 float ilength = 1.0f/length;
2387 if (length == 0.0f) length = 1.0f;
2388 ilength = 1.0f/length;
2389 axis.x *= ilength; 2516 axis.x *= ilength;
2390 axis.y *= ilength; 2517 axis.y *= ilength;
2391 axis.z *= ilength; 2518 axis.z *= ilength;
2392 2519
2393 float sinres = sinf(angle); 2520 float sinres = sinf(angle);
2438 resAxis.y = q.y/den; 2565 resAxis.y = q.y/den;
2439 resAxis.z = q.z/den; 2566 resAxis.z = q.z/den;
2440 } 2567 }
2441 else 2568 else
2442 { 2569 {
2443 // This occurs when the angle is zero. 2570 // This occurs when the angle is zero
2444 // Not a problem: just set an arbitrary normalized axis. 2571 // Not a problem, set an arbitrary normalized axis
2445 resAxis.x = 1.0f; 2572 resAxis.x = 1.0f;
2446 } 2573 }
2447 2574
2448 *outAxis = resAxis; 2575 *outAxis = resAxis;
2449 *outAngle = resAngle; 2576 *outAngle = resAngle;
2525 ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))); 2652 ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w))))));
2526 2653
2527 return result; 2654 return result;
2528 } 2655 }
2529 2656
2530 // Decompose a transformation matrix into its rotational, translational and scaling components 2657 // Compose a transformation matrix from rotational, translational and scaling components
2658 // TODO: This function is not following raymath conventions defined in header: NOT self-contained
2659 RMAPI Matrix MatrixCompose(Vector3 translation, Quaternion rotation, Vector3 scale)
2660 {
2661 // Initialize vectors
2662 Vector3 right = { 1.0f, 0.0f, 0.0f };
2663 Vector3 up = { 0.0f, 1.0f, 0.0f };
2664 Vector3 forward = { 0.0f, 0.0f, 1.0f };
2665
2666 // Scale vectors
2667 right = Vector3Scale(right, scale.x);
2668 up = Vector3Scale(up, scale.y);
2669 forward = Vector3Scale(forward , scale.z);
2670
2671 // Rotate vectors
2672 right = Vector3RotateByQuaternion(right, rotation);
2673 up = Vector3RotateByQuaternion(up, rotation);
2674 forward = Vector3RotateByQuaternion(forward, rotation);
2675
2676 // Set result matrix output
2677 Matrix result = {
2678 right.x, up.x, forward.x, translation.x,
2679 right.y, up.y, forward.y, translation.y,
2680 right.z, up.z, forward.z, translation.z,
2681 0.0f, 0.0f, 0.0f, 1.0f
2682 };
2683
2684 return result;
2685 }
2686
2687 // Decompose a transformation matrix into its rotational, translational and scaling components and remove shear
2688 // TODO: This function is not following raymath conventions defined in header: NOT self-contained
2531 RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotation, Vector3 *scale) 2689 RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotation, Vector3 *scale)
2532 { 2690 {
2533 // Extract translation. 2691 float eps = (float)1e-9;
2692
2693 // Extract Translation
2534 translation->x = mat.m12; 2694 translation->x = mat.m12;
2535 translation->y = mat.m13; 2695 translation->y = mat.m13;
2536 translation->z = mat.m14; 2696 translation->z = mat.m14;
2537 2697
2538 // Extract upper-left for determinant computation 2698 // Matrix Columns - Rotation will be extracted into here
2539 const float a = mat.m0; 2699 Vector3 matColumns[3] = {{ mat.m0, mat.m4, mat.m8 },
2540 const float b = mat.m4; 2700 { mat.m1, mat.m5, mat.m9 },
2541 const float c = mat.m8; 2701 { mat.m2, mat.m6, mat.m10 }};
2542 const float d = mat.m1; 2702
2543 const float e = mat.m5; 2703 // Shear Parameters XY, XZ, and YZ (extract and ignored)
2544 const float f = mat.m9; 2704 float shear[3] = { 0 };
2545 const float g = mat.m2; 2705
2546 const float h = mat.m6; 2706 // Normalized Scale Parameters
2547 const float i = mat.m10; 2707 Vector3 scl = { 0 };
2548 const float A = e*i - f*h; 2708
2549 const float B = f*g - d*i; 2709 // Max-Normalizing helps numerical stability
2550 const float C = d*h - e*g; 2710 float stabilizer = eps;
2551 2711 for (int i = 0; i < 3; i++)
2552 // Extract scale
2553 const float det = a*A + b*B + c*C;
2554 Vector3 abc = { a, b, c };
2555 Vector3 def = { d, e, f };
2556 Vector3 ghi = { g, h, i };
2557
2558 float scalex = Vector3Length(abc);
2559 float scaley = Vector3Length(def);
2560 float scalez = Vector3Length(ghi);
2561 Vector3 s = { scalex, scaley, scalez };
2562
2563 if (det < 0) s = Vector3Negate(s);
2564
2565 *scale = s;
2566
2567 // Remove scale from the matrix if it is not close to zero
2568 Matrix clone = mat;
2569 if (!FloatEquals(det, 0))
2570 { 2712 {
2571 clone.m0 /= s.x; 2713 stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].x));
2572 clone.m4 /= s.x; 2714 stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].y));
2573 clone.m8 /= s.x; 2715 stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].z));
2574 clone.m1 /= s.y;
2575 clone.m5 /= s.y;
2576 clone.m9 /= s.y;
2577 clone.m2 /= s.z;
2578 clone.m6 /= s.z;
2579 clone.m10 /= s.z;
2580
2581 // Extract rotation
2582 *rotation = QuaternionFromMatrix(clone);
2583 } 2716 }
2584 else 2717 matColumns[0] = Vector3Scale(matColumns[0], 1.0f / stabilizer);
2718 matColumns[1] = Vector3Scale(matColumns[1], 1.0f / stabilizer);
2719 matColumns[2] = Vector3Scale(matColumns[2], 1.0f / stabilizer);
2720
2721 // X Scale
2722 scl.x = Vector3Length(matColumns[0]);
2723 if (scl.x > eps) matColumns[0] = Vector3Scale(matColumns[0], 1.0f / scl.x);
2724
2725 // Compute XY shear and make col2 orthogonal
2726 shear[0] = Vector3DotProduct(matColumns[0], matColumns[1]);
2727 matColumns[1] = Vector3Subtract(matColumns[1], Vector3Scale(matColumns[0], shear[0]));
2728
2729 // Y Scale
2730 scl.y = Vector3Length(matColumns[1]);
2731 if (scl.y > eps)
2585 { 2732 {
2586 // Set to identity if close to zero 2733 matColumns[1] = Vector3Scale(matColumns[1], 1.0f / scl.y);
2587 *rotation = QuaternionIdentity(); 2734 shear[0] /= scl.y; // Correct XY shear
2588 } 2735 }
2736
2737 // Compute XZ and YZ shears and make col3 orthogonal
2738 shear[1] = Vector3DotProduct(matColumns[0], matColumns[2]);
2739 matColumns[2] = Vector3Subtract(matColumns[2], Vector3Scale(matColumns[0], shear[1]));
2740 shear[2] = Vector3DotProduct(matColumns[1], matColumns[2]);
2741 matColumns[2] = Vector3Subtract(matColumns[2], Vector3Scale(matColumns[1], shear[2]));
2742
2743 // Z Scale
2744 scl.z = Vector3Length(matColumns[2]);
2745 if (scl.z > eps)
2746 {
2747 matColumns[2] = Vector3Scale(matColumns[2], 1.0f / scl.z);
2748 shear[1] /= scl.z; // Correct XZ shear
2749 shear[2] /= scl.z; // Correct YZ shear
2750 }
2751
2752 // matColumns are now orthonormal in O(3). Now ensure its in SO(3) by enforcing det = 1
2753 if (Vector3DotProduct(matColumns[0], Vector3CrossProduct(matColumns[1], matColumns[2])) < 0)
2754 {
2755 scl = Vector3Negate(scl);
2756 matColumns[0] = Vector3Negate(matColumns[0]);
2757 matColumns[1] = Vector3Negate(matColumns[1]);
2758 matColumns[2] = Vector3Negate(matColumns[2]);
2759 }
2760
2761 // Set Scale
2762 *scale = Vector3Scale(scl, stabilizer);
2763
2764 // Extract Rotation
2765 Matrix rotationMatrix = { matColumns[0].x, matColumns[0].y, matColumns[0].z, 0,
2766 matColumns[1].x, matColumns[1].y, matColumns[1].z, 0,
2767 matColumns[2].x, matColumns[2].y, matColumns[2].z, 0,
2768 0, 0, 0, 1 };
2769 *rotation = QuaternionFromMatrix(rotationMatrix);
2589 } 2770 }
2590 2771
2591 #if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS) 2772 #if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS)
2592 2773
2593 // Optional C++ math operators 2774 // Optional C++ math operators
2646 inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs) 2827 inline Vector2 operator * (const Vector2& lhs, const Matrix& rhs)
2647 { 2828 {
2648 return Vector2Transform(lhs, rhs); 2829 return Vector2Transform(lhs, rhs);
2649 } 2830 }
2650 2831
2651 inline const Vector2& operator -= (Vector2& lhs, const Matrix& rhs) 2832 inline const Vector2& operator *= (Vector2& lhs, const Matrix& rhs)
2652 { 2833 {
2653 lhs = Vector2Transform(lhs, rhs); 2834 lhs = Vector2Transform(lhs, rhs);
2654 return lhs; 2835 return lhs;
2655 } 2836 }
2656 2837
2657 inline Vector2 operator / (const Vector2& lhs, const float& rhs) 2838 inline Vector2 operator / (const Vector2& lhs, const float& rhs)
2658 { 2839 {
2659 return Vector2Scale(lhs, 1.0f / rhs); 2840 return Vector2Scale(lhs, 1.0f/rhs);
2660 } 2841 }
2661 2842
2662 inline const Vector2& operator /= (Vector2& lhs, const float& rhs) 2843 inline const Vector2& operator /= (Vector2& lhs, const float& rhs)
2663 { 2844 {
2664 lhs = Vector2Scale(lhs, rhs); 2845 lhs = Vector2Scale(lhs, 1.0f/rhs);
2665 return lhs; 2846 return lhs;
2666 } 2847 }
2667 2848
2668 inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs) 2849 inline Vector2 operator / (const Vector2& lhs, const Vector2& rhs)
2669 { 2850 {
2740 inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs) 2921 inline Vector3 operator * (const Vector3& lhs, const Matrix& rhs)
2741 { 2922 {
2742 return Vector3Transform(lhs, rhs); 2923 return Vector3Transform(lhs, rhs);
2743 } 2924 }
2744 2925
2745 inline const Vector3& operator -= (Vector3& lhs, const Matrix& rhs) 2926 inline const Vector3& operator *= (Vector3& lhs, const Matrix& rhs)
2746 { 2927 {
2747 lhs = Vector3Transform(lhs, rhs); 2928 lhs = Vector3Transform(lhs, rhs);
2748 return lhs; 2929 return lhs;
2749 } 2930 }
2750 2931
2751 inline Vector3 operator / (const Vector3& lhs, const float& rhs) 2932 inline Vector3 operator / (const Vector3& lhs, const float& rhs)
2752 { 2933 {
2753 return Vector3Scale(lhs, 1.0f / rhs); 2934 return Vector3Scale(lhs, 1.0f/rhs);
2754 } 2935 }
2755 2936
2756 inline const Vector3& operator /= (Vector3& lhs, const float& rhs) 2937 inline const Vector3& operator /= (Vector3& lhs, const float& rhs)
2757 { 2938 {
2758 lhs = Vector3Scale(lhs, rhs); 2939 lhs = Vector3Scale(lhs, 1.0f/rhs);
2759 return lhs; 2940 return lhs;
2760 } 2941 }
2761 2942
2762 inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs) 2943 inline Vector3 operator / (const Vector3& lhs, const Vector3& rhs)
2763 { 2944 {
2832 return lhs; 3013 return lhs;
2833 } 3014 }
2834 3015
2835 inline Vector4 operator / (const Vector4& lhs, const float& rhs) 3016 inline Vector4 operator / (const Vector4& lhs, const float& rhs)
2836 { 3017 {
2837 return Vector4Scale(lhs, 1.0f / rhs); 3018 return Vector4Scale(lhs, 1.0f/rhs);
2838 } 3019 }
2839 3020
2840 inline const Vector4& operator /= (Vector4& lhs, const float& rhs) 3021 inline const Vector4& operator /= (Vector4& lhs, const float& rhs)
2841 { 3022 {
2842 lhs = Vector4Scale(lhs, rhs); 3023 lhs = Vector4Scale(lhs, 1.0f/rhs);
2843 return lhs; 3024 return lhs;
2844 } 3025 }
2845 3026
2846 inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs) 3027 inline Vector4 operator / (const Vector4& lhs, const Vector4& rhs)
2847 { 3028 {
2901 lhs = QuaternionTransform(lhs, rhs); 3082 lhs = QuaternionTransform(lhs, rhs);
2902 return lhs; 3083 return lhs;
2903 } 3084 }
2904 3085
2905 // Matrix operators 3086 // Matrix operators
3087 static constexpr Matrix MatrixUnit = { 1, 0, 0, 0,
3088 0, 1, 0, 0,
3089 0, 0, 1, 0,
3090 0, 0, 0, 1 };
3091
2906 inline Matrix operator + (const Matrix& lhs, const Matrix& rhs) 3092 inline Matrix operator + (const Matrix& lhs, const Matrix& rhs)
2907 { 3093 {
2908 return MatrixAdd(lhs, rhs); 3094 return MatrixAdd(lhs, rhs);
2909 } 3095 }
2910 3096
2933 inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs) 3119 inline const Matrix& operator *= (Matrix& lhs, const Matrix& rhs)
2934 { 3120 {
2935 lhs = MatrixMultiply(lhs, rhs); 3121 lhs = MatrixMultiply(lhs, rhs);
2936 return lhs; 3122 return lhs;
2937 } 3123 }
3124
3125 inline Matrix operator * (const Matrix& lhs, const float value)
3126 {
3127 return MatrixMultiplyValue(lhs, value);
3128 }
3129
3130 inline const Matrix& operator *= (Matrix& lhs, const float value)
3131 {
3132 lhs = MatrixMultiplyValue(lhs, value);
3133 return lhs;
3134 }
3135
2938 //------------------------------------------------------------------------------- 3136 //-------------------------------------------------------------------------------
2939 #endif // C++ operators 3137 #endif // C++ operators
2940 3138
2941 #endif // RAYMATH_H 3139 #endif // RAYMATH_H