├── README.md ├── LICENSE └── dvector.h /README.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | This is a header-only library, as such most of its functional documentation is contained within the "header section" of the 4 | source code in the form of comments. It is highly recommended that you read said documentation before using this library. 5 | 6 | ## Features 7 | 8 | The dvector library provides both common and more specialized 2D/3D vector math operations, its features include: 9 | 10 | - No hard dependencies besides the standard library, making it fully portable for most purposes 11 | - Provides vec2, vec3, vec4, quat, mat2, mat3, and mat4 types with various important operations 12 | - Supports an additional frst type along with frustum culling functions for spheres and AABBs 13 | - All dvector types are pass-by-value, allowing for easy use as arguments or return values 14 | 15 | ## Attribution 16 | 17 | You are not required to give attribution when using this library. If you want to give attribution anyway, either link to 18 | this repository, [my website](https://www.slopegames.com/), or credit me as [BareRose](https://github.com/BareRose). 19 | If you want to support me financially, consider giving to my [Patreon](https://www.patreon.com/slopegames). 20 | 21 | ## License 22 | 23 | Licensed under CC0 aka the most lawyer-friendly way of spelling "public domain". -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /dvector.h: -------------------------------------------------------------------------------- 1 | /* 2 | dvector.h - Portable, single-file, 2D/3D vector/quaternion/matrix math library, originally based on ccVector 3 | 4 | To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring 5 | rights to this software to the public domain worldwide. This software is distributed without any warranty. 6 | You should have received a copy of the CC0 Public Domain Dedication along with this software. 7 | If not, see . 8 | */ 9 | 10 | /* 11 | dvector supports the following three configurations: 12 | #define DVECTOR_EXTERN 13 | Default, should be used when using dvector in multiple compilation units within the same project. 14 | #define DVECTOR_IMPLEMENTATION 15 | Must be defined in exactly one source file within a project for dvector to be found by the linker. 16 | #define DVECTOR_STATIC 17 | Defines all dvector functions as static, useful if dvector is only used in a single compilation unit. 18 | 19 | dvector supports the following additional options: 20 | #define DVECTOR_DOUBLE 21 | Configures dvector to use double instead of the default float. Cannot use both float and double versions in the same compilation unit. 22 | #define DVECTOR_ISOC 23 | Changes the way dvector types are defined for compatibility with ISO C99. Only affects convenience without limiting functionality. 24 | 25 | dvector types: 26 | Supports vec2, vec3, vec4, quat, mat2, mat3, and mat4 types with various property aliases for flexible use and concise code. 27 | Each of the above types comes with a TYPE_ZERO and TYPE_IDEN (for quat and matrix types) constant which translates to a literal. 28 | Function-like macros of the form TYPE(...) also exist and are meant to provide a concise alternative to typing out literals. 29 | The auxiliary frst type supports frustum generation from a projview matrix and simple frustum culling of bounding volumes. 30 | 31 | dvector functions: 32 | Provided functions should be reasonably self-explanatory, and use of macros was deliberately kept low for better readability. 33 | All equality functions use direct comparison (no epsilon), therefore floating point errors may break equality for some values. 34 | All quat functions should return normalized quats, occasional normalization is recommended due to float error accumulation. 35 | All angles are in radians. Frustum culling of volumes returns 1 for volumes inside the frustum, 0 for volumes outside it. 36 | All coordinate systems are right-handed unless otherwise noted. Projection functions assume OpenGL-style screen space. 37 | */ 38 | 39 | //header section 40 | #ifndef DVECTOR_H 41 | #define DVECTOR_H 42 | 43 | //process configuration 44 | #ifdef DVECTOR_STATIC 45 | #define DVECTOR_IMPLEMENTATION 46 | #define DVDEF static 47 | #else //DVECTOR_EXTERN 48 | #define DVDEF extern 49 | #endif 50 | 51 | /* 52 | Use the below macros and constants for function parameters and variable 53 | definitions in local scope. To initialize globals, use naked literals. 54 | Example: 55 | vec3 default_position = {0, 0, 0}; 56 | void foo(){ 57 | bar(VEC3_ZERO); 58 | } 59 | */ 60 | 61 | //macros 62 | #ifdef DVECTOR_ISOC 63 | #define VEC2(X, Y) (vec2){X, Y} 64 | #define VEC3(X, Y, Z) (vec3){X, Y, Z} 65 | #define VEC4(X, Y, Z, W) (vec4){X, Y, Z, W} 66 | #define QUAT(X, Y, Z, W) (quat){X, Y, Z, W} 67 | #else 68 | #define VEC2(X, Y) (vec2){{X, Y}} 69 | #define VEC3(X, Y, Z) (vec3){{X, Y, Z}} 70 | #define VEC4(X, Y, Z, W) (vec4){{X, Y, Z, W}} 71 | #define QUAT(X, Y, Z, W) (quat){{X, Y, Z, W}} 72 | #endif 73 | #define MAT2(M00, M01, M10, M11) (mat2){{{M00, M01}, {M10, M11}}} 74 | #define MAT3(M00, M01, M02, M10, M11, M12, M20, M21, M22) (mat3){{{M00, M01, M02}, {M10, M11, M12}, {M20, M21, M22}}} 75 | #define MAT4(M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33) \ 76 | (mat4){{{M00, M01, M02, M03}, {M10, M11, M12, M13}, {M20, M21, M22, M23}, {M30, M31, M32, M33}}} 77 | 78 | //constants 79 | #define VEC2_ZERO VEC2(0, 0) 80 | #define VEC3_ZERO VEC3(0, 0, 0) 81 | #define VEC4_ZERO VEC4(0, 0, 0, 0) 82 | #define QUAT_IDEN QUAT(0, 0, 0, 1) 83 | #define MAT2_ZERO MAT2(0, 0, 0, 0) 84 | #define MAT2_IDEN MAT2(1, 0, 0, 1) 85 | #define MAT3_ZERO MAT3(0, 0, 0, 0, 0, 0, 0, 0, 0) 86 | #define MAT3_IDEN MAT3(1, 0, 0, 0, 1, 0, 0, 0, 1) 87 | #define MAT4_ZERO MAT4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 88 | #define MAT4_IDEN MAT4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) 89 | 90 | //math configuration 91 | #include 92 | #ifdef DVECTOR_DOUBLE 93 | #define DVTYPE double 94 | #define DVCOS cos 95 | #define DVSIN sin 96 | #define DVTAN tan 97 | #define DVACOS acos 98 | #define DVHYPOT hypot 99 | #else 100 | #define DVTYPE float 101 | #define DVCOS cosf 102 | #define DVSIN sinf 103 | #define DVTAN tanf 104 | #define DVACOS acosf 105 | #define DVHYPOT hypotf 106 | #endif 107 | 108 | //types 109 | #ifdef DVECTOR_ISOC 110 | typedef struct vec2 { 111 | DVTYPE x, y; 112 | } vec2; 113 | typedef struct vec3 { 114 | DVTYPE x, y, z; 115 | } vec3; 116 | typedef struct vec4 { 117 | DVTYPE x, y, z, w; 118 | } vec4, quat; 119 | typedef union mat2 { 120 | DVTYPE m[2][2]; 121 | vec2 col[2]; 122 | } mat2; 123 | typedef union mat3 { 124 | DVTYPE m[3][3]; 125 | vec3 col[3]; 126 | } mat3; 127 | typedef union mat4 { 128 | DVTYPE m[4][4]; 129 | vec4 col[4]; 130 | } mat4; 131 | typedef union frst { 132 | DVTYPE f[24]; 133 | vec4 pln[6]; 134 | } frst; 135 | #else 136 | typedef union vec2 { 137 | DVTYPE v[2]; 138 | struct {DVTYPE x, y;}; 139 | } vec2; 140 | typedef union vec3 { 141 | DVTYPE v[3]; 142 | struct {DVTYPE x, y, z;}; 143 | struct {vec2 xy; DVTYPE _z;}; 144 | struct {DVTYPE _x; vec2 yz;}; 145 | } vec3; 146 | typedef union vec4 { 147 | DVTYPE v[4]; 148 | struct {DVTYPE x, y, z, w;}; 149 | struct {vec3 xyz; DVTYPE _w;}; 150 | struct {DVTYPE _x; vec3 yzw;}; 151 | struct {vec2 xy; vec2 zw;}; 152 | struct {DVTYPE __x; vec2 yz; DVTYPE __w;}; 153 | } vec4, quat; 154 | typedef union mat2 { 155 | DVTYPE m[2][2]; 156 | struct {DVTYPE m00, m01, m10, m11;}; 157 | vec2 col[2]; 158 | struct {vec2 col0, col1;}; 159 | } mat2; 160 | typedef union mat3 { 161 | DVTYPE m[3][3]; 162 | struct {DVTYPE m00, m01, m02, m10, m11, m12, m20, m21, m22;}; 163 | vec3 col[3]; 164 | struct {vec3 col0, col1, col2;}; 165 | } mat3; 166 | typedef union mat4 { 167 | DVTYPE m[4][4]; 168 | struct {DVTYPE m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33;}; 169 | vec4 col[4]; 170 | struct {vec4 col0, col1, col2, col3;}; 171 | } mat4; 172 | typedef union frst { 173 | DVTYPE f[24]; 174 | vec4 pln[6]; 175 | struct {vec4 left, right, top, bottom, near, far;}; 176 | } frst; 177 | #endif 178 | 179 | //vec2 function declarations 180 | DVDEF DVTYPE vec2Length(vec2); 181 | DVDEF DVTYPE vec2DotProduct(vec2, vec2); 182 | DVDEF vec2 vec2Negate(vec2); 183 | DVDEF vec2 vec2Normalize(vec2); 184 | DVDEF vec2 vec2Multiply(vec2, DVTYPE); 185 | DVDEF vec2 vec2Divide(vec2, DVTYPE); 186 | DVDEF vec2 vec2Rotate(vec2, DVTYPE); 187 | DVDEF vec2 vec2RotateXZ(vec2, DVTYPE); 188 | DVDEF vec2 vec2Add(vec2, vec2); 189 | DVDEF vec2 vec2Subtract(vec2, vec2); 190 | DVDEF vec2 vec2Reflect(vec2, vec2); 191 | DVDEF vec2 vec2Mix(vec2, vec2, DVTYPE); 192 | DVDEF int vec2Equal(vec2, vec2); 193 | 194 | //vec3 function declarations 195 | DVDEF DVTYPE vec3Length(vec3); 196 | DVDEF DVTYPE vec3DotProduct(vec3, vec3); 197 | DVDEF vec2 vec3GetXZ(vec3); 198 | DVDEF vec3 vec3Negate(vec3); 199 | DVDEF vec3 vec3Normalize(vec3); 200 | DVDEF vec3 vec3Multiply(vec3, DVTYPE); 201 | DVDEF vec3 vec3Divide(vec3, DVTYPE); 202 | DVDEF vec3 vec3Add(vec3, vec3); 203 | DVDEF vec3 vec3Subtract(vec3, vec3); 204 | DVDEF vec3 vec3Reflect(vec3, vec3); 205 | DVDEF vec3 vec3CrossProduct(vec3, vec3); 206 | DVDEF vec3 vec3Mix(vec3, vec3, DVTYPE); 207 | DVDEF int vec3Equal(vec3, vec3); 208 | 209 | //vec4 function declarations 210 | DVDEF vec3 vec4GetXYZ(vec4); 211 | DVDEF DVTYPE vec4Length(vec4); 212 | DVDEF DVTYPE vec4DotProduct(vec4, vec4); 213 | DVDEF vec4 vec4Negate(vec4); 214 | DVDEF vec4 vec4Normalize(vec4); 215 | DVDEF vec4 vec4Multiply(vec4, DVTYPE); 216 | DVDEF vec4 vec4Divide(vec4, DVTYPE); 217 | DVDEF vec4 vec4Add(vec4, vec4); 218 | DVDEF vec4 vec4Subtract(vec4, vec4); 219 | DVDEF vec4 vec4Reflect(vec4, vec4); 220 | DVDEF vec4 vec4Mix(vec4, vec4, DVTYPE); 221 | DVDEF int vec4Equal(vec4, vec4); 222 | 223 | //quat function declarations 224 | DVDEF vec3 quatGetXYZ(quat); 225 | DVDEF vec3 quatMultiplyVector(quat, vec3); 226 | DVDEF quat quatAxisAngle(vec3, DVTYPE); 227 | DVDEF quat quatEulerXYZ(DVTYPE, DVTYPE, DVTYPE); 228 | DVDEF quat quatEulerXZY(DVTYPE, DVTYPE, DVTYPE); 229 | DVDEF quat quatEulerYXZ(DVTYPE, DVTYPE, DVTYPE); 230 | DVDEF quat quatEulerYZX(DVTYPE, DVTYPE, DVTYPE); 231 | DVDEF quat quatEulerZXY(DVTYPE, DVTYPE, DVTYPE); 232 | DVDEF quat quatEulerZYX(DVTYPE, DVTYPE, DVTYPE); 233 | DVDEF quat quatNormalize(quat); 234 | DVDEF quat quatConjugate(quat); 235 | DVDEF quat quatLerp(quat, quat, DVTYPE); 236 | DVDEF quat quatSlerp(quat, quat, DVTYPE); 237 | DVDEF quat quatMultiply(quat, quat); 238 | DVDEF int quatEqual(quat, quat); 239 | 240 | //mat2 function declarations 241 | DVDEF vec2 mat2MultiplyVector(mat2, vec2); 242 | DVDEF mat2 mat2Transpose(mat2); 243 | DVDEF mat2 mat2Inverse(mat2); 244 | DVDEF mat2 mat2MultiplyScalar(mat2, DVTYPE); 245 | DVDEF mat2 mat2MultiplyMatrix(mat2, mat2); 246 | DVDEF mat2 mat2Add(mat2, mat2); 247 | DVDEF mat2 mat2Subtract(mat2, mat2); 248 | DVDEF int mat2Equal(mat2, mat2); 249 | 250 | //mat3 function declarations 251 | DVDEF vec3 mat3MultiplyVector(mat3, vec3); 252 | DVDEF mat3 mat3SetRotation(DVTYPE); 253 | DVDEF mat3 mat3SetScale(DVTYPE); 254 | DVDEF mat3 mat3SetScaleXY(vec2); 255 | DVDEF mat3 mat3SetTranslation(vec2); 256 | DVDEF mat3 mat3Transpose(mat3); 257 | DVDEF mat3 mat3Inverse(mat3); 258 | DVDEF mat3 mat3MultiplyScalar(mat3, DVTYPE); 259 | DVDEF mat3 mat3Rotate(mat3, DVTYPE); 260 | DVDEF mat3 mat3Scale(mat3, DVTYPE); 261 | DVDEF mat3 mat3ScaleXY(mat3, vec2); 262 | DVDEF mat3 mat3Translate(mat3, vec2); 263 | DVDEF mat3 mat3MultiplyMatrix(mat3, mat3); 264 | DVDEF mat3 mat3Add(mat3, mat3); 265 | DVDEF mat3 mat3Subtract(mat3, mat3); 266 | DVDEF int mat3Equal(mat3, mat3); 267 | 268 | //mat4 function declarations 269 | DVDEF vec4 mat4MultiplyVector(mat4, vec4); 270 | DVDEF mat4 mat4SetRotationX(DVTYPE); 271 | DVDEF mat4 mat4SetRotationY(DVTYPE); 272 | DVDEF mat4 mat4SetRotationZ(DVTYPE); 273 | DVDEF mat4 mat4SetRotationQuaternion(quat); 274 | DVDEF mat4 mat4SetScale(DVTYPE); 275 | DVDEF mat4 mat4SetScaleXYZ(vec3); 276 | DVDEF mat4 mat4SetTranslation(vec3); 277 | DVDEF mat4 mat4LookAt(vec3, vec3, vec3); 278 | DVDEF mat4 mat4Perspective(DVTYPE, DVTYPE, DVTYPE, DVTYPE); 279 | DVDEF mat4 mat4Ortho(DVTYPE, DVTYPE, DVTYPE, DVTYPE, DVTYPE, DVTYPE); 280 | DVDEF mat4 mat4Transpose(mat4); 281 | DVDEF mat4 mat4Inverse(mat4); 282 | DVDEF mat4 mat4MultiplyScalar(mat4, DVTYPE); 283 | DVDEF mat4 mat4RotateX(mat4, DVTYPE); 284 | DVDEF mat4 mat4RotateY(mat4, DVTYPE); 285 | DVDEF mat4 mat4RotateZ(mat4, DVTYPE); 286 | DVDEF mat4 mat4RotateQuaternion(mat4, quat); 287 | DVDEF mat4 mat4Scale(mat4, DVTYPE); 288 | DVDEF mat4 mat4ScaleXYZ(mat4, vec3); 289 | DVDEF mat4 mat4Translate(mat4, vec3); 290 | DVDEF mat4 mat4MultiplyMatrix(mat4, mat4); 291 | DVDEF mat4 mat4Add(mat4, mat4); 292 | DVDEF mat4 mat4Subtract(mat4, mat4); 293 | DVDEF int mat4Equal(mat4, mat4); 294 | 295 | //frst function declarations 296 | DVDEF frst frstFromMatrix(mat4); 297 | DVDEF int frstCullSphere(frst, vec3, DVTYPE); 298 | DVDEF int frstCullAABB(frst, vec3, vec3); 299 | 300 | #endif //DVECTOR_H 301 | 302 | //implementation section 303 | #ifdef DVECTOR_IMPLEMENTATION 304 | #undef DVECTOR_IMPLEMENTATION 305 | 306 | //vec2 functions 307 | DVDEF DVTYPE vec2Length (vec2 v) { 308 | return DVHYPOT(v.x, v.y); 309 | } 310 | DVDEF DVTYPE vec2DotProduct (vec2 v1, vec2 v2) { 311 | return v1.x*v2.x + v1.y*v2.y; 312 | } 313 | DVDEF vec2 vec2Negate (vec2 v) { 314 | return VEC2(-v.x, -v.y); 315 | } 316 | DVDEF vec2 vec2Normalize (vec2 v) { 317 | return vec2Divide(v, vec2Length(v)); 318 | } 319 | DVDEF vec2 vec2Multiply (vec2 v, DVTYPE s) { 320 | return VEC2(v.x*s, v.y*s); 321 | } 322 | DVDEF vec2 vec2Divide (vec2 v, DVTYPE s) { 323 | return VEC2(v.x/s, v.y/s); 324 | } 325 | DVDEF vec2 vec2Rotate (vec2 v, DVTYPE r) { 326 | DVTYPE c = DVCOS(r), s = DVSIN(r); 327 | return VEC2(v.x*c-v.y*s, v.y*c+v.x*s); 328 | } 329 | DVDEF vec2 vec2RotateXZ (vec2 v, DVTYPE r) { 330 | DVTYPE c = DVCOS(r), s = DVSIN(r); 331 | return VEC2(v.x*c+v.y*s, v.y*c-v.x*s); 332 | } 333 | DVDEF vec2 vec2Add (vec2 v1, vec2 v2) { 334 | return VEC2(v1.x+v2.x, v1.y+v2.y); 335 | } 336 | DVDEF vec2 vec2Subtract (vec2 v1, vec2 v2) { 337 | return VEC2(v1.x-v2.x, v1.y-v2.y); 338 | } 339 | DVDEF vec2 vec2Reflect (vec2 v1, vec2 v2) { 340 | return vec2Subtract(v1, vec2Multiply(v2, 2*vec2DotProduct(v1, v2))); 341 | } 342 | DVDEF vec2 vec2Mix (vec2 v1, vec2 v2, DVTYPE s) { 343 | return VEC2(v1.x+(v2.x-v1.x)*s, v1.y+(v2.y-v1.y)*s); 344 | } 345 | DVDEF int vec2Equal (vec2 v1, vec2 v2) { 346 | return (v1.x == v2.x)&&(v1.y == v2.y); 347 | } 348 | 349 | //vec3 functions 350 | DVDEF DVTYPE vec3Length (vec3 v) { 351 | return DVHYPOT(DVHYPOT(v.x, v.y), v.z); 352 | } 353 | DVDEF DVTYPE vec3DotProduct (vec3 v1, vec3 v2) { 354 | return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; 355 | } 356 | DVDEF vec2 vec3GetXZ (vec3 v) { 357 | return VEC2(v.x, v.z); 358 | } 359 | DVDEF vec3 vec3Negate (vec3 v) { 360 | return VEC3(-v.x, -v.y, -v.z); 361 | } 362 | DVDEF vec3 vec3Normalize (vec3 v) { 363 | return vec3Divide(v, vec3Length(v)); 364 | } 365 | DVDEF vec3 vec3Multiply (vec3 v, DVTYPE s) { 366 | return VEC3(v.x*s, v.y*s, v.z*s); 367 | } 368 | DVDEF vec3 vec3Divide (vec3 v, DVTYPE s) { 369 | return VEC3(v.x/s, v.y/s, v.z/s); 370 | } 371 | DVDEF vec3 vec3Add (vec3 v1, vec3 v2) { 372 | return VEC3(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z); 373 | } 374 | DVDEF vec3 vec3Subtract (vec3 v1, vec3 v2) { 375 | return VEC3(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z); 376 | } 377 | DVDEF vec3 vec3Reflect (vec3 v1, vec3 v2) { 378 | return vec3Subtract(v1, vec3Multiply(v2, 2*vec3DotProduct(v1, v2))); 379 | } 380 | DVDEF vec3 vec3CrossProduct (vec3 v1, vec3 v2) { 381 | return VEC3(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); 382 | } 383 | DVDEF vec3 vec3Mix (vec3 v1, vec3 v2, DVTYPE s) { 384 | return VEC3(v1.x+(v2.x-v1.x)*s, v1.y+(v2.y-v1.y)*s, v1.z+(v2.z-v1.z)*s); 385 | } 386 | DVDEF int vec3Equal (vec3 v1, vec3 v2) { 387 | return (v1.x == v2.x)&&(v1.y == v2.y)&&(v1.z == v2.z); 388 | } 389 | 390 | 391 | //vec4 functions 392 | DVDEF vec3 vec4GetXYZ (vec4 v) { 393 | return VEC3(v.x, v.y, v.z); 394 | } 395 | DVDEF DVTYPE vec4Length (vec4 v) { 396 | return DVHYPOT(DVHYPOT(v.x, v.y), DVHYPOT(v.z, v.w)); 397 | } 398 | DVDEF DVTYPE vec4DotProduct (vec4 v1, vec4 v2) { 399 | return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w; 400 | } 401 | DVDEF vec4 vec4Negate (vec4 v) { 402 | return VEC4(-v.x, -v.y, -v.z, -v.w); 403 | } 404 | DVDEF vec4 vec4Normalize (vec4 v) { 405 | return vec4Divide(v, vec4Length(v)); 406 | } 407 | DVDEF vec4 vec4Multiply (vec4 v, DVTYPE s) { 408 | return VEC4(v.x*s, v.y*s, v.z*s, v.w*s); 409 | } 410 | DVDEF vec4 vec4Divide (vec4 v, DVTYPE s) { 411 | return VEC4(v.x/s, v.y/s, v.z/s, v.w/s); 412 | } 413 | DVDEF vec4 vec4Add (vec4 v1, vec4 v2) { 414 | return VEC4(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z, v1.w+v2.w); 415 | } 416 | DVDEF vec4 vec4Subtract (vec4 v1, vec4 v2) { 417 | return VEC4(v1.x-v2.x, v1.y-v2.y, v1.z-v2.z, v1.w-v2.w); 418 | } 419 | DVDEF vec4 vec4Reflect (vec4 v1, vec4 v2) { 420 | return vec4Subtract(v1, vec4Multiply(v2, 2*vec4DotProduct(v1, v2))); 421 | } 422 | DVDEF vec4 vec4Mix (vec4 v1, vec4 v2, DVTYPE s) { 423 | return VEC4(v1.x+(v2.x-v1.x)*s, v1.y+(v2.y-v1.y)*s, v1.z+(v2.z-v1.z)*s, v1.w+(v2.w-v1.w)*s); 424 | } 425 | DVDEF int vec4Equal (vec4 v1, vec4 v2) { 426 | return (v1.x == v2.x)&&(v1.y == v2.y)&&(v1.z == v2.z)&&(v1.w == v2.w); 427 | } 428 | 429 | //quat functions 430 | DVDEF vec3 quatGetXYZ (quat q) { 431 | return VEC3(q.x, q.y, q.z); 432 | } 433 | DVDEF vec3 quatMultiplyVector (quat q, vec3 v) { 434 | vec3 q_xyz = VEC3(q.x, q.y, q.z); 435 | vec3 t = vec3Multiply(vec3CrossProduct(q_xyz, v), 2); 436 | return vec3Add(vec3Add(v, vec3Multiply(t, q.w)), vec3CrossProduct(q_xyz, t)); 437 | } 438 | DVDEF quat quatAxisAngle (vec3 a, DVTYPE r) { 439 | DVTYPE s = DVSIN(r/2); 440 | return QUAT(a.x*s, a.y*s, a.z*s, DVCOS(r/2)); 441 | } 442 | DVDEF quat quatEulerXYZ (DVTYPE a, DVTYPE b, DVTYPE c) { 443 | return quatMultiply(quatAxisAngle(VEC3(0, 0, 1), c), quatMultiply(quatAxisAngle(VEC3(0, 1, 0), b), quatAxisAngle(VEC3(1, 0, 0), a))); 444 | } 445 | DVDEF quat quatEulerXZY (DVTYPE a, DVTYPE b, DVTYPE c) { 446 | return quatMultiply(quatAxisAngle(VEC3(0, 1, 0), c), quatMultiply(quatAxisAngle(VEC3(0, 0, 1), b), quatAxisAngle(VEC3(1, 0, 0), a))); 447 | } 448 | DVDEF quat quatEulerYXZ (DVTYPE a, DVTYPE b, DVTYPE c) { 449 | return quatMultiply(quatAxisAngle(VEC3(0, 0, 1), c), quatMultiply(quatAxisAngle(VEC3(1, 0, 0), b), quatAxisAngle(VEC3(0, 1, 0), a))); 450 | } 451 | DVDEF quat quatEulerYZX (DVTYPE a, DVTYPE b, DVTYPE c) { 452 | return quatMultiply(quatAxisAngle(VEC3(1, 0, 0), c), quatMultiply(quatAxisAngle(VEC3(0, 0, 1), b), quatAxisAngle(VEC3(0, 1, 0), a))); 453 | } 454 | DVDEF quat quatEulerZXY (DVTYPE a, DVTYPE b, DVTYPE c) { 455 | return quatMultiply(quatAxisAngle(VEC3(0, 1, 0), c), quatMultiply(quatAxisAngle(VEC3(1, 0, 0), b), quatAxisAngle(VEC3(0, 0, 1), a))); 456 | } 457 | DVDEF quat quatEulerZYX (DVTYPE a, DVTYPE b, DVTYPE c) { 458 | return quatMultiply(quatAxisAngle(VEC3(1, 0, 0), c), quatMultiply(quatAxisAngle(VEC3(0, 1, 0), b), quatAxisAngle(VEC3(0, 0, 1), a))); 459 | } 460 | DVDEF quat quatNormalize (quat q) { 461 | return vec4Normalize(q); 462 | } 463 | DVDEF quat quatConjugate (quat q) { 464 | return QUAT(-q.x, -q.y, -q.z, q.w); 465 | } 466 | DVDEF quat quatLerp (quat q1, quat q2, DVTYPE s) { 467 | return quatNormalize(QUAT((1-s)*q1.x + s*q2.x, (1-s)*q1.y + s*q2.y, (1-s)*q1.z + s*q2.z, (1-s)*q1.w + s*q2.w)); 468 | } 469 | DVDEF quat quatSlerp (quat q1, quat q2, DVTYPE s) { 470 | DVTYPE th = DVACOS(q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w), sn = DVSIN(th), wa = DVSIN((1-s)*th)/sn, wb = DVSIN(s*th)/sn; 471 | return quatNormalize(QUAT(wa*q1.x + wb*q2.x, wa*q1.y + wb*q2.y, wa*q1.z + wb*q2.z, wa*q1.w + wb*q2.w)); 472 | } 473 | DVDEF quat quatMultiply (quat q1, quat q2) { 474 | return QUAT(q1.x*q2.w + q1.y*q2.z - q1.z*q2.y + q1.w*q2.x, -q1.x*q2.z + q1.y*q2.w + q1.z*q2.x + q1.w*q2.y, 475 | q1.x*q2.y - q1.y*q2.x + q1.z*q2.w + q1.w*q2.z, -q1.x*q2.x - q1.y*q2.y - q1.z*q2.z + q1.w*q2.w); 476 | } 477 | DVDEF int quatEqual (quat q1, quat q2) { 478 | return (q1.x == q2.x)&&(q1.y == q2.y)&&(q1.z == q2.z)&&(q1.w == q2.w); 479 | } 480 | 481 | //mat2 functions 482 | DVDEF vec2 mat2MultiplyVector (mat2 m, vec2 v) { 483 | return VEC2(m.m[0][0]*v.x + m.m[1][0]*v.y, m.m[0][1]*v.x + m.m[1][1]*v.y); 484 | } 485 | DVDEF mat2 mat2Transpose (mat2 m) { 486 | return MAT2(m.m[0][0], m.m[1][0], m.m[0][1], m.m[1][1]); 487 | } 488 | DVDEF mat2 mat2Inverse (mat2 m) { 489 | return mat2MultiplyScalar(MAT2(m.m[1][1], -m.m[0][1], -m.m[1][0], m.m[0][0]), 1/(m.m[0][0]*m.m[1][1]-m.m[1][0]*m.m[0][1])); 490 | } 491 | DVDEF mat2 mat2MultiplyScalar (mat2 m, DVTYPE s) { 492 | return MAT2(m.m[0][0]*s, m.m[0][1]*s, m.m[1][0]*s, m.m[1][1]*s); 493 | } 494 | DVDEF mat2 mat2MultiplyMatrix (mat2 m1, mat2 m2) { 495 | mat2 m; 496 | for (int i = 0; i < 2; i++) 497 | for (int j = 0; j < 2; j++) 498 | m.m[i][j] = m1.m[i][0]*m2.m[0][j] + m1.m[i][1]*m2.m[1][j]; 499 | return m; 500 | } 501 | DVDEF mat2 mat2Add (mat2 m1, mat2 m2) { 502 | return MAT2(m1.m[0][0]+m2.m[0][0], m1.m[0][1]+m2.m[0][1], m1.m[1][0]+m2.m[1][0], m1.m[1][1]+m2.m[1][1]); 503 | } 504 | DVDEF mat2 mat2Subtract (mat2 m1, mat2 m2) { 505 | return MAT2(m1.m[0][0]-m2.m[0][0], m1.m[0][1]-m2.m[0][1], m1.m[1][0]-m2.m[1][0], m1.m[1][1]-m2.m[1][1]); 506 | } 507 | DVDEF int mat2Equal (mat2 m1, mat2 m2) { 508 | return (m1.m[0][0] == m2.m[0][0])&&(m1.m[0][1] == m2.m[0][1])&&(m1.m[1][0] == m2.m[1][0])&&(m1.m[1][1] == m2.m[1][1]); 509 | } 510 | 511 | //mat3 function declarations 512 | DVDEF vec3 mat3MultiplyVector (mat3 m, vec3 v) { 513 | DVTYPE r[3]; 514 | for (int i = 0; i < 3; i++) 515 | r[i] = m.m[0][i]*v.x + m.m[1][i]*v.y + m.m[2][i]*v.z; 516 | return VEC3(r[0], r[1], r[2]); 517 | } 518 | DVDEF mat3 mat3SetRotation (DVTYPE r) { 519 | DVTYPE c = DVCOS(r), s = DVSIN(r); 520 | return MAT3(c, s, 0, -s, c, 0, 0, 0, 1); 521 | } 522 | DVDEF mat3 mat3SetScale (DVTYPE s) { 523 | return MAT3(s, 0, 0, 0, s, 0, 0, 0, 1); 524 | } 525 | DVDEF mat3 mat3SetScaleXY (vec2 s) { 526 | return MAT3(s.x, 0, 0, 0, s.y, 0, 0, 0, 1); 527 | } 528 | DVDEF mat3 mat3SetTranslation (vec2 v) { 529 | return MAT3(1, 0, 0, 0, 1, 0, v.x, v.y, 1); 530 | } 531 | DVDEF mat3 mat3Transpose (mat3 m) { 532 | return MAT3(m.m[0][0], m.m[1][0], m.m[2][0], m.m[0][1], m.m[1][1], m.m[2][1], m.m[0][2], m.m[1][2], m.m[2][2]); 533 | } 534 | DVDEF mat3 mat3Inverse (mat3 m) { 535 | mat3 t = MAT3(m.m[1][1]*m.m[2][2] - m.m[2][1]*m.m[1][2], m.m[1][2]*m.m[2][0] - m.m[1][0]*m.m[2][2], m.m[1][0]*m.m[2][1] - m.m[1][1]*m.m[2][0], 536 | m.m[2][1]*m.m[0][2] - m.m[0][1]*m.m[2][2], m.m[0][0]*m.m[2][2] - m.m[0][2]*m.m[2][0], m.m[0][1]*m.m[2][0] - m.m[0][0]*m.m[2][1], 537 | m.m[0][1]*m.m[1][2] - m.m[1][1]*m.m[0][2], m.m[0][2]*m.m[1][0] - m.m[0][0]*m.m[1][2], m.m[0][0]*m.m[1][1] - m.m[0][1]*m.m[1][0]); 538 | return mat3MultiplyScalar(t, 1/(m.m[0][0]*t.m[0][0] + m.m[1][0]*t.m[1][0] + m.m[2][0]*t.m[2][0])); 539 | } 540 | DVDEF mat3 mat3MultiplyScalar (mat3 m, DVTYPE s) { 541 | for (int i = 0; i < 3; i++) 542 | for (int j = 0; j < 3; j++) 543 | m.m[i][j] *= s; 544 | return m; 545 | } 546 | DVDEF mat3 mat3Rotate (mat3 m, DVTYPE r) { 547 | return mat3MultiplyMatrix(m, mat3SetRotation(r)); 548 | } 549 | DVDEF mat3 mat3Scale (mat3 m, DVTYPE s) { 550 | return mat3MultiplyMatrix(m, mat3SetScale(s)); 551 | } 552 | DVDEF mat3 mat3ScaleXY (mat3 m, vec2 v) { 553 | return mat3MultiplyMatrix(m, mat3SetScaleXY(v)); 554 | } 555 | DVDEF mat3 mat3Translate (mat3 m, vec2 v) { 556 | return mat3MultiplyMatrix(m, mat3SetTranslation(v)); 557 | } 558 | DVDEF mat3 mat3MultiplyMatrix (mat3 m1, mat3 m2) { 559 | mat3 m; 560 | for (int i = 0; i < 3; i++) 561 | for (int j = 0; j < 3; j++) 562 | m.m[i][j] = m1.m[i][0]*m2.m[0][j] + m1.m[i][1]*m2.m[1][j] + m1.m[i][2]*m2.m[2][j]; 563 | return m; 564 | } 565 | DVDEF mat3 mat3Add (mat3 m1, mat3 m2) { 566 | mat3 m; 567 | for (int i = 0; i < 3; i++) 568 | for (int j = 0; j < 3; j++) 569 | m.m[i][j] = m1.m[i][j] + m2.m[i][j]; 570 | return m; 571 | } 572 | DVDEF mat3 mat3Subtract (mat3 m1, mat3 m2) { 573 | mat3 m; 574 | for (int i = 0; i < 3; i++) 575 | for (int j = 0; j < 3; j++) 576 | m.m[i][j] = m1.m[i][j] - m2.m[i][j]; 577 | return m; 578 | } 579 | DVDEF int mat3Equal (mat3 m1, mat3 m2) { 580 | for (int i = 0; i < 3; i++) 581 | for (int j = 0; j < 3; j++) 582 | if (m1.m[i][j] != m2.m[i][j]) 583 | return 0; 584 | return 1; 585 | } 586 | 587 | //mat4 function declarations 588 | DVDEF vec4 mat4MultiplyVector (mat4 m, vec4 v) { 589 | DVTYPE r[4]; 590 | for (int i = 0; i < 4; i++) 591 | r[i] = m.m[0][i]*v.x + m.m[1][i]*v.y + m.m[2][i]*v.z + m.m[3][i]*v.w; 592 | return VEC4(r[0], r[1], r[2], r[3]); 593 | } 594 | DVDEF mat4 mat4SetRotationX (DVTYPE r) { 595 | DVTYPE c = DVCOS(r), s = DVSIN(r); 596 | return MAT4(1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1); 597 | } 598 | DVDEF mat4 mat4SetRotationY (DVTYPE r) { 599 | DVTYPE c = DVCOS(r), s = DVSIN(r); 600 | return MAT4(c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1); 601 | } 602 | DVDEF mat4 mat4SetRotationZ (DVTYPE r) { 603 | DVTYPE c = DVCOS(r), s = DVSIN(r); 604 | return MAT4(c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 605 | } 606 | DVDEF mat4 mat4SetRotationQuaternion (quat q) { 607 | DVTYPE xx = q.x*q.x, xy = q.x*q.y, xz = q.x*q.z, xw = q.x*q.w, yy = q.y*q.y, yz = q.y*q.z, yw = q.y*q.w, zz = q.z*q.z, zw = q.z*q.w; 608 | return MAT4(1-2*yy-2*zz, 2*xy+2*zw, 2*xz-2*yw, 0, 2*xy-2*zw, 1-2*xx-2*zz, 2*yz+2*xw, 0, 2*xz+2*yw, 2*yz-2*xw, 1-2*xx-2*yy, 0, 0, 0, 0, 1); 609 | } 610 | DVDEF mat4 mat4SetScale (DVTYPE s) { 611 | return MAT4(s, 0, 0, 0, 0, s, 0, 0, 0, 0, s, 0, 0, 0, 0, 1); 612 | } 613 | DVDEF mat4 mat4SetScaleXYZ (vec3 v) { 614 | return MAT4(v.x, 0, 0, 0, 0, v.y, 0, 0, 0, 0, v.z, 0, 0, 0, 0, 1); 615 | } 616 | DVDEF mat4 mat4SetTranslation (vec3 v) { 617 | return MAT4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, v.x, v.y, v.z, 1); 618 | } 619 | DVDEF mat4 mat4LookAt (vec3 from, vec3 to, vec3 up) { 620 | vec3 f = vec3Normalize(vec3Subtract(to, from)), s = vec3Normalize(vec3CrossProduct(f, up)), t = vec3CrossProduct(s, f); 621 | mat4 m = MAT4(s.x, t.x, -f.x, 0, s.y, t.y, -f.y, 0, s.z, t.z, -f.z, 0, 0, 0, 0, 1); 622 | for (int i = 0; i < 3; i++) 623 | m.m[3][i] = -vec3DotProduct(VEC3(m.m[0][i], m.m[1][i], m.m[2][i]), from); 624 | return m; 625 | } 626 | DVDEF mat4 mat4Perspective (DVTYPE vfov, DVTYPE aspect, DVTYPE ndist, DVTYPE fdist) { 627 | DVTYPE a = 1/DVTAN(vfov/2); 628 | return MAT4(a/aspect, 0, 0, 0, 0, a, 0, 0, 0, 0, -((fdist+ndist)/(fdist-ndist)), -1, 0, 0, -((2*fdist*ndist)/(fdist-ndist)), 0); 629 | } 630 | DVDEF mat4 mat4Ortho (DVTYPE left, DVTYPE right, DVTYPE bottom, DVTYPE top, DVTYPE ndist, DVTYPE fdist) { 631 | return MAT4(2/(right-left), 0, 0, 0, 0, 2/(top-bottom), 0, 0, 0, 0, -2/(fdist-ndist), 0, 632 | -(right+left)/(right-left), -(top+bottom)/(top-bottom), -(fdist+ndist)/(fdist-ndist), 1); 633 | } 634 | DVDEF mat4 mat4Transpose (mat4 m) { 635 | return MAT4(m.m[0][0], m.m[1][0], m.m[2][0], m.m[3][0], m.m[0][1], m.m[1][1], m.m[2][1], m.m[3][1], 636 | m.m[0][2], m.m[1][2], m.m[2][2], m.m[3][2], m.m[0][3], m.m[1][3], m.m[2][3], m.m[3][3]); 637 | } 638 | DVDEF mat4 mat4Inverse (mat4 m) { 639 | DVTYPE s[6] = {m.m[0][0]*m.m[1][1] - m.m[1][0]*m.m[0][1], m.m[0][0]*m.m[1][2] - m.m[1][0]*m.m[0][2], m.m[0][0]*m.m[1][3] - m.m[1][0]*m.m[0][3], 640 | m.m[0][1]*m.m[1][2] - m.m[1][1]*m.m[0][2], m.m[0][1]*m.m[1][3] - m.m[1][1]*m.m[0][3], m.m[0][2]*m.m[1][3] - m.m[1][2]*m.m[0][3]}; 641 | DVTYPE c[6] = {m.m[2][0]*m.m[3][1] - m.m[3][0]*m.m[2][1], m.m[2][0]*m.m[3][2] - m.m[3][0]*m.m[2][2], m.m[2][0]*m.m[3][3] - m.m[3][0]*m.m[2][3], 642 | m.m[2][1]*m.m[3][2] - m.m[3][1]*m.m[2][2], m.m[2][1]*m.m[3][3] - m.m[3][1]*m.m[2][3], m.m[2][2]*m.m[3][3] - m.m[3][2]*m.m[2][3]}; 643 | return mat4MultiplyScalar(MAT4(m.m[1][1]*c[5] - m.m[1][2]*c[4] + m.m[1][3]*c[3], m.m[0][2]*c[4] - m.m[0][1]*c[5] - m.m[0][3]*c[3], 644 | m.m[3][1]*s[5] - m.m[3][2]*s[4] + m.m[3][3]*s[3], m.m[2][2]*s[4] - m.m[2][1]*s[5] - m.m[2][3]*s[3], m.m[1][2]*c[2] - m.m[1][0]*c[5] - m.m[1][3]*c[1], 645 | m.m[0][0]*c[5] - m.m[0][2]*c[2] + m.m[0][3]*c[1], m.m[3][2]*s[2] - m.m[3][0]*s[5] - m.m[3][3]*s[1], m.m[2][0]*s[5] - m.m[2][2]*s[2] + m.m[2][3]*s[1], 646 | m.m[1][0]*c[4] - m.m[1][1]*c[2] + m.m[1][3]*c[0], m.m[0][1]*c[2] - m.m[0][0]*c[4] - m.m[0][3]*c[0], m.m[3][0]*s[4] - m.m[3][1]*s[2] + m.m[3][3]*s[0], 647 | m.m[2][1]*s[2] - m.m[2][0]*s[4] - m.m[2][3]*s[0], m.m[1][1]*c[1] - m.m[1][0]*c[3] - m.m[1][2]*c[0], m.m[0][0]*c[3] - m.m[0][1]*c[1] + m.m[0][2]*c[0], 648 | m.m[3][1]*s[1] - m.m[3][0]*s[3] - m.m[3][2]*s[0], m.m[2][0]*s[3] - m.m[2][1]*s[1] + m.m[2][2]*s[0]), 649 | 1/(s[0]*c[5] - s[1]*c[4] + s[2]*c[3] + s[3]*c[2] - s[4]*c[1] + s[5]*c[0])); 650 | } 651 | DVDEF mat4 mat4MultiplyScalar (mat4 m, DVTYPE s) { 652 | for (int i = 0; i < 4; i++) 653 | for (int j = 0; j < 4; j++) 654 | m.m[i][j] *= s; 655 | return m; 656 | } 657 | DVDEF mat4 mat4RotateX (mat4 m, DVTYPE r) { 658 | return mat4MultiplyMatrix(mat4SetRotationX(r), m); 659 | } 660 | DVDEF mat4 mat4RotateY (mat4 m, DVTYPE r) { 661 | return mat4MultiplyMatrix(mat4SetRotationY(r), m); 662 | } 663 | DVDEF mat4 mat4RotateZ (mat4 m, DVTYPE r) { 664 | return mat4MultiplyMatrix(mat4SetRotationZ(r), m); 665 | } 666 | DVDEF mat4 mat4RotateQuaternion (mat4 m, quat q) { 667 | return mat4MultiplyMatrix(mat4SetRotationQuaternion(q), m); 668 | } 669 | DVDEF mat4 mat4Scale (mat4 m, DVTYPE s) { 670 | return mat4MultiplyMatrix(mat4SetScale(s), m); 671 | } 672 | DVDEF mat4 mat4ScaleXYZ (mat4 m, vec3 v) { 673 | return mat4MultiplyMatrix(mat4SetScaleXYZ(v), m); 674 | } 675 | DVDEF mat4 mat4Translate (mat4 m, vec3 v) { 676 | return mat4MultiplyMatrix(mat4SetTranslation(v), m); 677 | } 678 | DVDEF mat4 mat4MultiplyMatrix (mat4 m1, mat4 m2) { 679 | mat4 m; 680 | for (int i = 0; i < 4; i++) 681 | for (int j = 0; j < 4; j++) 682 | m.m[i][j] = m1.m[0][j]*m2.m[i][0] + m1.m[1][j]*m2.m[i][1] + m1.m[2][j]*m2.m[i][2] + m1.m[3][j]*m2.m[i][3]; 683 | return m; 684 | } 685 | DVDEF mat4 mat4Add (mat4 m1, mat4 m2) { 686 | mat4 m; 687 | for (int i = 0; i < 4; i++) 688 | for (int j = 0; j < 4; j++) 689 | m.m[i][j] = m1.m[i][j] + m2.m[i][j]; 690 | return m; 691 | } 692 | DVDEF mat4 mat4Subtract (mat4 m1, mat4 m2) { 693 | mat4 m; 694 | for (int i = 0; i < 4; i++) 695 | for (int j = 0; j < 4; j++) 696 | m.m[i][j] = m1.m[i][j] - m2.m[i][j]; 697 | return m; 698 | } 699 | DVDEF int mat4Equal (mat4 m1, mat4 m2) { 700 | for (int i = 0; i < 4; i++) 701 | for (int j = 0; j < 4; j++) 702 | if (m1.m[i][j] != m2.m[i][j]) 703 | return 0; 704 | return 1; 705 | } 706 | 707 | //frst functions 708 | DVDEF frst frstFromMatrix (mat4 m) { 709 | frst f; 710 | f.pln[0] = VEC4(m.m[0][3]+m.m[0][0], m.m[1][3]+m.m[1][0], m.m[2][3]+m.m[2][0], m.m[3][3]+m.m[3][0]); //left 711 | f.pln[1] = VEC4(m.m[0][3]-m.m[0][0], m.m[1][3]-m.m[1][0], m.m[2][3]-m.m[2][0], m.m[3][3]-m.m[3][0]); //right 712 | f.pln[2] = VEC4(m.m[0][3]-m.m[0][1], m.m[1][3]-m.m[1][1], m.m[2][3]-m.m[2][1], m.m[3][3]-m.m[3][1]); //top 713 | f.pln[3] = VEC4(m.m[0][3]+m.m[0][1], m.m[1][3]+m.m[1][1], m.m[2][3]+m.m[2][1], m.m[3][3]+m.m[3][1]); //bottom 714 | f.pln[4] = VEC4(m.m[0][3]+m.m[0][2], m.m[1][3]+m.m[1][2], m.m[2][3]+m.m[2][2], m.m[3][3]+m.m[3][2]); //near 715 | f.pln[5] = VEC4(m.m[0][3]-m.m[0][2], m.m[1][3]-m.m[1][2], m.m[2][3]-m.m[2][2], m.m[3][3]-m.m[3][2]); //far 716 | for (int i = 0; i < 6; i++) 717 | f.pln[i] = vec4Divide(f.pln[i], vec3Length(vec4GetXYZ(f.pln[i]))); 718 | return f; 719 | } 720 | DVDEF int frstCullSphere (frst f, vec3 v, DVTYPE s) { 721 | for (int i = 0; i < 6; i++) 722 | if (vec3DotProduct(vec4GetXYZ(f.pln[i]), v) + f.pln[i].w + s < 0) 723 | return 0; 724 | return 1; 725 | } 726 | DVDEF int frstCullAABB (frst f, vec3 min, vec3 max) { 727 | for (int i = 0; i < 6; i++) { 728 | const vec3 v = VEC3(f.pln[i].x > 0 ? max.x : min.x, f.pln[i].y > 0 ? max.y : min.y, f.pln[i].z > 0 ? max.z : min.z); 729 | if (vec3DotProduct(vec4GetXYZ(f.pln[i]), v) + f.pln[i].w < 0) 730 | return 0; 731 | } 732 | return 1; 733 | } 734 | 735 | #endif //DVECTOR_IMPLEMENTATION 736 | --------------------------------------------------------------------------------