1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "common/math/quat.h"
18 
clamp(float x)19 static float clamp(float x) { return x < 0.0f ? 0.0f : x; }
20 
initQuat(Quat * q,const struct Mat33 * R)21 void initQuat(Quat *q, const struct Mat33 *R) {
22   float Hx = R->elem[0][0];
23   float My = R->elem[1][1];
24   float Az = R->elem[2][2];
25 
26   q->x = sqrtf(clamp(Hx - My - Az + 1.0f) * 0.25f);
27   q->y = sqrtf(clamp(-Hx + My - Az + 1.0f) * 0.25f);
28   q->z = sqrtf(clamp(-Hx - My + Az + 1.0f) * 0.25f);
29   q->w = sqrtf(clamp(Hx + My + Az + 1.0f) * 0.25f);
30   q->x = copysignf(q->x, R->elem[1][2] - R->elem[2][1]);
31   q->y = copysignf(q->y, R->elem[2][0] - R->elem[0][2]);
32   q->z = copysignf(q->z, R->elem[0][1] - R->elem[1][0]);
33 }
34 
quatToMatrix(struct Mat33 * R,const Quat * q)35 void quatToMatrix(struct Mat33 *R, const Quat *q) {
36   float q0 = q->w;
37   float q1 = q->x;
38   float q2 = q->y;
39   float q3 = q->z;
40   float sq_q1 = 2.0f * q1 * q1;
41   float sq_q2 = 2.0f * q2 * q2;
42   float sq_q3 = 2.0f * q3 * q3;
43   float q1_q2 = 2.0f * q1 * q2;
44   float q3_q0 = 2.0f * q3 * q0;
45   float q1_q3 = 2.0f * q1 * q3;
46   float q2_q0 = 2.0f * q2 * q0;
47   float q2_q3 = 2.0f * q2 * q3;
48   float q1_q0 = 2.0f * q1 * q0;
49 
50   R->elem[0][0] = 1.0f - sq_q2 - sq_q3;
51   R->elem[1][0] = q1_q2 - q3_q0;
52   R->elem[2][0] = q1_q3 + q2_q0;
53   R->elem[0][1] = q1_q2 + q3_q0;
54   R->elem[1][1] = 1.0f - sq_q1 - sq_q3;
55   R->elem[2][1] = q2_q3 - q1_q0;
56   R->elem[0][2] = q1_q3 - q2_q0;
57   R->elem[1][2] = q2_q3 + q1_q0;
58   R->elem[2][2] = 1.0f - sq_q1 - sq_q2;
59 }
60 
quatNormalize(Quat * q)61 void quatNormalize(Quat *q) {
62   if (q->w < 0.0f) {
63     q->x = -q->x;
64     q->y = -q->y;
65     q->z = -q->z;
66     q->w = -q->w;
67   }
68 
69   float invNorm =
70       1.0f / sqrtf(q->x * q->x + q->y * q->y + q->z * q->z + q->w * q->w);
71 
72   q->x *= invNorm;
73   q->y *= invNorm;
74   q->z *= invNorm;
75   q->w *= invNorm;
76 }
77