Mercurial
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 |