Author: rambetter
authorRudolf Polzer <divverent@alientrap.org>
Wed, 29 Dec 2010 16:41:57 +0000 (17:41 +0100)
committerRudolf Polzer <divverent@alientrap.org>
Wed, 29 Dec 2010 16:41:57 +0000 (17:41 +0100)
New Revision: 379
Undoing revision 377 (reverting just those files modified by that
commit).  I have disovered the fundamental problem to the math error problems,
and although this commit (r377) is "correct", it fails to address the
fundamental problem.  Therefore, I'd rather leave the code in a state that
has the exact same behavior as before until I get a chance to address the
fundamental issue.

libs/mathlib.h
libs/mathlib/mathlib.c
tools/quake3/common/polylib.c

index d206d33..1a86094 100644 (file)
@@ -89,6 +89,7 @@ void VectorMA( const vec3_t va, vec_t scale, const vec3_t vb, vec3_t vc );
 
 void _CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
 vec_t VectorNormalize (const vec3_t in, vec3_t out);
+vec_t VectorSetLength (const vec3_t in, vec_t length, vec3_t out);
 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 7daf27b..0d134a5 100644 (file)
@@ -135,6 +135,21 @@ vec_t VectorNormalize( const vec3_t in, vec3_t out ) {
        return length;
 }
 
+vec_t VectorSetLength(const vec3_t in, vec_t length, vec3_t out) {
+       vec_t   origLength;
+
+       origLength = (vec_t) sqrt((in[0] * in[0]) + (in[1] * in[1]) + (in[2] * in[2]));
+       if (origLength == 0)
+       {
+               VectorClear(out);
+               return 0;
+       }
+
+       VectorScale(in, length / origLength, out);
+
+       return origLength;
+}
+
 vec_t ColorNormalize( const vec3_t in, vec3_t out ) {
        float   max, scale;
 
index 27d64d1..b62d12f 100644 (file)
@@ -219,8 +219,10 @@ winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
        // Once these vectors are calculated, I'm constructing the winding points in exactly the same
        // way as was done in the original function.  Orientation is the same.
 
-       // EDIT: We're also changing the size of the winding polygon; this is a side effect of
-       // eliminating a VectorNormalize() call.  The new winding polygon is actually bigger.
+       // Note that the 4 points in the returned winding_t may actually not be necessary (3 might
+       // be enough).  However, I want to minimize the chance of ANY bugs popping up due to any
+       // change in behavior of this function.  Therefore, behavior stays exactly the same, except
+       // for precision of math.  Performance might be better in the new function as well.
 
        int             x, i;
        vec_t           max, v;
@@ -251,42 +253,15 @@ winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
                        vright[2] = normal[1];
                        break;
        }
-       // vright and normal are now perpendicular, you can prove this by taking their
-       // dot product and seeing that it's always exactly 0 (with no error).
-
-       // NOTE: vright is NOT a unit vector at this point.  vright will have length
-       // not exceeding 1.0.  The minimum length that vright can achieve happens when,
-       // for example, the Z and X components of the normal input vector are equal,
-       // and when its Y component is zero.  In that case Z and X of the normal vector
-       // are both approximately 0.70711.  The resulting vright vector in this case
-       // will have a length of 0.70711.
-
-       // We're relying on the fact that MAX_WORLD_COORD is a power of 2 to keep
-       // our calculation precise and relatively free of floating point error.
-       // The code will work if that's not the case, but not as well.
-       VectorScale(vright, MAX_WORLD_COORD * 4, vright);
-
-       // At time time of this writing, MAX_WORLD_COORD was 65536 (2^16).  Therefore
-       // the length of vright at this point is at least 185364.  A corner of the world
-       // at location (65536, 65536, 65536) is distance 113512 away from the origin.
-
        CrossProduct(normal, vright, vup);
 
-       // vup now has length equal to that of vright.
+       // IMPORTANT NOTE: vright and vup are NOT unit vectors at this point.
+       // However, normal, vup, and vright are pairwise perpendicular.
 
+       VectorSetLength(vup, MAX_WORLD_COORD * 2, vup);
+       VectorSetLength(vright, MAX_WORLD_COORD * 2, vright);
        VectorScale(normal, dist, org);
 
-       // org is now a point on the plane defined by normal and dist.  Furthermore,
-       // org, vright, and vup are pairwise perpendicular.  Now, the 4 vectors
-       // (+-)vright + (+-)vup have length that is at least sqrt(185364^2 + 185364^2),
-       // which is about 262144.  That length lies outside the world, since the furthest
-       // point in the world has distance 113512 from the origin as mentioned above.
-       // Also, these 4 vectors are perpendicular to the org vector.  So adding them
-       // to org will only increase their length.  Therefore the 4 points defined below
-       // all lie outside of the world.  Furthermore, it can be easily seen that the
-       // edges connecting these 4 points (in the winding_t below) lie completely outside
-       // the world.  sqrt(262144^2 + 262144^2)/2 = 185363, which is greater than 113512.
-
        w = AllocWinding(4);
 
        VectorSubtract(org, vright, w->p[0]);