Merge branch 'master' into martin-t/globals
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / warpzone / anglestransform.qc
1 #include "anglestransform.qh"
2
3 // angles transforms
4 // angles in fixedmakevectors/fixedvectoangles space
5 vector AnglesTransform_Apply(vector transform, vector v)
6 {
7         FIXED_MAKE_VECTORS_NEW(transform, forward, right, up);
8         return forward * v.x + right * (-v.y) + up * v.z;
9 }
10
11 vector AnglesTransform_Multiply(vector t1, vector t2)
12 {
13         FIXED_MAKE_VECTORS_NEW(t2, forward, right, up);
14         forward = AnglesTransform_Apply(t1, forward);
15         up = AnglesTransform_Apply(t1, up);
16         return fixedvectoangles2(forward, up);
17 }
18
19 vector AnglesTransform_Invert(vector transform)
20 {
21         vector i_forward, i_up;
22         FIXED_MAKE_VECTORS_NEW(transform, forward, right, up);
23         // we want angles that turn forward into '1 0 0', right into '0 1 0' and up into '0 0 1'
24         // but these are orthogonal unit vectors!
25         // so to invert, we can simply fixedvectoangles the TRANSPOSED matrix
26         // TODO is this always -transform?
27         i_forward.x = forward.x;
28         i_forward.y = -right.x;
29         i_forward.z = up.x;
30         i_up.x = forward.z;
31         i_up.y = -right.z;
32         i_up.z = up.z;
33         return fixedvectoangles2(i_forward, i_up);
34 }
35
36 vector AnglesTransform_TurnDirectionFR(vector transform)
37 {
38         // turn 180 degrees around v_up
39         // changes in-direction to out-direction
40         //fixedmakevectors(transform);
41         //return fixedvectoangles2(-1 * v_forward, 1 * v_up);
42         transform.x = -transform.x;
43         transform.y = 180 + transform.y;
44         transform.z = -transform.z;
45         // pitch: -s +c
46         // yaw:   -s -c
47         // roll:  -s +c
48         return transform;
49 }
50
51 vector AnglesTransform_TurnDirectionFU(vector transform)
52 {
53         // turn 180 degrees around v_up
54         // changes in-direction to out-direction
55         //fixedmakevectors(transform);
56         //return fixedvectoangles2(-1 * v_forward, 1 * v_up);
57         transform.x = -transform.x;
58         transform.y = 180 + transform.y;
59         transform.z = 180 - transform.z;
60         return transform;
61 }
62
63 vector AnglesTransform_RightDivide(vector to_transform, vector from_transform)
64 {
65         return AnglesTransform_Multiply(to_transform, AnglesTransform_Invert(from_transform));
66 }
67
68 vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform)
69 {
70         return AnglesTransform_Multiply(AnglesTransform_Invert(from_transform), to_transform);
71 }
72
73 vector AnglesTransform_Normalize(vector t, float minimize_roll)
74 {
75         float need_flip;
76         // first, bring all angles in their range...
77         t.x = t.x - 360 * rint(t.x / 360);
78         t.y = t.y - 360 * rint(t.y / 360);
79         t.z = t.z - 360 * rint(t.z / 360);
80         if(minimize_roll)
81                 need_flip = (t.z > 90 || t.z <= -90);
82         else
83                 need_flip = (t.x > 90 || t.x < -90); // for pitch we prefer to allow exactly -90 degrees for looking straight down
84         if(need_flip)
85         {
86                 if(t.x >= 0) t.x = 180 - t.x; else t.x = -180 - t.x;
87                 if(t.y > 0) t.y -= 180; else t.y += 180;
88                 if(t.z > 0) t.z -= 180; else t.z += 180;
89         }
90         return t;
91 }
92
93 vector AnglesTransform_CancelRoll(vector t)
94 {
95         const float epsilon = 30;
96         float f;
97
98         // constraints:
99         // forward vector (NOT SO important)
100         // right vector, up vector: screen rotation (MORE important)
101         // choose best match among all pitch-yaw only rotations
102
103         // FIXME find a better method
104
105         f = fabs(t.x - (-90)) / epsilon;
106         if(f < 1)
107         {
108                 //t_x = -90;
109                 t.y += t.z;
110                 t.z = 0;
111         }
112         else
113         {
114                 f = fabs(t.x - 90) / epsilon;
115                 if(f < 1)
116                 {
117                         //t_x = 90;
118                         t.y -= t.z;
119                         t.z = 0;
120                 }
121         }
122         return t;
123 }
124
125 #if POSITIVE_PITCH_IS_DOWN
126 vector AnglesTransform_ApplyToAngles(vector transform, vector v)
127 {
128         v.x = -v.x;
129         v = AnglesTransform_Multiply(transform, v);
130         v.x = -v.x;
131         return v;
132 }
133 vector AnglesTransform_ApplyToVAngles(vector transform, vector v)
134 {
135         v = AnglesTransform_Multiply(transform, v);
136         return v;
137 }
138 vector AnglesTransform_FromAngles(vector v)
139 {
140         v.x = -v.x;
141         return v;
142 }
143 vector AnglesTransform_ToAngles(vector v)
144 {
145         v.x = -v.x;
146         return v;
147 }
148 vector AnglesTransform_FromVAngles(vector v)
149 {
150         return v;
151 }
152 vector AnglesTransform_ToVAngles(vector v)
153 {
154         return v;
155 }
156 #else
157 vector AnglesTransform_ApplyToAngles(vector transform, vector v)
158 {
159         v = AnglesTransform_Multiply(transform, v);
160         return v;
161 }
162 vector AnglesTransform_ApplyToVAngles(vector transform, vector v)
163 {
164         v.x = -v.x;
165         v = AnglesTransform_Multiply(transform, v);
166         v.x = -v.x;
167         return v;
168 }
169 vector AnglesTransform_FromAngles(vector v)
170 {
171         return v;
172 }
173 vector AnglesTransform_ToAngles(vector v)
174 {
175         return v;
176 }
177 vector AnglesTransform_FromVAngles(vector v)
178 {
179         v.x = -v.x;
180         return v;
181 }
182 vector AnglesTransform_ToVAngles(vector v)
183 {
184         v.x = -v.x;
185         return v;
186 }
187 #endif
188
189 vector AnglesTransform_Multiply_GetPostShift(vector t0, vector st0, vector t1, vector st1)
190 {
191         // we want the result of:
192         //   t0 * (t1 * p + st1) + st0
193         //   t0 * t1 * p + t0 * st1 + st0
194         return st0 + AnglesTransform_Apply(t0, st1);
195 }
196 vector AnglesTransform_PrePostShift_GetPostShift(vector sf, vector t, vector st)
197 {
198         return st - AnglesTransform_Apply(t, sf);
199 }