Distance Formula Too Slow
How can you make this faster?
Function Distance(Orig as D3DVECTOR, Dest as D3DVECTOR) as single
Distance = ((Orig.X - Dest.X)^2 + (Orig.X - Dest.X)^2 + (Orig.X - Dest.X)^2) ^ .5
End Function
I tried to subtract the verticies first and multiply them by themselves then sqr''d them and increased the framerate slightly. I was wondering if there is a faster function or just an faster way to square root it.
If you only need the distace values for comparison,
you could just compare squares of distances.
you could just compare squares of distances.
The square root function is very slow, it takes many cycles. Make yourself a lookup table, and precalculate it before the start. This is the only thing I can think of.
Andre LaMothe includes a distance between two points function in Tricks of the Windows Game Programming Gurus. Its not quite as accurate (within 3%), but it may well be good enough for you. It shouldn''t be hard to modify it to use D3DVECTORs.
Here it is:
Here it is:
float Fast_Distance_3D(float fx, float fy, float fz){// this function computes the distance from the origin to x,y,zint temp; // used for swapingint x,y,z; // used for algorithm// make sure values are all positivex = fabs(fx) * 1024;y = fabs(fy) * 1024;z = fabs(fz) * 1024;// sort valuesif (y < x) SWAP(x,y,temp)if (z < y) SWAP(y,z,temp)if (y < x) SWAP(x,y,temp)int dist = (z + 11*(y >> 5) + (x >> 2) );// compute distance with 8% errorreturn((float)(dist >> 10));}
hmm, great! Just what I was looking for. I ported the code, but what do these things do?
SWAP(x,y,temp)
is it like iif?
(y >> 5) + (x >> 2)
does this perform bit-shifting?
I''m clueless and C++ impared.
SWAP(x,y,temp)
is it like iif?
(y >> 5) + (x >> 2)
does this perform bit-shifting?
I''m clueless and C++ impared.
Swap is probably a macro that just swaps the value of the first two parameters in it.
>> is bit shifting , so (y >> 5) is basically a cheap way to divide y by 32 (32 = 2^5).
>> is divison by powers of 2, and << is multiplication by powers of 2.
>> is bit shifting , so (y >> 5) is basically a cheap way to divide y by 32 (32 = 2^5).
>> is divison by powers of 2, and << is multiplication by powers of 2.
February 13, 2000 01:54 PM
Code for using table based Square root.
#include
#include
/* MOST_SIG_OFFSET gives the (int *) offset from the address of the double
* to the part of the number containing the sign and exponent.
* You will need to find the relevant offset for your architecture.
*/
#define MOST_SIG_OFFSET 1
/* SQRT_TAB_SIZE - the size of the lookup table - must be a power of four.
*/
#define SQRT_TAB_SIZE 16384
/* MANT_SHIFTS is the number of shifts to move mantissa into position.
* If you quadruple the table size subtract two from this constant,
* if you quarter the table size then add two.
* Valid values are: (16384, 7) (4096, 9) (1024, 11) (256, 13)
*/
#define MANT_SHIFTS 7
#define EXP_BIAS 1023 /* Exponents are always positive */
#define EXP_SHIFTS 20 /* Shifs exponent to least sig. bits */
#define EXP_LSB 0x00100000 /* 1 << EXP_SHIFTS */
#define MANT_MASK 0x000FFFFF /* Mask to extract mantissa */
int sqrt_tab[SQRT_TAB_SIZE];
void init_sqrt_tab()
{
int i;
double f;
unsigned int *fi = (unsigned int *) &f + MOST_SIG_OFFSET;
for (i = 0; i < SQRT_TAB_SIZE/2; i++)
{
f = 0; /* Clears least sig part */
*fi = (i << MANT_SHIFTS) / (EXP_BIAS << EXP_SHIFTS);
f = sqrt(f);
sqrt_tab = *fi & MANT_MASK;
f = 0; /* Clears least sig part */
*fi = (i << MANT_SHIFTS) / ((EXP_BIAS + 1) << EXP_SHIFTS);
f = sqrt(f);
sqrt_tab = *fi & MANT_MASK;<br> }<br>}<br><br>double fsqrt( double f)<br>{<br> unsigned int e;<br> unsigned int *fi = (unsigned int *) &f + MOST_SIG_OFFSET;<br><br> if (f == 0.0) return(0.0);<br> e = (*fi >> EXP_SHIFTS) - EXP_BIAS;<br> *fi &= MANT_MASK;<br> if (e & 1)<br> *fi /= EXP_LSB;<br> e >>= 1;<br> *fi = (sqrt_tab[*fi >> MANT_SHIFTS]) /<br> ((e + EXP_BIAS) << EXP_SHIFTS);<br> return(f);<br>} </i>
#include
#include
/* MOST_SIG_OFFSET gives the (int *) offset from the address of the double
* to the part of the number containing the sign and exponent.
* You will need to find the relevant offset for your architecture.
*/
#define MOST_SIG_OFFSET 1
/* SQRT_TAB_SIZE - the size of the lookup table - must be a power of four.
*/
#define SQRT_TAB_SIZE 16384
/* MANT_SHIFTS is the number of shifts to move mantissa into position.
* If you quadruple the table size subtract two from this constant,
* if you quarter the table size then add two.
* Valid values are: (16384, 7) (4096, 9) (1024, 11) (256, 13)
*/
#define MANT_SHIFTS 7
#define EXP_BIAS 1023 /* Exponents are always positive */
#define EXP_SHIFTS 20 /* Shifs exponent to least sig. bits */
#define EXP_LSB 0x00100000 /* 1 << EXP_SHIFTS */
#define MANT_MASK 0x000FFFFF /* Mask to extract mantissa */
int sqrt_tab[SQRT_TAB_SIZE];
void init_sqrt_tab()
{
int i;
double f;
unsigned int *fi = (unsigned int *) &f + MOST_SIG_OFFSET;
for (i = 0; i < SQRT_TAB_SIZE/2; i++)
{
f = 0; /* Clears least sig part */
*fi = (i << MANT_SHIFTS) / (EXP_BIAS << EXP_SHIFTS);
f = sqrt(f);
sqrt_tab = *fi & MANT_MASK;
f = 0; /* Clears least sig part */
*fi = (i << MANT_SHIFTS) / ((EXP_BIAS + 1) << EXP_SHIFTS);
f = sqrt(f);
sqrt_tab = *fi & MANT_MASK;<br> }<br>}<br><br>double fsqrt( double f)<br>{<br> unsigned int e;<br> unsigned int *fi = (unsigned int *) &f + MOST_SIG_OFFSET;<br><br> if (f == 0.0) return(0.0);<br> e = (*fi >> EXP_SHIFTS) - EXP_BIAS;<br> *fi &= MANT_MASK;<br> if (e & 1)<br> *fi /= EXP_LSB;<br> e >>= 1;<br> *fi = (sqrt_tab[*fi >> MANT_SHIFTS]) /<br> ((e + EXP_BIAS) << EXP_SHIFTS);<br> return(f);<br>} </i>
February 13, 2000 01:57 PM
you need to include math.h and stdio.h. Sorry if this board fudged up the formatting of the code.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement