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