Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
math.qh
Go to the documentation of this file.
1#pragma once
2
3#include "lib/float.qh"
4
6void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
7{
8 if (weight == 0) return;
9 if (mean == 0) e.(a) *= (value ** weight);
10 else e.(a) += (value ** mean) * weight;
11 e.(c) += weight;
12}
13
15float mean_evaluate(entity e, .float a, .float c, float mean)
16{
17 if (e.(c) == 0) return 0;
18 if (mean == 0) return (e.(a) ** (1.0 / e.(c)));
19 else return ((e.(a) / e.(c)) ** (1.0 / mean));
20}
21
22#define MEAN_ACCUMULATE(s, prefix, v, w) mean_accumulate(s, prefix##_accumulator, prefix##_count, prefix##_mean, v, w)
23#define MEAN_EVALUATE(s, prefix) mean_evaluate(s, prefix##_accumulator, prefix##_count, prefix##_mean)
24#define MEAN_DECLARE(prefix, m) float prefix##_mean = m; .float prefix##_count, prefix##_accumulator
25
26
27/*
28==================
29Angc used for animations
30==================
31*/
32
33
35float angc(float a1, float a2)
36{
37 while (a1 > 180)
38 a1 -= 360;
39 while (a1 < -179)
40 a1 += 360;
41 while (a2 > 180)
42 a2 -= 360;
43 while (a2 < -179)
44 a2 += 360;
45 float a = a1 - a2;
46 while (a > 180)
47 a -= 360;
48 while (a < -179)
49 a += 360;
50 return a;
51}
52
54float fsnap(float val, float fsize)
55{
56 return rint(val / fsize) * fsize;
57}
58
60vector vsnap(vector point, float fsize)
61{
62 vector vret;
63
64 vret.x = rint(point.x / fsize) * fsize;
65 vret.y = rint(point.y / fsize) * fsize;
66 vret.z = ceil(point.z / fsize) * fsize;
67
68 return vret;
69}
70
72float lerpratio(float f0, float f1, float ratio)
73{
74 return f0 * (1 - ratio) + f1 * ratio;
75}
76
78float lerp(float t0, float f0, float t1, float f1, float t)
79{
80 return lerpratio(f0, f1, (t - t0) / (t1 - t0));
81}
82
84float lerp3ratio(float f0, float f1, float f2, float ratio)
85{
86 float mid = 0.5;
87 return ratio < mid ? lerpratio(f0, f1, ratio / mid) : ratio > mid ? lerpratio(f1, f2, (ratio - mid) / mid) : f1;
88}
89
90
92vector lerpvratio(vector f0, vector f1, float ratio)
93{
94 return f0 * (1 - ratio) + f1 * ratio;
95}
96
99{
100 float mid = 0.5;
101 return ratio < mid ? lerpvratio(f0, f1, ratio / mid) : ratio > mid ? lerpvratio(f1, f2, (ratio - mid) / mid) : f1;
102}
103
105vector lerpv(float t0, vector v0, float t1, vector v1, float t)
106{
107 return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
108}
109
112{
113 return (c - 2 * b + a) * (t * t)
114 + (b - a) * (2 * t)
115 + a;
116}
117
120{
121 return (c - 2 * b + a) * (2 * t)
122 + (b - a) * 2;
123}
124
126float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float spd)
127{
128 return (((startspeedfactor + endspeedfactor - 2
129 ) * spd - 2 * startspeedfactor - endspeedfactor + 3
130 ) * spd + startspeedfactor
131 ) * spd;
132}
133
135bool cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
136{
137 if (startspeedfactor < 0 || endspeedfactor < 0) return false;
138
139 /*
140 // if this is the case, the possible zeros of the first derivative are outside
141 // 0..1
142 We can calculate this condition as condition
143 if(se <= 3)
144 return true;
145 */
146
147 // better, see below:
148 if (startspeedfactor <= 3 && endspeedfactor <= 3) return true;
149
150 // if this is the case, the first derivative has no zeros at all
151 float se = startspeedfactor + endspeedfactor;
152 float s_e = startspeedfactor - endspeedfactor;
153 if (3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
154 return true;
155
156 // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
157 // we also get s_e <= 6 - se
158 // 3 * (se - 4)^2 + (6 - se)^2
159 // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
160 // Therefore, above "better" check works!
161
162 return false;
163
164 // known good cases:
165 // (0, [0..3])
166 // (0.5, [0..3.8])
167 // (1, [0..4])
168 // (1.5, [0..3.9])
169 // (2, [0..3.7])
170 // (2.5, [0..3.4])
171 // (3, [0..3])
172 // (3.5, [0.2..2.3])
173 // (4, 1)
174
175 /*
176 On another note:
177 inflection point is always at (2s + e - 3) / (3s + 3e - 6).
178
179 s + e - 2 == 0: no inflection
180
181 s + e > 2:
182 0 < inflection < 1 if:
183 0 < 2s + e - 3 < 3s + 3e - 6
184 2s + e > 3 and 2e + s > 3
185
186 s + e < 2:
187 0 < inflection < 1 if:
188 0 > 2s + e - 3 > 3s + 3e - 6
189 2s + e < 3 and 2e + s < 3
190
191 Therefore: there is an inflection point iff:
192 e outside (3 - s)/2 .. 3 - s*2
193
194 in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0)
195 */
196}
197
200float float2range11(float f)
201{
202 return f / (fabs(f) + 1);
203}
204
207float float2range01(float f)
208{
209 return 0.5 + 0.5 * float2range11(f);
210}
211
213float median(float a, float b, float c)
214{
215 return (a < c) ? bound(a, b, c) : bound(c, b, a);
216}
217
219float almost_equals(float a, float b)
220{
221 float eps = (max(a, -a) + max(b, -b)) * 0.001;
222 return a - b < eps && b - a < eps;
223}
224
226float almost_equals_eps(float a, float b, float times_eps)
227{
228 float eps = max(fabs(a), fabs(b)) * FLOAT_EPSILON * times_eps;
229 return a - b < eps && b - a < eps;
230}
231
233float almost_in_bounds(float a, float b, float c)
234{
235 float eps = (max(a, -a) + max(c, -c)) * 0.001;
236 if (a > c) eps = -eps;
237 return b == median(a - eps, b, c + eps);
238}
239
241float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
242{
243 if (halflifedist > 0) return (0.5 ** ((bound(mindist, d, maxdist) - mindist) / halflifedist));
244 else if (halflifedist < 0) return (0.5 ** ((bound(mindist, d, maxdist) - maxdist) / halflifedist));
245 else return 1;
246}
247
248#define power2of(e) (2 ** e)
249
251float log2of(float e)
252{
253 // NOTE: generated code
254 if (e > 2048)
255 if (e > 131072)
256 if (e > 1048576)
257 if (e > 4194304) return 23;
258 else
259 if (e > 2097152) return 22;
260 else return 21;
261 else
262 if (e > 524288) return 20;
263 else
264 if (e > 262144) return 19;
265 else return 18;
266 else
267 if (e > 16384)
268 if (e > 65536) return 17;
269 else
270 if (e > 32768) return 16;
271 else return 15;
272 else
273 if (e > 8192) return 14;
274 else
275 if (e > 4096) return 13;
276 else return 12;
277 else
278 if (e > 32)
279 if (e > 256)
280 if (e > 1024) return 11;
281 else
282 if (e > 512) return 10;
283 else return 9;
284 else
285 if (e > 128) return 8;
286 else
287 if (e > 64) return 7;
288 else return 6;
289 else
290 if (e > 4)
291 if (e > 16) return 5;
292 else
293 if (e > 8) return 4;
294 else return 3;
295 else
296 if (e > 2) return 2;
297 else
298 if (e > 1) return 1;
299 else return 0;
300}
301
304vector solve_quadratic(float a, float b, float c)
305{
306 vector v;
307 float D;
308 v = '0 0 0';
309 if (a == 0)
310 {
311 if (b != 0)
312 {
313 v.x = v.y = -c / b;
314 v.z = 1;
315 }
316 else
317 {
318 if (c == 0)
319 {
320 // actually, every number solves the equation!
321 v.z = 1;
322 }
323 }
324 }
325 else
326 {
327 D = b * b - 4 * a * c;
328 if (D >= 0)
329 {
330 D = sqrt(D);
331 if (a > 0) // put the smaller solution first
332 {
333 v.x = ((-b) - D) / (2 * a);
334 v.y = ((-b) + D) / (2 * a);
335 }
336 else
337 {
338 v.x = (-b + D) / (2 * a);
339 v.y = (-b - D) / (2 * a);
340 }
341 v.z = 1;
342 }
343 else
344 {
345 // complex solutions!
346 D = sqrt(-D);
347 v.x = -b / (2 * a);
348 if (a > 0) v.y = D / (2 * a);
349 else v.y = -D / (2 * a);
350 v.z = 0;
351 }
352 }
353 return v;
354}
355
363float map_ranges(float value, float src_min, float src_max, float dest_min, float dest_max) {
364 float src_diff = src_max - src_min;
365 float dest_diff = dest_max - dest_min;
366 float ratio = (value - src_min) / src_diff;
367 return dest_min + dest_diff * ratio;
368}
369
372float map_bound_ranges(float value, float src_min, float src_max, float dest_min, float dest_max) {
373 if (value <= src_min) return dest_min;
374 if (value >= src_max) return dest_max;
375 return map_ranges(value, src_min, src_max, dest_min, dest_max);
376}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
const float FLOAT_EPSILON
Definition float.qh:4
#define ERASEABLE
Definition _all.inc:37
ERASEABLE float mean_evaluate(entity e,.float a,.float c, float mean)
Definition math.qh:15
ERASEABLE float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
Definition math.qh:241
ERASEABLE float lerpratio(float f0, float f1, float ratio)
Definition math.qh:72
ERASEABLE void mean_accumulate(entity e,.float a,.float c, float mean, float value, float weight)
Definition math.qh:6
ERASEABLE float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float spd)
Definition math.qh:126
ERASEABLE float lerp3ratio(float f0, float f1, float f2, float ratio)
Definition math.qh:84
ERASEABLE float log2of(float e)
Definition math.qh:251
ERASEABLE float map_ranges(float value, float src_min, float src_max, float dest_min, float dest_max)
Maps values between the src and dest range: src_min to dest_min, src_max to dest_max,...
Definition math.qh:363
ERASEABLE float angc(float a1, float a2)
Definition math.qh:35
ERASEABLE float float2range11(float f)
continuous function mapping all reals into -1..1
Definition math.qh:200
ERASEABLE vector lerpv3ratio(vector f0, vector f1, vector f2, float ratio)
Definition math.qh:98
ERASEABLE vector vsnap(vector point, float fsize)
Definition math.qh:60
ERASEABLE vector lerpv(float t0, vector v0, float t1, vector v1, float t)
Definition math.qh:105
ERASEABLE float fsnap(float val, float fsize)
Definition math.qh:54
ERASEABLE vector solve_quadratic(float a, float b, float c)
ax^2 + bx + c = 0
Definition math.qh:304
ERASEABLE float float2range01(float f)
continuous function mapping all reals into 0..1
Definition math.qh:207
ERASEABLE vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
Definition math.qh:119
ERASEABLE float almost_equals(float a, float b)
Definition math.qh:219
ERASEABLE vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
Definition math.qh:111
ERASEABLE float median(float a, float b, float c)
Definition math.qh:213
ERASEABLE float map_bound_ranges(float value, float src_min, float src_max, float dest_min, float dest_max)
Same as map_ranges except that values outside the source range are clamped to min or max.
Definition math.qh:372
ERASEABLE bool cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
Definition math.qh:135
ERASEABLE float almost_in_bounds(float a, float b, float c)
Definition math.qh:233
ERASEABLE vector lerpvratio(vector f0, vector f1, float ratio)
Definition math.qh:92
ERASEABLE float lerp(float t0, float f0, float t1, float f1, float t)
Definition math.qh:78
ERASEABLE float almost_equals_eps(float a, float b, float times_eps)
Definition math.qh:226
float ceil(float f)
float bound(float min, float value, float max)
float sqrt(float f)
float rint(float f)
float fabs(float f)
float max(float f,...)
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1points f2
Definition all.inc:364
f1
Definition all.inc:561
vector
Definition self.qh:92