Go to notes and algorithms index. ~ Go to home page.

fp_distance() and fp_length()


Floating Point Version, using a triginomic emulation formula.

The first function finds the distance between two points, and the second function finds the length of a vector line.




// These routines are formula based and not look-up table based.  They have
// been quickly converted from the integer versions and have not been fine-tuned
// for better accuracy etc.
// Jon P 26-April-2003

#define TINY_FLOAT 0.000001f


float fp_length( float p_dx, float p_dy, float p_dz )
   {
   //
   // (C) of Jon E P 1998.
   // This is the floating point version -- (c) Jon P, 2003.
   //
   //
   //
   register float temp, temp2;
   float a, c, dz;

   temp = p_dx;
   if ( temp < 0 ) temp = 0.0f - temp;

   temp2 = p_dy;
   if ( temp2 < 0 ) temp2 = 0.0f - temp;

   dz = p_dz;
   if ( dz < 0 ) dz = 0.0f - temp;

   // The variable you might expect to be called 'b' is replaced by 'temp',
   // also note that 'temp' is redefined later-on and ceases to correspond to 'b'.
   // (this enables register use without the register having to be coloured)
   if ( temp >= temp2 && temp >= dz )
      {
      a = temp; // 'a' = longest dimension.
      temp = temp2;
      c = dz;
      }
   else
      {
      if ( temp2 >= temp && temp2 >= dz )
         {
         a = temp2; // 'a' = longest dimension.
         //temp = dx;
         c = dz;
         }
      else
         {
         a = dz; // 'a' = longest dimension.
         //temp = dx;
         c = temp2;
         }
      }

   // The above IF statement has sorted ordinates:-
   //    'a' will be the largest ordinate.
   //    'temp' will be the second largest ordinate.
   //    'b' will be the smallest ordinate.

   if ( a < TINY_FLOAT ) return a; // line had zero or near zero length.

   if ( temp < TINY_FLOAT ) return a; // line was perpendicular with co-ordinate system
   //                                 (or near enough).
   
   temp /= a;
   temp2 = temp * temp;
   temp2 /= 2.6855f;
   temp2 += 1.0f;
   temp *= 0.042f;
   temp2 += temp;
   a *= temp2;
   // The Hyp of a 2D right angled triangle has now been found
   //  (where 'a' and 'temp' were the other two sides and
   //   'a' has now been updated to contain the hyp length).

   if ( c < TINY_FLOAT ) return a; // Effectively a 2D vector (not 3D).

   temp = c;
   temp /= a;
   temp2 = temp * temp;
   temp2 /= 2.6855f;
   temp2 += 1.0f;
   temp *= 0.042f;
   temp2 += temp;
   a *= temp2;

   return a;
   }

   
float fp_distance( D3DVECTOR *p_1, D3DVECTOR *p_2 )
   {
   //
   // (C) of Jon E P 1998.
   // This is the floating point version -- (c) Jon P, 2003.
   //
   // Calculate the distance from p_1 to p_2

   register float temp, temp2;
   float a, c, dz;

   temp = p_1->x - p_2->x;      // dx
   if ( temp < 0 ) temp = 0.0f - temp;

   temp2 = p_1->y - p_2->y;     // dy
   if ( temp2 < 0 ) temp2 = 0.0f - temp;

   dz = p_1->z - p_2->z;        // dz
   if ( dz < 0 ) dz = 0.0f - temp;



   // The variable you might expect to be called 'b' is replaced by 'temp',
   // also note that 'temp' is redefined later-on and ceases to correspond to 'b'.
   // (this enables register use without the register having to be coloured)
   if ( temp >= temp2 && temp >= dz )
      {
      a = temp; // 'a' = longest dimension.
      temp = temp2;
      c = dz;
      }
   else
      {
      if ( temp2 >= temp && temp2 >= dz )
         {
         a = temp2; // 'a' = longest dimension.
         //temp = dx;
         c = dz;
         }
      else
         {
         a = dz; // 'a' = longest dimension.
         //temp = dx;
         c = temp2;
         }
      }

   // The above IF statement has sorted ordinates:-
   //    'a' will be the largest ordinate.
   //    'temp' will be the second largest ordinate.
   //    'b' will be the smallest ordinate.

   if ( a < TINY_FLOAT ) return a; // line had zero or near zero length.

   if ( temp < TINY_FLOAT ) return a; // line was perpendicular with co-ordinate system
   //                                 (or near enough).
   
   temp /= a;
   temp2 = temp * temp;
   temp2 /= 2.6855f;
   temp2 += 1.0f;
   temp *= 0.042f;
   temp2 += temp;
   a *= temp2;
   // The Hyp of a 2D right angled triangle has now been found
   //  (where 'a' and 'temp' were the other two sides and
   //   'a' has now been updated to contain the hyp length).

   if ( c < TINY_FLOAT ) return a; // Effectively a 2D vector (not 3D).

   temp = c;
   temp /= a;
   temp2 = temp * temp;
   temp2 /= 2.6855f;
   temp2 += 1.0f;
   temp *= 0.042f;
   temp2 += temp;
   a *= temp2;

   return a;
   }