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