Importing code changes for q3map2 from Rambetter-math-fix-experiments branch
into trunk. Right now all the new code that fixes problems is turned off. There are three new #defines in q3map2.h: EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES, EXPERIMENTAL_SNAP_NORMAL_FIX, and EXPERIMENTAL_SNAP_PLANE_FIX. All of these are currently set to 0, which means don't enable that new code. You can easily edit these to be 1 in order to enable the new code. There are very very minor changes to the code even with these three #defines disabled. They are as follows. - In PlaneEqual() in map.c, now considering deltas equal to given epsilon values as "far enough to be different". Previously, the '<=' operation was used, now '<' is being used. - In FindFloatPlane() in map.c, considering delta equal to distanceEpsilon (for plane distance) to be sufficiently far away. Before, delta had to be strictly greater than distanceEpsilon. - VectorNormalize() in mathlib.c is more accurate now. This change itself causes at least one regression test to succeed. The previous implementation of VectorNormalize() caused excessive errors to be introduced due to sloppy arithmetic. Note, the epsilon changes account for the possibility that the epsilons are set to 0.0 on the command-line. git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@416 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
@@ -26,6 +26,54 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
vec3_t vec3_origin = {0.0f,0.0f,0.0f};
|
||||
|
||||
/*
|
||||
================
|
||||
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
|
||||
@@ -127,21 +175,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 ) {
|
||||
@@ -591,3 +648,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