]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/lib/deglobalization.qh
comment NaN handling
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / deglobalization.qh
1 #include "lib/misc.qh"
2 #include "lib/static.qh"
3 #include "lib/vector.qh"
4
5 // These macros wrap functions which use globals so mutation only occurs inside them and is not visible from outside.
6 // Functions for which all usages are replaced with these macros can be hidden inside our `*defs.qh` files
7 // to prevent anyone from using them accidentally.
8
9 // TODO stuff in the engine that uses the v_forward/v_right/v_up globals and is not wrapped:
10 //  - RF_USEAXIS, addentities, predraw,
11 //    CL_GetEntityMatrix (in engine but is called from other functions so transitively any of them can use the globals - e.g. V_CalcRefdef, maybe others)
12 //  - e.camera_transform / CL_VM_TransformView (in engine)
13 //  - adddynamiclight
14 //  - makestatic
15 //  - gettaginfo
16 //  - getentity
17 //  - skel_get_bonerel, skel_get_boneabs, skel_set_bone, skel_mul_bone, skel_mul_bones
18 //  - aim
19
20 #ifdef GAMEQC
21 STATIC_INIT(globals) {
22         // set to NaN to more easily detect uninitialized use
23         // TODO when all functions are wrapped and the raw functions are not used anymore,
24         // assert that the global vectors are NaN before calling the raw functions
25         // to make sure nobody (even builtins) is accidentally using them - NaN is the most likely value to expose remaining usages
26
27         // TODO make sure `isnan` actually works - potential compiler bug:
28         //LOG_INFOF("%f\n", 0.0/0.0 == 0.0/0.0);
29         //LOG_INFOF("%f\n", 0.0/0.0 != 0.0/0.0);
30         //float x = 0.0/0.0;
31         //LOG_INFOF("%f\n", x == x);
32         //LOG_INFOF("%f\n", x != x);
33
34         v_forward = VEC_NAN;
35         v_right = VEC_NAN;
36         v_up = VEC_NAN;
37 }
38 #endif
39
40 /// Same as the `makevectors` builtin but uses the provided locals instead of the `v_*` globals.
41 /// Always use this instead of raw `makevectors` to make the data flow clear.
42 #define MAKE_VECTORS(angles, forward, right, up) MACRO_BEGIN { \
43         makevectors(angles); \
44         forward = v_forward; \
45         right = v_right; \
46         up = v_up; \
47         v_forward = VEC_NAN; \
48         v_right = VEC_NAN; \
49         v_up = VEC_NAN; \
50 } MACRO_END
51
52 /// Same as `MAKE_VECTORS` but also creates the locals for convenience.
53 #define MAKE_VECTORS_NEW(angles, forward, right, up) \
54         vector forward = '0 0 0'; \
55         vector right = '0 0 0'; \
56         vector up = '0 0 0'; \
57         MAKE_VECTORS(angles, forward, right, up);
58
59 #define VECTOR_VECTORS(forward_in, forward, right, up) MACRO_BEGIN { \
60         _vectorvectors_hidden(forward_in); \
61         forward = v_forward; \
62         right = v_right; \
63         up = v_up; \
64         v_forward = VEC_NAN; \
65         v_right = VEC_NAN; \
66         v_up = VEC_NAN; \
67 } MACRO_END
68
69 #define VECTOR_VECTORS_NEW(forward_in, forward, right, up) \
70         vector forward = '0 0 0'; \
71         vector right = '0 0 0'; \
72         vector up = '0 0 0'; \
73         VECTOR_VECTORS(forward_in, forward, right, up);