f4b8aaa49a40f99ea572521722c523e7055096f7
[fw/altos] / src / core / ao_quaternion.h
1 /*
2  * Copyright © 2013 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #ifndef _AO_QUATERNION_H_
19 #define _AO_QUATERNION_H_
20
21 #include <math.h>
22
23 struct ao_quaternion {
24         float   r;              /* real bit */
25         float   x, y, z;        /* imaginary bits */
26 };
27
28 static inline void ao_quaternion_multiply(struct ao_quaternion *r,
29                                           struct ao_quaternion *a,
30                                           struct ao_quaternion *b)
31 {
32         struct ao_quaternion    t;
33 #define T(_a,_b)        (((a)->_a) * ((b)->_b))
34         t.r = T(r,r) - T(x,x) - T(y,y) - T(z,z);
35         t.x = T(r,x) + T(x,r) + T(y,z) - T(z,y);
36         t.y = T(r,y) - T(x,z) + T(y,r) + T(z,x);
37         t.z = T(r,z) + T(x,y) - T(y,x) + T(z,r);
38 #undef T
39         *r = t;
40 }
41
42 static inline void ao_quaternion_conjugate(struct ao_quaternion *r,
43                                            struct ao_quaternion *a)
44 {
45         r->r = a->r;
46         r->x = -a->x;
47         r->y = -a->y;
48         r->z = -a->z;
49 }
50
51 static inline float ao_quaternion_normal(struct ao_quaternion *a)
52 {
53 #define S(_a)   (((a)->_a) * ((a)->_a))
54         return S(r) + S(x) + S(y) + S(z);
55 #undef S
56 }
57
58 static inline void ao_quaternion_scale(struct ao_quaternion *r,
59                                        struct ao_quaternion *a,
60                                        float b)
61 {
62         r->r = a->r * b;
63         r->x = a->x * b;
64         r->y = a->y * b;
65         r->z = a->z * b;
66 }
67
68 static inline void ao_quaternion_normalize(struct ao_quaternion *r,
69                                            struct ao_quaternion *a)
70 {
71         float   n = ao_quaternion_normal(a);
72
73         if (n > 0)
74                 ao_quaternion_scale(r, a, 1/sqrtf(n));
75         else
76                 *r = *a;
77 }
78
79 static inline void ao_quaternion_rotate(struct ao_quaternion *r,
80                                         struct ao_quaternion *a,
81                                         struct ao_quaternion *b)
82 {
83         struct ao_quaternion    c;
84         struct ao_quaternion    t;
85
86         ao_quaternion_conjugate(&c, b);
87         ao_quaternion_multiply(&t, b, a);
88         ao_quaternion_multiply(r, &t, &c);
89 }
90
91 static inline void ao_quaternion_init_vector(struct ao_quaternion *r,
92                                              float x, float y, float z)
93 {
94         r->r = 0;
95         r->x = x;
96         r->y = y;
97         r->z = z;
98 }
99
100 static inline void ao_quaternion_init_rotation(struct ao_quaternion *r,
101                                                float x, float y, float z,
102                                                float s, float c)
103 {
104         r->r = c;
105         r->x = s * x;
106         r->y = s * y;
107         r->z = s * z;
108 }
109
110 static inline void ao_quaternion_init_zero_rotation(struct ao_quaternion *r)
111 {
112         r->r = 1;
113         r->x = r->y = r->z = 0;
114 }
115
116 #endif /* _AO_QUATERNION_H_ */