diff --git a/libs/mathlib.h b/libs/mathlib.h index ae98071e..aafe568d 100644 --- a/libs/mathlib.h +++ b/libs/mathlib.h @@ -38,12 +38,12 @@ typedef vec_t vec3_t[3]; typedef vec_t vec5_t[5]; typedef vec_t vec4_t[4]; -// Smallest positive value such that 1.0 + VEC_SMALLEST_EPSILON != 1.0 -// In the case of 32 bits (which is the case), it's 0.00000011921. +// Smallest positive value such that 1.0 + VEC_SMALLEST_EPSILON_AROUND_ONE != 1.0. +// In the case of 32 bits (which is likely the case), it's 0.00000011921. // Don't forget that your epsilons should depend on the possible range of values, -// because for example 1000.0 + VEC_SMALLEST_EPSILON will almost certainly be -// equal to 1000.0. -#define VEC_SMALLEST_EPSILON FLT_EPSILON +// because for example adding VEC_SMALLEST_EPSILON_AROUND_ONE to 1024.0 will almost +// certainly not change its value. +#define VEC_SMALLEST_EPSILON_AROUND_ONE FLT_EPSILON #define SIDE_FRONT 0 #define SIDE_ON 2 @@ -316,12 +316,12 @@ vec_t ray_intersect_triangle(const ray_t *ray, qboolean bCullBack, const vec3_t typedef double vec_accu_t; typedef vec_accu_t vec3_accu_t[3]; -// Smallest positive value such that 1.0 + VEC_ACCU_SMALLEST_EPSILON != 1.0 -// In the case of 64 bits (which is the case), it's 0.00000000000000022204. +// Smallest positive value such that 1.0 + VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE != 1.0. +// In the case of 64 bits (which is likely the case), it's 0.00000000000000022204. // Don't forget that your epsilons should depend on the possible range of values, -// because for example 1000.0 + VEC_ACCU_SMALLEST_EPSILON will almost certainly -// be equal to 1000.0. -#define VEC_ACCU_SMALLEST_EPSILON DBL_EPSILON +// because for example adding VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE to 1024.0 will almost +// certainly not change its value. +#define VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE DBL_EPSILON // TODO: I have a feeling it may be safer to break these function out into actual functions // in order to avoid accidental loss of precision. For example, say you call diff --git a/tools/quake3/common/polylib.c b/tools/quake3/common/polylib.c index 93f15241..79eb3fb1 100644 --- a/tools/quake3/common/polylib.c +++ b/tools/quake3/common/polylib.c @@ -632,7 +632,18 @@ void ChopWindingInPlaceAccu(winding_accu_t **inout, vec3_t normal, vec_t dist, v // want the resolution of vec_accu_t to have a large resolution around the epsilon. // Some of that leftover resolution even goes away after we scale to points far away. - static const vec_accu_t smallestEpsilonAllowed = ((vec_accu_t) VEC_SMALLEST_EPSILON) * 0.5; + // Here is a further discussion regarding the choice of smallestEpsilonAllowed. + // In the 32 float world (we can assume vec_t is that), the "epsilon around 1.0" is + // 0.00000011921. In the 64 bit float world (we can assume vec_accu_t is that), the + // "epsilon around 1.0" is 0.00000000000000022204. (By the way these two epsilons + // are defined as VEC_SMALLEST_EPSILON_AROUND_ONE VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE + // respectively.) If you divide the first by the second, you get approximately + // 536,885,246. Dividing that number by 200,000 (a typical base winding coordinate) + // gives 2684. So in other words, if our smallestEpsilonAllowed was chosen as exactly + // VEC_SMALLEST_EPSILON_AROUND_ONE, you would be guaranteed at least 2000 "ticks" in + // 64-bit land inside of the epsilon for all numbers we're dealing with. + + static const vec_accu_t smallestEpsilonAllowed = ((vec_accu_t) VEC_SMALLEST_EPSILON_AROUND_ONE) * 0.5; if (crudeEpsilon < smallestEpsilonAllowed) fineEpsilon = smallestEpsilonAllowed; else fineEpsilon = (vec_accu_t) crudeEpsilon;