// I need this define in order to test some of the regression tests from time to time.
// This define affect the precision of VectorNormalize() function only.
#define MATHLIB_VECTOR_NORMALIZE_PRECISION_FIX 1
- vec_t VectorNormalize( const vec3_t in, vec3_t out );
-vec_t VectorAccurateNormalize (const vec3_t in, vec3_t out);
-vec_t VectorFastNormalize (const vec3_t in, vec3_t out);
++vec_t VectorAccurateNormalize( const vec3_t in, vec3_t out );
++vec_t VectorFastNormalize( const vec3_t in, vec3_t out );
+ #if MATHLIB_VECTOR_NORMALIZE_PRECISION_FIX
+ #define VectorNormalize VectorAccurateNormalize
+ #else
+ #define VectorNormalize VectorFastNormalize
+ #endif
vec_t ColorNormalize( const vec3_t in, vec3_t out );
-void VectorInverse (vec3_t v);
-void VectorPolar(vec3_t v, float radius, float theta, float phi);
+void VectorInverse( vec3_t v );
+void VectorPolar( vec3_t v, float radius, float theta, float phi );
// default snapping, to 1
-void VectorSnap(vec3_t v);
+void VectorSnap( vec3_t v );
// integer snapping
-void VectorISnap(vec3_t point, int snap);
+void VectorISnap( vec3_t point, int snap );
// Gef: added snap to float for sub-integer grid sizes
// TTimo: we still use the int version of VectorSnap when possible
return 0;
}
- out[0] = (vec_t) (x / length);
- out[1] = (vec_t) (y / length);
- out[2] = (vec_t) (z / length);
+ out[0] = (vec_t) ( x / length );
+ out[1] = (vec_t) ( y / length );
+ out[2] = (vec_t) ( z / length );
return (vec_t) length;
+ }
- #else
+ vec_t VectorFastNormalize( const vec3_t in, vec3_t out ) {
- vec_t length, ilength;
+ // SmileTheory: This is ioquake3's VectorNormalize2
+ // for when accuracy matters less than speed
- float length, ilength;
-
- length = in[0]*in[0] + in[1]*in[1] + in[2]*in[2];
-
- if (length)
- {
- /* writing it this way allows gcc to recognize that rsqrt can be used */
- ilength = 1/(float)sqrt (length);
- /* sqrt(length) = length * (1 / sqrt(length)) */
- length *= ilength;
- out[0] = in[0]*ilength;
- out[1] = in[1]*ilength;
- out[2] = in[2]*ilength;
- } else {
- VectorClear( out );
- }
++ float length, ilength;
+
- length = (vec_t)sqrt( in[0] * in[0] + in[1] * in[1] + in[2] * in[2] );
- if ( length == 0 ) {
++ length = in[0] * in[0] + in[1] * in[1] + in[2] * in[2];
++
++ if ( length ) {
++ /* writing it this way allows gcc to recognize that rsqrt can be used */
++ ilength = 1 / (float)sqrt( length );
++ /* sqrt(length) = length * (1 / sqrt(length)) */
++ length *= ilength;
++ out[0] = in[0] * ilength;
++ out[1] = in[1] * ilength;
++ out[2] = in[2] * ilength;
++ }
++ else {
+ VectorClear( out );
- return 0;
+ }
- ilength = 1.0f / length;
- out[0] = in[0] * ilength;
- out[1] = in[1] * ilength;
- out[2] = in[2] * ilength;
-
- return length;
+ return length;
-
- #endif
-
}
vec_t ColorNormalize( const vec3_t in, vec3_t out ) {
/*
-PointToPolygonFormFactor()
-calculates the area over a point/normal hemisphere a winding covers
-ydnar: fixme: there has to be a faster way to calculate this
-without the expensive per-vert sqrts and transcendental functions
-ydnar 2002-09-30: added -faster switch because only 19% deviance > 10%
-between this and the approximation
-*/
+ PointToPolygonFormFactor()
+ calculates the area over a point/normal hemisphere a winding covers
+ ydnar: fixme: there has to be a faster way to calculate this
+ without the expensive per-vert sqrts and transcendental functions
+ ydnar 2002-09-30: added -faster switch because only 19% deviance > 10%
+ between this and the approximation
+ */
+
+#define ONE_OVER_2PI 0.159154942f //% (1.0f / (2.0f * 3.141592657f))
+
+float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ){
+ vec3_t triVector, triNormal;
+ int i, j;
+ vec3_t dirs[ MAX_POINTS_ON_WINDING ];
+ float total;
+ float dot, angle, facing;
-#define ONE_OVER_2PI 0.159154942f //% (1.0f / (2.0f * 3.141592657f))
-float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w )
-{
- vec3_t triVector, triNormal;
- int i, j;
- vec3_t dirs[ MAX_POINTS_ON_WINDING ];
- float total;
- float dot, angle, facing;
-
-
/* this is expensive */
- for( i = 0; i < w->numpoints; i++ )
+ for ( i = 0; i < w->numpoints; i++ )
{
VectorSubtract( w->p[ i ], point, dirs[ i ] );
- VectorNormalize( dirs[ i ], dirs[ i ] );
+ VectorFastNormalize( dirs[ i ], dirs[ i ] );
}
-
+
/* duplicate first vertex to avoid mod operation */
VectorCopy( dirs[ 0 ], dirs[ i ] );
-
+
/* calculcate relative area */
total = 0.0f;
- for( i = 0; i < w->numpoints; i++ )
+ for ( i = 0; i < w->numpoints; i++ )
{
/* get a triangle */
j = i + 1;
dot = DotProduct( dirs[ i ], dirs[ j ] );
-
+
/* roundoff can cause slight creep, which gives an IND from acos */
- if( dot > 1.0f )
+ if ( dot > 1.0f ) {
dot = 1.0f;
- else if( dot < -1.0f )
+ }
+ else if ( dot < -1.0f ) {
dot = -1.0f;
-
+ }
+
/* get the angle */
angle = acos( dot );
-
+
CrossProduct( dirs[ i ], dirs[ j ], triVector );
- if ( VectorNormalize( triVector, triNormal ) < 0.0001f ) {
- if( VectorFastNormalize( triVector, triNormal ) < 0.0001f )
++ if ( VectorFastNormalize( triVector, triNormal ) < 0.0001f ) {
continue;
-
+ }
+
facing = DotProduct( normal, triNormal );
total += facing * angle;
-
+
/* ydnar: this was throwing too many errors with radiosity + crappy maps. ignoring it. */
- if( total > 6.3f || total < -6.3f )
+ if ( total > 6.3f || total < -6.3f ) {
return 0.0f;
+ }
}
-
+
/* now in the range of 0 to 1 over the entire incoming hemisphere */
//% total /= (2.0f * 3.141592657f);
total *= ONE_OVER_2PI;
/*
-TraceLine_r()
-returns qtrue if something is hit and tracing can stop
+ TraceLine_r()
+ returns qtrue if something is hit and tracing can stop
+
-SmileTheory: made half-iterative
-*/
++ SmileTheory: made half-iterative
+ */
- static qboolean TraceLine_r( int nodeNum, vec3_t origin, vec3_t end, trace_t *trace ){
+ #define TRACELINE_R_HALF_ITERATIVE 1
+
+ #if TRACELINE_R_HALF_ITERATIVE
+ static qboolean TraceLine_r( int nodeNum, const vec3_t start, const vec3_t end, trace_t *trace )
+ #else
+ static qboolean TraceLine_r( int nodeNum, const vec3_t origin, const vec3_t end, trace_t *trace )
+ #endif
+ {
- traceNode_t *node;
- int side;
- float front, back, frac;
- vec3_t origin, mid;
- qboolean r;
-
+ traceNode_t *node;
+ int side;
+ float front, back, frac;
- vec3_t mid;
++ vec3_t origin, mid;
+ qboolean r;
+
+ #if TRACELINE_R_HALF_ITERATIVE
+ VectorCopy( start, origin );
- /* bogus node number means solid, end tracing unless testing all */
- if ( nodeNum < 0 ) {
- VectorCopy( origin, trace->hit );
- trace->passSolid = qtrue;
- return qtrue;
- }
- while( 1 )
++ while ( 1 )
+ #endif
+ {
+ /* bogus node number means solid, end tracing unless testing all */
- if( nodeNum < 0 )
- {
++ if ( nodeNum < 0 ) {
+ VectorCopy( origin, trace->hit );
+ trace->passSolid = qtrue;
+ return qtrue;
+ }
-
+
- /* get node */
- node = &traceNodes[ nodeNum ];
+ /* get node */
+ node = &traceNodes[ nodeNum ];
-
+
- /* solid? */
- if ( node->type == TRACE_LEAF_SOLID ) {
- VectorCopy( origin, trace->hit );
- trace->passSolid = qtrue;
- return qtrue;
- }
+ /* solid? */
- if( node->type == TRACE_LEAF_SOLID )
- {
++ if ( node->type == TRACE_LEAF_SOLID ) {
+ VectorCopy( origin, trace->hit );
+ trace->passSolid = qtrue;
+ return qtrue;
+ }
-
+
- /* leafnode? */
- if ( node->type < 0 ) {
- /* note leaf and return */
- if ( node->numItems > 0 && trace->numTestNodes < MAX_TRACE_TEST_NODES ) {
- trace->testNodes[ trace->numTestNodes++ ] = nodeNum;
+ /* leafnode? */
- if( node->type < 0 )
- {
- /* note leaf and return */
- if( node->numItems > 0 && trace->numTestNodes < MAX_TRACE_TEST_NODES )
++ if ( node->type < 0 ) {
++ /* note leaf and return */
++ if ( node->numItems > 0 && trace->numTestNodes < MAX_TRACE_TEST_NODES ) {
+ trace->testNodes[ trace->numTestNodes++ ] = nodeNum;
++ }
+ return qfalse;
}
- return qfalse;
- }
-
+
- /* ydnar 2003-09-07: don't test branches of the bsp with nothing in them when testall is enabled */
- if ( trace->testAll && node->numItems == 0 ) {
- return qfalse;
- }
+ /* ydnar 2003-09-07: don't test branches of the bsp with nothing in them when testall is enabled */
- if( trace->testAll && node->numItems == 0 )
++ if ( trace->testAll && node->numItems == 0 ) {
+ return qfalse;
-
++ }
+
- /* classify beginning and end points */
- switch ( node->type )
- {
- case PLANE_X:
- front = origin[ 0 ] - node->plane[ 3 ];
- back = end[ 0 ] - node->plane[ 3 ];
- break;
+ /* classify beginning and end points */
- switch( node->type )
++ switch ( node->type )
+ {
- case PLANE_X:
- front = origin[ 0 ] - node->plane[ 3 ];
- back = end[ 0 ] - node->plane[ 3 ];
- break;
-
- case PLANE_Y:
- front = origin[ 1 ] - node->plane[ 3 ];
- back = end[ 1 ] - node->plane[ 3 ];
- break;
-
- case PLANE_Z:
- front = origin[ 2 ] - node->plane[ 3 ];
- back = end[ 2 ] - node->plane[ 3 ];
- break;
-
- default:
- front = DotProduct( origin, node->plane ) - node->plane[ 3 ];
- back = DotProduct( end, node->plane ) - node->plane[ 3 ];
- break;
++ case PLANE_X:
++ front = origin[ 0 ] - node->plane[ 3 ];
++ back = end[ 0 ] - node->plane[ 3 ];
++ break;
+
- case PLANE_Y:
- front = origin[ 1 ] - node->plane[ 3 ];
- back = end[ 1 ] - node->plane[ 3 ];
- break;
++ case PLANE_Y:
++ front = origin[ 1 ] - node->plane[ 3 ];
++ back = end[ 1 ] - node->plane[ 3 ];
++ break;
+
- case PLANE_Z:
- front = origin[ 2 ] - node->plane[ 3 ];
- back = end[ 2 ] - node->plane[ 3 ];
- break;
++ case PLANE_Z:
++ front = origin[ 2 ] - node->plane[ 3 ];
++ back = end[ 2 ] - node->plane[ 3 ];
++ break;
+
- default:
- front = DotProduct( origin, node->plane ) - node->plane[ 3 ];
- back = DotProduct( end, node->plane ) - node->plane[ 3 ];
- break;
- }
++ default:
++ front = DotProduct( origin, node->plane ) - node->plane[ 3 ];
++ back = DotProduct( end, node->plane ) - node->plane[ 3 ];
++ break;
+ }
-
+
- /* entirely in front side? */
- if ( front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON ) {
- return TraceLine_r( node->children[ 0 ], origin, end, trace );
- }
+ /* entirely in front side? */
- if( front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON )
- {
++ if ( front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON ) {
+ #if TRACELINE_R_HALF_ITERATIVE
+ nodeNum = node->children[ 0 ];
+ continue;
+ #else
+ return TraceLine_r( node->children[ 0 ], origin, end, trace );
+ #endif
+ }
-
+
- /* entirely on back side? */
- if ( front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON ) {
- return TraceLine_r( node->children[ 1 ], origin, end, trace );
- }
+ /* entirely on back side? */
- if( front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON )
- {
++ if ( front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON ) {
+ #if TRACELINE_R_HALF_ITERATIVE
+ nodeNum = node->children[ 1 ];
+ continue;
+ #else
+ return TraceLine_r( node->children[ 1 ], origin, end, trace );
+ #endif
+ }
-
+
- /* select side */
- side = front < 0;
+ /* select side */
+ side = front < 0;
-
+
- /* calculate intercept point */
- frac = front / ( front - back );
- mid[ 0 ] = origin[ 0 ] + ( end[ 0 ] - origin[ 0 ] ) * frac;
- mid[ 1 ] = origin[ 1 ] + ( end[ 1 ] - origin[ 1 ] ) * frac;
- mid[ 2 ] = origin[ 2 ] + ( end[ 2 ] - origin[ 2 ] ) * frac;
+ /* calculate intercept point */
- frac = front / (front - back);
- mid[ 0 ] = origin[ 0 ] + (end[ 0 ] - origin[ 0 ]) * frac;
- mid[ 1 ] = origin[ 1 ] + (end[ 1 ] - origin[ 1 ]) * frac;
- mid[ 2 ] = origin[ 2 ] + (end[ 2 ] - origin[ 2 ]) * frac;
-
++ frac = front / ( front - back );
++ mid[ 0 ] = origin[ 0 ] + ( end[ 0 ] - origin[ 0 ] ) * frac;
++ mid[ 1 ] = origin[ 1 ] + ( end[ 1 ] - origin[ 1 ] ) * frac;
++ mid[ 2 ] = origin[ 2 ] + ( end[ 2 ] - origin[ 2 ] ) * frac;
+
- /* fixme: check inhibit radius, then solid nodes and ignore */
+ /* fixme: check inhibit radius, then solid nodes and ignore */
-
+
- /* set trace hit here */
- //% VectorCopy( mid, trace->hit );
+ /* set trace hit here */
+ //% VectorCopy( mid, trace->hit );
-
+
- /* trace first side */
- r = TraceLine_r( node->children[ side ], origin, mid, trace );
- if ( r ) {
- return r;
- }
+ /* trace first side */
- if( TraceLine_r( node->children[ side ], origin, mid, trace ) )
++ if ( TraceLine_r( node->children[ side ], origin, mid, trace ) ) {
+ return qtrue;
-
++ }
+
- /* trace other side */
- return TraceLine_r( node->children[ !side ], mid, end, trace );
+ /* trace other side */
+ #if TRACELINE_R_HALF_ITERATIVE
+ nodeNum = node->children[ !side ];
+ VectorCopy( mid, origin );
+ #else
+ return TraceLine_r( node->children[ !side ], mid, end, trace );
+ #endif
+ }
}
/*
-SetupTrace() - ydnar
-sets up certain trace values
-*/
+ SetupTrace() - ydnar
+ sets up certain trace values
+ */
-float SetupTrace( trace_t *trace )
-{
+float SetupTrace( trace_t *trace ){
VectorSubtract( trace->end, trace->origin, trace->displacement );
- trace->distance = VectorNormalize( trace->displacement, trace->direction );
+ trace->distance = VectorFastNormalize( trace->displacement, trace->direction );
VectorCopy( trace->origin, trace->hit );
return trace->distance;
}