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