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