Home | History | Annotate | Download | only in demos
      1 /*
      2  * Copyright (c) 2015-2016 The Khronos Group Inc.
      3  * Copyright (c) 2015-2016 Valve Corporation
      4  * Copyright (c) 2015-2016 LunarG, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and/or associated documentation files (the "Materials"), to
      8  * deal in the Materials without restriction, including without limitation the
      9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     10  * sell copies of the Materials, and to permit persons to whom the Materials are
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice(s) and this permission notice shall be included in
     14  * all copies or substantial portions of the Materials.
     15  *
     16  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     19  *
     20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
     21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
     23  * USE OR OTHER DEALINGS IN THE MATERIALS.
     24  *
     25  * Relicensed from the WTFPL (http://www.wtfpl.net/faq/).
     26  */
     27 
     28 #ifndef LINMATH_H
     29 #define LINMATH_H
     30 
     31 #include <math.h>
     32 
     33 // Converts degrees to radians.
     34 #define degreesToRadians(angleDegrees) (angleDegrees * M_PI / 180.0)
     35 
     36 // Converts radians to degrees.
     37 #define radiansToDegrees(angleRadians) (angleRadians * 180.0 / M_PI)
     38 
     39 typedef float vec3[3];
     40 static inline void vec3_add(vec3 r, vec3 const a, vec3 const b) {
     41     int i;
     42     for (i = 0; i < 3; ++i)
     43         r[i] = a[i] + b[i];
     44 }
     45 static inline void vec3_sub(vec3 r, vec3 const a, vec3 const b) {
     46     int i;
     47     for (i = 0; i < 3; ++i)
     48         r[i] = a[i] - b[i];
     49 }
     50 static inline void vec3_scale(vec3 r, vec3 const v, float const s) {
     51     int i;
     52     for (i = 0; i < 3; ++i)
     53         r[i] = v[i] * s;
     54 }
     55 static inline float vec3_mul_inner(vec3 const a, vec3 const b) {
     56     float p = 0.f;
     57     int i;
     58     for (i = 0; i < 3; ++i)
     59         p += b[i] * a[i];
     60     return p;
     61 }
     62 static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b) {
     63     r[0] = a[1] * b[2] - a[2] * b[1];
     64     r[1] = a[2] * b[0] - a[0] * b[2];
     65     r[2] = a[0] * b[1] - a[1] * b[0];
     66 }
     67 static inline float vec3_len(vec3 const v) {
     68     return sqrtf(vec3_mul_inner(v, v));
     69 }
     70 static inline void vec3_norm(vec3 r, vec3 const v) {
     71     float k = 1.f / vec3_len(v);
     72     vec3_scale(r, v, k);
     73 }
     74 static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n) {
     75     float p = 2.f * vec3_mul_inner(v, n);
     76     int i;
     77     for (i = 0; i < 3; ++i)
     78         r[i] = v[i] - p * n[i];
     79 }
     80 
     81 typedef float vec4[4];
     82 static inline void vec4_add(vec4 r, vec4 const a, vec4 const b) {
     83     int i;
     84     for (i = 0; i < 4; ++i)
     85         r[i] = a[i] + b[i];
     86 }
     87 static inline void vec4_sub(vec4 r, vec4 const a, vec4 const b) {
     88     int i;
     89     for (i = 0; i < 4; ++i)
     90         r[i] = a[i] - b[i];
     91 }
     92 static inline void vec4_scale(vec4 r, vec4 v, float s) {
     93     int i;
     94     for (i = 0; i < 4; ++i)
     95         r[i] = v[i] * s;
     96 }
     97 static inline float vec4_mul_inner(vec4 a, vec4 b) {
     98     float p = 0.f;
     99     int i;
    100     for (i = 0; i < 4; ++i)
    101         p += b[i] * a[i];
    102     return p;
    103 }
    104 static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b) {
    105     r[0] = a[1] * b[2] - a[2] * b[1];
    106     r[1] = a[2] * b[0] - a[0] * b[2];
    107     r[2] = a[0] * b[1] - a[1] * b[0];
    108     r[3] = 1.f;
    109 }
    110 static inline float vec4_len(vec4 v) { return sqrtf(vec4_mul_inner(v, v)); }
    111 static inline void vec4_norm(vec4 r, vec4 v) {
    112     float k = 1.f / vec4_len(v);
    113     vec4_scale(r, v, k);
    114 }
    115 static inline void vec4_reflect(vec4 r, vec4 v, vec4 n) {
    116     float p = 2.f * vec4_mul_inner(v, n);
    117     int i;
    118     for (i = 0; i < 4; ++i)
    119         r[i] = v[i] - p * n[i];
    120 }
    121 
    122 typedef vec4 mat4x4[4];
    123 static inline void mat4x4_identity(mat4x4 M) {
    124     int i, j;
    125     for (i = 0; i < 4; ++i)
    126         for (j = 0; j < 4; ++j)
    127             M[i][j] = i == j ? 1.f : 0.f;
    128 }
    129 static inline void mat4x4_dup(mat4x4 M, mat4x4 N) {
    130     int i, j;
    131     for (i = 0; i < 4; ++i)
    132         for (j = 0; j < 4; ++j)
    133             M[i][j] = N[i][j];
    134 }
    135 static inline void mat4x4_row(vec4 r, mat4x4 M, int i) {
    136     int k;
    137     for (k = 0; k < 4; ++k)
    138         r[k] = M[k][i];
    139 }
    140 static inline void mat4x4_col(vec4 r, mat4x4 M, int i) {
    141     int k;
    142     for (k = 0; k < 4; ++k)
    143         r[k] = M[i][k];
    144 }
    145 static inline void mat4x4_transpose(mat4x4 M, mat4x4 N) {
    146     int i, j;
    147     for (j = 0; j < 4; ++j)
    148         for (i = 0; i < 4; ++i)
    149             M[i][j] = N[j][i];
    150 }
    151 static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b) {
    152     int i;
    153     for (i = 0; i < 4; ++i)
    154         vec4_add(M[i], a[i], b[i]);
    155 }
    156 static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b) {
    157     int i;
    158     for (i = 0; i < 4; ++i)
    159         vec4_sub(M[i], a[i], b[i]);
    160 }
    161 static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k) {
    162     int i;
    163     for (i = 0; i < 4; ++i)
    164         vec4_scale(M[i], a[i], k);
    165 }
    166 static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y,
    167                                       float z) {
    168     int i;
    169     vec4_scale(M[0], a[0], x);
    170     vec4_scale(M[1], a[1], y);
    171     vec4_scale(M[2], a[2], z);
    172     for (i = 0; i < 4; ++i) {
    173         M[3][i] = a[3][i];
    174     }
    175 }
    176 static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b) {
    177     int k, r, c;
    178     for (c = 0; c < 4; ++c)
    179         for (r = 0; r < 4; ++r) {
    180             M[c][r] = 0.f;
    181             for (k = 0; k < 4; ++k)
    182                 M[c][r] += a[k][r] * b[c][k];
    183         }
    184 }
    185 static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v) {
    186     int i, j;
    187     for (j = 0; j < 4; ++j) {
    188         r[j] = 0.f;
    189         for (i = 0; i < 4; ++i)
    190             r[j] += M[i][j] * v[i];
    191     }
    192 }
    193 static inline void mat4x4_translate(mat4x4 T, float x, float y, float z) {
    194     mat4x4_identity(T);
    195     T[3][0] = x;
    196     T[3][1] = y;
    197     T[3][2] = z;
    198 }
    199 static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y,
    200                                              float z) {
    201     vec4 t = {x, y, z, 0};
    202     vec4 r;
    203     int i;
    204     for (i = 0; i < 4; ++i) {
    205         mat4x4_row(r, M, i);
    206         M[3][i] += vec4_mul_inner(r, t);
    207     }
    208 }
    209 static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b) {
    210     int i, j;
    211     for (i = 0; i < 4; ++i)
    212         for (j = 0; j < 4; ++j)
    213             M[i][j] = i < 3 && j < 3 ? a[i] * b[j] : 0.f;
    214 }
    215 static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z,
    216                                  float angle) {
    217     float s = sinf(angle);
    218     float c = cosf(angle);
    219     vec3 u = {x, y, z};
    220 
    221     if (vec3_len(u) > 1e-4) {
    222         vec3_norm(u, u);
    223         mat4x4 T;
    224         mat4x4_from_vec3_mul_outer(T, u, u);
    225 
    226         mat4x4 S = {{0, u[2], -u[1], 0},
    227                     {-u[2], 0, u[0], 0},
    228                     {u[1], -u[0], 0, 0},
    229                     {0, 0, 0, 0}};
    230         mat4x4_scale(S, S, s);
    231 
    232         mat4x4 C;
    233         mat4x4_identity(C);
    234         mat4x4_sub(C, C, T);
    235 
    236         mat4x4_scale(C, C, c);
    237 
    238         mat4x4_add(T, T, C);
    239         mat4x4_add(T, T, S);
    240 
    241         T[3][3] = 1.;
    242         mat4x4_mul(R, M, T);
    243     } else {
    244         mat4x4_dup(R, M);
    245     }
    246 }
    247 static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle) {
    248     float s = sinf(angle);
    249     float c = cosf(angle);
    250     mat4x4 R = {{1.f, 0.f, 0.f, 0.f},
    251                 {0.f, c, s, 0.f},
    252                 {0.f, -s, c, 0.f},
    253                 {0.f, 0.f, 0.f, 1.f}};
    254     mat4x4_mul(Q, M, R);
    255 }
    256 static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle) {
    257     float s = sinf(angle);
    258     float c = cosf(angle);
    259     mat4x4 R = {{c, 0.f, s, 0.f},
    260                 {0.f, 1.f, 0.f, 0.f},
    261                 {-s, 0.f, c, 0.f},
    262                 {0.f, 0.f, 0.f, 1.f}};
    263     mat4x4_mul(Q, M, R);
    264 }
    265 static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle) {
    266     float s = sinf(angle);
    267     float c = cosf(angle);
    268     mat4x4 R = {{c, s, 0.f, 0.f},
    269                 {-s, c, 0.f, 0.f},
    270                 {0.f, 0.f, 1.f, 0.f},
    271                 {0.f, 0.f, 0.f, 1.f}};
    272     mat4x4_mul(Q, M, R);
    273 }
    274 static inline void mat4x4_invert(mat4x4 T, mat4x4 M) {
    275     float s[6];
    276     float c[6];
    277     s[0] = M[0][0] * M[1][1] - M[1][0] * M[0][1];
    278     s[1] = M[0][0] * M[1][2] - M[1][0] * M[0][2];
    279     s[2] = M[0][0] * M[1][3] - M[1][0] * M[0][3];
    280     s[3] = M[0][1] * M[1][2] - M[1][1] * M[0][2];
    281     s[4] = M[0][1] * M[1][3] - M[1][1] * M[0][3];
    282     s[5] = M[0][2] * M[1][3] - M[1][2] * M[0][3];
    283 
    284     c[0] = M[2][0] * M[3][1] - M[3][0] * M[2][1];
    285     c[1] = M[2][0] * M[3][2] - M[3][0] * M[2][2];
    286     c[2] = M[2][0] * M[3][3] - M[3][0] * M[2][3];
    287     c[3] = M[2][1] * M[3][2] - M[3][1] * M[2][2];
    288     c[4] = M[2][1] * M[3][3] - M[3][1] * M[2][3];
    289     c[5] = M[2][2] * M[3][3] - M[3][2] * M[2][3];
    290 
    291     /* Assumes it is invertible */
    292     float idet = 1.0f / (s[0] * c[5] - s[1] * c[4] + s[2] * c[3] + s[3] * c[2] -
    293                          s[4] * c[1] + s[5] * c[0]);
    294 
    295     T[0][0] = (M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
    296     T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
    297     T[0][2] = (M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
    298     T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet;
    299 
    300     T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet;
    301     T[1][1] = (M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet;
    302     T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet;
    303     T[1][3] = (M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet;
    304 
    305     T[2][0] = (M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet;
    306     T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet;
    307     T[2][2] = (M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet;
    308     T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet;
    309 
    310     T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet;
    311     T[3][1] = (M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet;
    312     T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet;
    313     T[3][3] = (M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet;
    314 }
    315 static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M) {
    316     mat4x4_dup(R, M);
    317     float s = 1.;
    318     vec3 h;
    319 
    320     vec3_norm(R[2], R[2]);
    321 
    322     s = vec3_mul_inner(R[1], R[2]);
    323     vec3_scale(h, R[2], s);
    324     vec3_sub(R[1], R[1], h);
    325     vec3_norm(R[2], R[2]);
    326 
    327     s = vec3_mul_inner(R[1], R[2]);
    328     vec3_scale(h, R[2], s);
    329     vec3_sub(R[1], R[1], h);
    330     vec3_norm(R[1], R[1]);
    331 
    332     s = vec3_mul_inner(R[0], R[1]);
    333     vec3_scale(h, R[1], s);
    334     vec3_sub(R[0], R[0], h);
    335     vec3_norm(R[0], R[0]);
    336 }
    337 
    338 static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t,
    339                                   float n, float f) {
    340     M[0][0] = 2.f * n / (r - l);
    341     M[0][1] = M[0][2] = M[0][3] = 0.f;
    342 
    343     M[1][1] = 2.f * n / (t - b);
    344     M[1][0] = M[1][2] = M[1][3] = 0.f;
    345 
    346     M[2][0] = (r + l) / (r - l);
    347     M[2][1] = (t + b) / (t - b);
    348     M[2][2] = -(f + n) / (f - n);
    349     M[2][3] = -1.f;
    350 
    351     M[3][2] = -2.f * (f * n) / (f - n);
    352     M[3][0] = M[3][1] = M[3][3] = 0.f;
    353 }
    354 static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t,
    355                                 float n, float f) {
    356     M[0][0] = 2.f / (r - l);
    357     M[0][1] = M[0][2] = M[0][3] = 0.f;
    358 
    359     M[1][1] = 2.f / (t - b);
    360     M[1][0] = M[1][2] = M[1][3] = 0.f;
    361 
    362     M[2][2] = -2.f / (f - n);
    363     M[2][0] = M[2][1] = M[2][3] = 0.f;
    364 
    365     M[3][0] = -(r + l) / (r - l);
    366     M[3][1] = -(t + b) / (t - b);
    367     M[3][2] = -(f + n) / (f - n);
    368     M[3][3] = 1.f;
    369 }
    370 static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect,
    371                                       float n, float f) {
    372     /* NOTE: Degrees are an unhandy unit to work with.
    373      * linmath.h uses radians for everything! */
    374     float const a = (float)(1.f / tan(y_fov / 2.f));
    375 
    376     m[0][0] = a / aspect;
    377     m[0][1] = 0.f;
    378     m[0][2] = 0.f;
    379     m[0][3] = 0.f;
    380 
    381     m[1][0] = 0.f;
    382     m[1][1] = a;
    383     m[1][2] = 0.f;
    384     m[1][3] = 0.f;
    385 
    386     m[2][0] = 0.f;
    387     m[2][1] = 0.f;
    388     m[2][2] = -((f + n) / (f - n));
    389     m[2][3] = -1.f;
    390 
    391     m[3][0] = 0.f;
    392     m[3][1] = 0.f;
    393     m[3][2] = -((2.f * f * n) / (f - n));
    394     m[3][3] = 0.f;
    395 }
    396 static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up) {
    397     /* Adapted from Android's OpenGL Matrix.java.                        */
    398     /* See the OpenGL GLUT documentation for gluLookAt for a description */
    399     /* of the algorithm. We implement it in a straightforward way:       */
    400 
    401     /* TODO: The negation of of can be spared by swapping the order of
    402      *       operands in the following cross products in the right way. */
    403     vec3 f;
    404     vec3_sub(f, center, eye);
    405     vec3_norm(f, f);
    406 
    407     vec3 s;
    408     vec3_mul_cross(s, f, up);
    409     vec3_norm(s, s);
    410 
    411     vec3 t;
    412     vec3_mul_cross(t, s, f);
    413 
    414     m[0][0] = s[0];
    415     m[0][1] = t[0];
    416     m[0][2] = -f[0];
    417     m[0][3] = 0.f;
    418 
    419     m[1][0] = s[1];
    420     m[1][1] = t[1];
    421     m[1][2] = -f[1];
    422     m[1][3] = 0.f;
    423 
    424     m[2][0] = s[2];
    425     m[2][1] = t[2];
    426     m[2][2] = -f[2];
    427     m[2][3] = 0.f;
    428 
    429     m[3][0] = 0.f;
    430     m[3][1] = 0.f;
    431     m[3][2] = 0.f;
    432     m[3][3] = 1.f;
    433 
    434     mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
    435 }
    436 
    437 typedef float quat[4];
    438 static inline void quat_identity(quat q) {
    439     q[0] = q[1] = q[2] = 0.f;
    440     q[3] = 1.f;
    441 }
    442 static inline void quat_add(quat r, quat a, quat b) {
    443     int i;
    444     for (i = 0; i < 4; ++i)
    445         r[i] = a[i] + b[i];
    446 }
    447 static inline void quat_sub(quat r, quat a, quat b) {
    448     int i;
    449     for (i = 0; i < 4; ++i)
    450         r[i] = a[i] - b[i];
    451 }
    452 static inline void quat_mul(quat r, quat p, quat q) {
    453     vec3 w;
    454     vec3_mul_cross(r, p, q);
    455     vec3_scale(w, p, q[3]);
    456     vec3_add(r, r, w);
    457     vec3_scale(w, q, p[3]);
    458     vec3_add(r, r, w);
    459     r[3] = p[3] * q[3] - vec3_mul_inner(p, q);
    460 }
    461 static inline void quat_scale(quat r, quat v, float s) {
    462     int i;
    463     for (i = 0; i < 4; ++i)
    464         r[i] = v[i] * s;
    465 }
    466 static inline float quat_inner_product(quat a, quat b) {
    467     float p = 0.f;
    468     int i;
    469     for (i = 0; i < 4; ++i)
    470         p += b[i] * a[i];
    471     return p;
    472 }
    473 static inline void quat_conj(quat r, quat q) {
    474     int i;
    475     for (i = 0; i < 3; ++i)
    476         r[i] = -q[i];
    477     r[3] = q[3];
    478 }
    479 #define quat_norm vec4_norm
    480 static inline void quat_mul_vec3(vec3 r, quat q, vec3 v) {
    481     quat v_ = {v[0], v[1], v[2], 0.f};
    482 
    483     quat_conj(r, q);
    484     quat_norm(r, r);
    485     quat_mul(r, v_, r);
    486     quat_mul(r, q, r);
    487 }
    488 static inline void mat4x4_from_quat(mat4x4 M, quat q) {
    489     float a = q[3];
    490     float b = q[0];
    491     float c = q[1];
    492     float d = q[2];
    493     float a2 = a * a;
    494     float b2 = b * b;
    495     float c2 = c * c;
    496     float d2 = d * d;
    497 
    498     M[0][0] = a2 + b2 - c2 - d2;
    499     M[0][1] = 2.f * (b * c + a * d);
    500     M[0][2] = 2.f * (b * d - a * c);
    501     M[0][3] = 0.f;
    502 
    503     M[1][0] = 2 * (b * c - a * d);
    504     M[1][1] = a2 - b2 + c2 - d2;
    505     M[1][2] = 2.f * (c * d + a * b);
    506     M[1][3] = 0.f;
    507 
    508     M[2][0] = 2.f * (b * d + a * c);
    509     M[2][1] = 2.f * (c * d - a * b);
    510     M[2][2] = a2 - b2 - c2 + d2;
    511     M[2][3] = 0.f;
    512 
    513     M[3][0] = M[3][1] = M[3][2] = 0.f;
    514     M[3][3] = 1.f;
    515 }
    516 
    517 static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q) {
    518     /*  XXX: The way this is written only works for othogonal matrices. */
    519     /* TODO: Take care of non-orthogonal case. */
    520     quat_mul_vec3(R[0], q, M[0]);
    521     quat_mul_vec3(R[1], q, M[1]);
    522     quat_mul_vec3(R[2], q, M[2]);
    523 
    524     R[3][0] = R[3][1] = R[3][2] = 0.f;
    525     R[3][3] = 1.f;
    526 }
    527 static inline void quat_from_mat4x4(quat q, mat4x4 M) {
    528     float r = 0.f;
    529     int i;
    530 
    531     int perm[] = {0, 1, 2, 0, 1};
    532     int *p = perm;
    533 
    534     for (i = 0; i < 3; i++) {
    535         float m = M[i][i];
    536         if (m < r)
    537             continue;
    538         m = r;
    539         p = &perm[i];
    540     }
    541 
    542     r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]]);
    543 
    544     if (r < 1e-6) {
    545         q[0] = 1.f;
    546         q[1] = q[2] = q[3] = 0.f;
    547         return;
    548     }
    549 
    550     q[0] = r / 2.f;
    551     q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]]) / (2.f * r);
    552     q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]]) / (2.f * r);
    553     q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]]) / (2.f * r);
    554 }
    555 
    556 #endif
    557