]> git.rm.cloudns.org Git - xonotic/netradiant.git/commitdiff
patch to speed up map compiling:
authorJames Canete <smiletheory@gmail.com>
Wed, 22 Feb 2012 12:48:48 +0000 (13:48 +0100)
committerRudolf Polzer <divverent@xonotic.org>
Wed, 22 Feb 2012 12:48:48 +0000 (13:48 +0100)
kill tail recursion in TraceLine_r
speed up normalizing again where the full accuracy is not necessary

libs/mathlib.h
libs/mathlib/mathlib.c
tools/quake3/q3map2/light.c
tools/quake3/q3map2/light_trace.c

index 382933d7afce201d4aa125ef183b061353eb893e..02ed6fd0913232e36c8c7a74ba2e8c815dbe7c3e 100644 (file)
@@ -101,7 +101,13 @@ void _CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
 // 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);
+#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);
index 98fb972a28aa9aa5eedf4fa2542fdbc0d3eadec4..41d1496dc13ce023b51623f45a7e7dedccf05952 100644 (file)
@@ -166,9 +166,7 @@ void _VectorCopy (vec3_t in, vec3_t out)
        out[2] = in[2];
 }
 
-vec_t VectorNormalize( const vec3_t in, vec3_t out ) {
-
-#if MATHLIB_VECTOR_NORMALIZE_PRECISION_FIX
+vec_t VectorAccurateNormalize( const vec3_t in, vec3_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,
@@ -193,27 +191,30 @@ vec_t VectorNormalize( const vec3_t in, vec3_t out ) {
        out[2] = (vec_t) (z / length);
 
        return (vec_t) length;
+}
 
-#else
-
-       vec_t   length, ilength;
-
-       length = (vec_t)sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
-       if (length == 0)
-       {
-               VectorClear (out);
-               return 0;
-       }
+vec_t VectorFastNormalize( const vec3_t in, vec3_t out ) {
 
-       ilength = 1.0f/length;
-       out[0] = in[0]*ilength;
-       out[1] = in[1]*ilength;
-       out[2] = in[2]*ilength;
+       // SmileTheory: This is ioquake3's VectorNormalize2
+       //              for when accuracy matters less than speed
+    float   length, ilength;
 
-       return length;
+    length = in[0]*in[0] + in[1]*in[1] + in[2]*in[2];
 
-#endif
+    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 length;
 }
 
 vec_t ColorNormalize( const vec3_t in, vec3_t out ) {
index db1cc576c96d2e39e8b9baf789ebfabbd5038a34..fe4bcf1b49b8688b704a02acc98518ecba352b5c 100644 (file)
@@ -702,7 +702,7 @@ float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const w
        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 */
@@ -726,7 +726,7 @@ float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const w
                angle = acos( dot );
                
                CrossProduct( dirs[ i ], dirs[ j ], triVector );
-               if( VectorNormalize( triVector, triNormal ) < 0.0001f )
+               if( VectorFastNormalize( triVector, triNormal ) < 0.0001f )
                        continue;
                
                facing = DotProduct( normal, triNormal );
index d0b72d35968ef58d06c7afc82a0630c2a64800fe..e7c3b0190362f958ad9efe083027b989ce3eaa0a 100644 (file)
@@ -1581,102 +1581,134 @@ qboolean TraceWinding( traceWinding_t *tw, trace_t *trace )
 /*
 TraceLine_r()
 returns qtrue if something is hit and tracing can stop
+
+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                  mid;
+       vec3_t                  origin, mid;
        qboolean                r;
-
-       
-       /* bogus node number means solid, end tracing unless testing all */
-       if( nodeNum < 0 )
-       {
-               VectorCopy( origin, trace->hit );
-               trace->passSolid = qtrue;
-               return qtrue;
-       }
-       
-       /* get node */
-       node = &traceNodes[ nodeNum ];
-       
-       /* 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;
-               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;
-       
-       /* classify beginning and end points */
-       switch( node->type )
+#if TRACELINE_R_HALF_ITERATIVE
+       VectorCopy( start, origin );
+
+       while( 1 )
+#endif
        {
-               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;
+               /* bogus node number means solid, end tracing unless testing all */
+               if( nodeNum < 0 )
+               {
+                       VectorCopy( origin, trace->hit );
+                       trace->passSolid = qtrue;
+                       return qtrue;
+               }
+               
+               /* get node */
+               node = &traceNodes[ nodeNum ];
+               
+               /* 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;
+                       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;
+               
+               /* classify beginning and end points */
+               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;
+               }
+               
+               /* entirely in front side? */
+               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 )
+               {
+#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;
+               
+               /* 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;
+               
+               /* fixme: check inhibit radius, then solid nodes and ignore */
+               
+               /* set trace hit here */
+               //%     VectorCopy( mid, trace->hit );
+               
+               /* trace first side */
+               if( TraceLine_r( node->children[ side ], origin, mid, trace ) )
+                       return qtrue;
+               
+               /* 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
        }
-       
-       /* entirely in front side? */
-       if( front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON )
-               return TraceLine_r( node->children[ 0 ], origin, end, trace );
-       
-       /* entirely on back side? */
-       if( front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON )
-               return TraceLine_r( node->children[ 1 ], origin, end, trace );
-       
-       /* 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;
-       
-       /* fixme: check inhibit radius, then solid nodes and ignore */
-       
-       /* 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 other side */
-       return TraceLine_r( node->children[ !side ], mid, end, trace );
 }
 
 
@@ -1754,7 +1786,7 @@ sets up certain trace values
 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;
 }