This is in branch Rambetter-math-fix-experiments.

- Adding a bunch of *Accu() functions:
    * SnapWeldVectorAccu() in brush.c (needs major proofread).
    * FixWindingAccu() in brush.c (needs major proofread).
    * CopyWindingAccuToNormal()	in polylib.c.
    * VectorLengthAccu() in mathlib.c.
    * Q_rintAccu() in mathlib.h.
    * FreeWindingAccu() declaration in polylib.h (was missing).

- Adding a #ifdef's for EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES.
It's turned on now.  Testing brush winding formation.

This code compiles on Linux, I have no idea if it works.  About to test	a
little,	then going to bed.


git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/Rambetter-math-fix-experiments@384 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
rambetter 2010-12-30 11:57:13 +00:00
parent adf336fec1
commit f32b2b3712
5 changed files with 114 additions and 0 deletions

View file

@ -335,6 +335,9 @@ typedef vec_accu_t vec3_accu_t[3];
#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 VectorLengthAccu(vec3_accu_t v);
#ifdef __cplusplus
}

View file

@ -63,6 +63,11 @@ vec_t VectorLength(vec3_t v)
return length;
}
vec_accu_t VectorLengthAccu(vec3_accu_t v)
{
return (vec_accu_t) sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]));
}
qboolean VectorCompare (vec3_t v1, vec3_t v2)
{
int i;

View file

@ -459,6 +459,28 @@ winding_t *CopyWinding (winding_t *w)
return c;
}
/*
==================
CopyWindingAccuToNormal
==================
*/
winding_t *CopyWindingAccuToNormal(winding_accu_t *w)
{
int i;
winding_t *c;
c = AllocWinding(w->numpoints);
c->numpoints = w->numpoints;
for (i = 0; i < c->numpoints; i++)
{
// TODO: Add VectorCopyAccuToNormal() to mathlib.h.
c->p[i][0] = (vec_t) w->p[i][0];
c->p[i][1] = (vec_t) w->p[i][1];
c->p[i][2] = (vec_t) w->p[i][2];
}
return c;
}
/*
==================
ReverseWinding

View file

@ -70,3 +70,5 @@ typedef struct
winding_accu_t *BaseWindingForPlaneAccu(vec3_t normal, vec_t dist);
void ChopWindingInPlaceAccu(winding_accu_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
winding_t *CopyWindingAccuToNormal(winding_accu_t *w);
void FreeWindingAccu(winding_accu_t *w);

View file

@ -277,6 +277,34 @@ void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out )
}
}
void SnapWeldVectorAccu(vec3_accu_t a, vec3_accu_t b, vec3_accu_t out)
{
// I have very serious concerns about this function.
// This is a first pass where I just copy the original SnapWeldVector()
// and make sure it works with the higher resolution data types.
// TODO: Examine this function with a fine-toothed comb.
int i;
vec_accu_t ai, bi, outi;
if (a == NULL || b == NULL || out == NULL) return;
for (i = 0; i < 3; i++)
{
ai = Q_rintAccu(a[i]);
bi = Q_rintAccu(a[i]); // Note, it's using a[i]. This is from legacy code.
if (ai == a[i]) out[i] = a[i];
else if (bi == b[i]) out[i] = b[i];
else if (fabs(ai - a[i]) < fabs(bi < b[i])) out[i] = a[i];
else out[i] = b[i];
outi = Q_rintAccu(out[i]);
if (fabs(outi - out[i]) <= SNAP_EPSILON) out[i] = outi;
}
}
/*
@ -338,11 +366,44 @@ qboolean FixWinding( winding_t *w )
return valid;
}
qboolean FixWindingAccu(winding_accu_t *w)
{
// Serious doubts about this function. Will check it out later.
// This is just a copy from the original for high res data types.
// TODO: Examine this function with a fine-toothed comb.
qboolean valid = qtrue;
int i, j, k;
vec3_accu_t vec;
vec_accu_t dist;
if (!w) return qfalse;
for (i = 0; i < w->numpoints; i++)
{
if (w->numpoints == 3) return valid;
j = (i + 1) % w->numpoints;
VectorSubtractAccu(w->p[i], w->p[j], vec);
dist = VectorLengthAccu(vec);
if (dist < DEGENERATE_EPSILON)
{
valid = qfalse;
SnapWeldVectorAccu(w->p[i], w->p[j], vec);
VectorCopyAccu(vec, w->p[i]);
for (k = i + 2; k < w->numpoints; k++) {
VectorCopyAccu(w->p[k], w->p[k - 1]);
}
w->numpoints--;
}
}
if (w->numpoints < 3) valid = qfalse;
return valid;
}
#define EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES 1
/*
CreateBrushWindings()
@ -353,7 +414,11 @@ returns false if the brush doesn't enclose a valid volume
qboolean CreateBrushWindings( brush_t *brush )
{
int i, j;
#ifdef EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES
winding_accu_t *w;
#else
winding_t *w;
#endif
side_t *side;
plane_t *plane;
@ -366,7 +431,11 @@ qboolean CreateBrushWindings( brush_t *brush )
plane = &mapplanes[ side->planenum ];
/* make huge winding */
#ifdef EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES
w = BaseWindingForPlaneAccu(plane->normal, plane->dist);
#else
w = BaseWindingForPlane( plane->normal, plane->dist );
#endif
/* walk the list of brush sides */
for( j = 0; j < brush->numsides && w != NULL; j++ )
@ -378,14 +447,27 @@ qboolean CreateBrushWindings( brush_t *brush )
if( brush->sides[ j ].bevel )
continue;
plane = &mapplanes[ brush->sides[ j ].planenum ^ 1 ];
#ifdef EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES
ChopWindingInPlaceAccu(&w, plane->normal, plane->dist, 0);
#else
ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON );
#endif
/* ydnar: fix broken windings that would generate trifans */
#ifdef EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES
FixWindingAccu(w);
#else
FixWinding( w );
#endif
}
/* set side winding */
#ifdef EXPERIMENTAL_HIGH_PRECISION_MATH_Q3MAP2_FIXES
side->winding = CopyWindingAccuToNormal(w);
FreeWindingAccu(w);
#else
side->winding = w;
#endif
}
/* find brush bounds */