::zerowing-base=422
This commit is contained in:
@@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
// mathlib.h
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -40,6 +41,12 @@ typedef vec_t vec3_t[3];
|
||||
typedef vec_t vec5_t[5];
|
||||
typedef vec_t vec4_t[4];
|
||||
|
||||
// Smallest positive value for vec_t such that 1.0 + VEC_SMALLEST_EPSILON_AROUND_ONE != 1.0.
|
||||
// In the case of 32 bit floats (which is almost certainly the case), it's 0.00000011921.
|
||||
// Don't forget that your epsilons should depend on the possible range of values,
|
||||
// because for example adding VEC_SMALLEST_EPSILON_AROUND_ONE to 1024.0 will have no effect.
|
||||
#define VEC_SMALLEST_EPSILON_AROUND_ONE FLT_EPSILON
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_ON 2
|
||||
#define SIDE_BACK 1
|
||||
@@ -83,6 +90,9 @@ extern const vec3_t g_vec3_axis_z;
|
||||
|
||||
qboolean VectorCompare (const vec3_t v1, const vec3_t v2);
|
||||
|
||||
qboolean VectorIsOnAxis(vec3_t v);
|
||||
qboolean VectorIsOnAxialPlane(vec3_t v);
|
||||
|
||||
vec_t VectorLength(const vec3_t v);
|
||||
|
||||
void VectorMA( const vec3_t va, vec_t scale, const vec3_t vb, vec3_t vc );
|
||||
@@ -419,6 +429,50 @@ vec_t ray_intersect_plane(const ray_t* ray, const vec3_t normal, vec_t dist);
|
||||
int plane_intersect_planes(const vec4_t plane1, const vec4_t plane2, const vec4_t plane3, vec3_t intersection);
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Below is double-precision math stuff. This was initially needed by the new
|
||||
// "base winding" code in q3map2 brush processing in order to fix the famous
|
||||
// "disappearing triangles" issue. These definitions can be used wherever extra
|
||||
// precision is needed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef double vec_accu_t;
|
||||
typedef vec_accu_t vec3_accu_t[3];
|
||||
|
||||
// Smallest positive value for vec_accu_t such that 1.0 + VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE != 1.0.
|
||||
// In the case of 64 bit doubles (which is almost certainly the case), it's 0.00000000000000022204.
|
||||
// Don't forget that your epsilons should depend on the possible range of values,
|
||||
// because for example adding VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE to 1024.0 will have no effect.
|
||||
#define VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE DBL_EPSILON
|
||||
|
||||
vec_accu_t VectorLengthAccu(const vec3_accu_t v);
|
||||
|
||||
// I have a feeling it may be safer to break these #define functions out into actual functions
|
||||
// in order to avoid accidental loss of precision. For example, say you call
|
||||
// VectorScaleAccu(vec3_t, vec_t, vec3_accu_t). The scale would take place in 32 bit land
|
||||
// and the result would be cast to 64 bit, which would cause total loss of precision when
|
||||
// scaling by a large factor.
|
||||
//#define DotProductAccu(x, y) ((x)[0] * (y)[0] + (x)[1] * (y)[1] + (x)[2] * (y)[2])
|
||||
//#define VectorSubtractAccu(a, b, c) ((c)[0] = (a)[0] - (b)[0], (c)[1] = (a)[1] - (b)[1], (c)[2] = (a)[2] - (b)[2])
|
||||
//#define VectorAddAccu(a, b, c) ((c)[0] = (a)[0] + (b)[0], (c)[1] = (a)[1] + (b)[1], (c)[2] = (a)[2] + (b)[2])
|
||||
//#define VectorCopyAccu(a, b) ((b)[0] = (a)[0], (b)[1] = (a)[1], (b)[2] = (a)[2])
|
||||
//#define VectorScaleAccu(a, b, c) ((c)[0] = (b) * (a)[0], (c)[1] = (b) * (a)[1], (c)[2] = (b) * (a)[2])
|
||||
//#define CrossProductAccu(a, b, c) ((c)[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1], (c)[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2], (c)[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0])
|
||||
//#define Q_rintAccu(in) ((vec_accu_t) floor(in + 0.5))
|
||||
|
||||
vec_accu_t DotProductAccu(const vec3_accu_t a, const vec3_accu_t b);
|
||||
void VectorSubtractAccu(const vec3_accu_t a, const vec3_accu_t b, vec3_accu_t out);
|
||||
void VectorAddAccu(const vec3_accu_t a, const vec3_accu_t b, vec3_accu_t out);
|
||||
void VectorCopyAccu(const vec3_accu_t in, vec3_accu_t out);
|
||||
void VectorScaleAccu(const vec3_accu_t in, vec_accu_t scaleFactor, vec3_accu_t out);
|
||||
void CrossProductAccu(const vec3_accu_t a, const vec3_accu_t b, vec3_accu_t out);
|
||||
vec_accu_t Q_rintAccu(vec_accu_t val);
|
||||
|
||||
void VectorCopyAccuToRegular(const vec3_accu_t in, vec3_t out);
|
||||
void VectorCopyRegularToAccu(const vec3_t in, vec3_accu_t out);
|
||||
vec_accu_t VectorNormalizeAccu(const vec3_accu_t in, vec3_accu_t out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,54 @@ const vec3_t g_vec3_axis_x = { 1, 0, 0, };
|
||||
const vec3_t g_vec3_axis_y = { 0, 1, 0, };
|
||||
const vec3_t g_vec3_axis_z = { 0, 0, 1, };
|
||||
|
||||
/*
|
||||
================
|
||||
VectorIsOnAxis
|
||||
================
|
||||
*/
|
||||
qboolean VectorIsOnAxis(vec3_t v)
|
||||
{
|
||||
int i, zeroComponentCount;
|
||||
|
||||
zeroComponentCount = 0;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (v[i] == 0.0)
|
||||
{
|
||||
zeroComponentCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (zeroComponentCount > 1)
|
||||
{
|
||||
// The zero vector will be on axis.
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VectorIsOnAxialPlane
|
||||
================
|
||||
*/
|
||||
qboolean VectorIsOnAxialPlane(vec3_t v)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (v[i] == 0.0)
|
||||
{
|
||||
// The zero vector will be on axial plane.
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
MakeNormalVectors
|
||||
@@ -119,21 +167,30 @@ void _VectorCopy (vec3_t in, vec3_t out)
|
||||
}
|
||||
|
||||
vec_t VectorNormalize( const vec3_t in, vec3_t out ) {
|
||||
vec_t length, ilength;
|
||||
|
||||
length = (vec_t)sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
|
||||
// The sqrt() function takes double as an input and returns double as an
|
||||
// output according the the man pages on Debian and on FreeBSD. Therefore,
|
||||
// I don't see a reason why using a double outright (instead of using the
|
||||
// vec_accu_t alias for example) could possibly be frowned upon.
|
||||
|
||||
double x, y, z, length;
|
||||
|
||||
x = (double) in[0];
|
||||
y = (double) in[1];
|
||||
z = (double) in[2];
|
||||
|
||||
length = sqrt((x * x) + (y * y) + (z * z));
|
||||
if (length == 0)
|
||||
{
|
||||
VectorClear (out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ilength = 1.0f/length;
|
||||
out[0] = in[0]*ilength;
|
||||
out[1] = in[1]*ilength;
|
||||
out[2] = in[2]*ilength;
|
||||
out[0] = (vec_t) (x / length);
|
||||
out[1] = (vec_t) (y / length);
|
||||
out[2] = (vec_t) (z / length);
|
||||
|
||||
return length;
|
||||
return (vec_t) length;
|
||||
}
|
||||
|
||||
vec_t ColorNormalize( const vec3_t in, vec3_t out ) {
|
||||
@@ -584,3 +641,153 @@ void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
|
||||
dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Below is double-precision math stuff. This was initially needed by the new
|
||||
// "base winding" code in q3map2 brush processing in order to fix the famous
|
||||
// "disappearing triangles" issue. These definitions can be used wherever extra
|
||||
// precision is needed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorLengthAccu
|
||||
=================
|
||||
*/
|
||||
vec_accu_t VectorLengthAccu(const vec3_accu_t v)
|
||||
{
|
||||
return (vec_accu_t) sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
DotProductAccu
|
||||
=================
|
||||
*/
|
||||
vec_accu_t DotProductAccu(const vec3_accu_t a, const vec3_accu_t b)
|
||||
{
|
||||
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorSubtractAccu
|
||||
=================
|
||||
*/
|
||||
void VectorSubtractAccu(const vec3_accu_t a, const vec3_accu_t b, vec3_accu_t out)
|
||||
{
|
||||
out[0] = a[0] - b[0];
|
||||
out[1] = a[1] - b[1];
|
||||
out[2] = a[2] - b[2];
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorAddAccu
|
||||
=================
|
||||
*/
|
||||
void VectorAddAccu(const vec3_accu_t a, const vec3_accu_t b, vec3_accu_t out)
|
||||
{
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
out[2] = a[2] + b[2];
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorCopyAccu
|
||||
=================
|
||||
*/
|
||||
void VectorCopyAccu(const vec3_accu_t in, vec3_accu_t out)
|
||||
{
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorScaleAccu
|
||||
=================
|
||||
*/
|
||||
void VectorScaleAccu(const vec3_accu_t in, vec_accu_t scaleFactor, vec3_accu_t out)
|
||||
{
|
||||
out[0] = in[0] * scaleFactor;
|
||||
out[1] = in[1] * scaleFactor;
|
||||
out[2] = in[2] * scaleFactor;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CrossProductAccu
|
||||
=================
|
||||
*/
|
||||
void CrossProductAccu(const vec3_accu_t a, const vec3_accu_t b, vec3_accu_t out)
|
||||
{
|
||||
out[0] = (a[1] * b[2]) - (a[2] * b[1]);
|
||||
out[1] = (a[2] * b[0]) - (a[0] * b[2]);
|
||||
out[2] = (a[0] * b[1]) - (a[1] * b[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Q_rintAccu
|
||||
=================
|
||||
*/
|
||||
vec_accu_t Q_rintAccu(vec_accu_t val)
|
||||
{
|
||||
return (vec_accu_t) floor(val + 0.5);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorCopyAccuToRegular
|
||||
=================
|
||||
*/
|
||||
void VectorCopyAccuToRegular(const vec3_accu_t in, vec3_t out)
|
||||
{
|
||||
out[0] = (vec_t) in[0];
|
||||
out[1] = (vec_t) in[1];
|
||||
out[2] = (vec_t) in[2];
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorCopyRegularToAccu
|
||||
=================
|
||||
*/
|
||||
void VectorCopyRegularToAccu(const vec3_t in, vec3_accu_t out)
|
||||
{
|
||||
out[0] = (vec_accu_t) in[0];
|
||||
out[1] = (vec_accu_t) in[1];
|
||||
out[2] = (vec_accu_t) in[2];
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VectorNormalizeAccu
|
||||
=================
|
||||
*/
|
||||
vec_accu_t VectorNormalizeAccu(const vec3_accu_t in, vec3_accu_t out)
|
||||
{
|
||||
// The sqrt() function takes double as an input and returns double as an
|
||||
// output according the the man pages on Debian and on FreeBSD. Therefore,
|
||||
// I don't see a reason why using a double outright (instead of using the
|
||||
// vec_accu_t alias for example) could possibly be frowned upon.
|
||||
|
||||
vec_accu_t length;
|
||||
|
||||
length = (vec_accu_t) sqrt((in[0] * in[0]) + (in[1] * in[1]) + (in[2] * in[2]));
|
||||
if (length == 0)
|
||||
{
|
||||
VectorClear(out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
out[0] = in[0] / length;
|
||||
out[1] = in[1] / length;
|
||||
out[2] = in[2] / length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user