#153665 - Rajveer - Thu Apr 03, 2008 5:04 pm
I've found a bug in my collision code which allows division of a really large number by a really small number, problem is I can't do anything about the algorithm because it's sound on floating point systems e.g. in one case:
Code: |
divf32( 1005201,1) = -177664000 |
If converting this to floating point, this would be:
(1005201/4096) / (1/4096) = 1005201
Am I right? If so why is this? Maybe I should do this part in floating point and convert to fixed after the floating divide? *shudder*
EDIT: Ahah! It's only when the denominator is 1 or -1, otherwise it's the correct value. Why does this happen?
EDIT2: Nope, I'm wrong. When doing divf32( 1123008, x) I get the wrong answer when x is between -2 and 2. Any help?
#153670 - DiscoStew - Thu Apr 03, 2008 6:11 pm
I believe I know what you problem is. Your variables (as well as the divide) are based on 32-bit values, and the value can only go so high/low, and you are crossing the threshold of the signed value, as the divide affects the very last bit that decides is the value is negative or positive.
As for your thought about divide, the way dividing works for fixed numbers isn't quite that way. To divide 2 fixed numbers of the same type, the following formula is used.
(a << x) / b
Where a is the numerator, b is the denominator, and x is the fixed length that a and b are based off of. This is so that the resulting value is the same fixed-type as the values used.
With your values, this is what is happening
(1005201 << 12) / 1
(4117303296) / 1 = 4117303296
Now, convert that to hexadecimal, and you get
0xF5691000
Take note, that the defined value is "f32", which means it is not only 32-bits long, but it is signed as well. So, what is the true value of that hex number as a value of "f32"? It is exactly what you gave us, which is
-177664000
I hope that helps you understand the problem, as well as figure out a solution to it.
_________________
DS - It's all about DiscoStew
#153673 - elhobbs - Thu Apr 03, 2008 8:22 pm
to put it another way 245.4104 /0.000244 = 1005201 or 4117303296 when converted to an f32. This exceeds the 19 bits of precision for the integer portion of an f32. This assumes that the values in your example were already in f32 format. if they were not then the same thing applies to your input value of 1005201, it is too large to be expressed as an f32.
#153712 - Rajveer - Fri Apr 04, 2008 10:38 am
Cheers for the detailed explanations guys. I'm not sure how I'd correct this: I could use floating-point as a worst case scenario but I don't want to. I can't use a long long as divf32 returns DIV_RESULT32, so if I want the result as a 64-bit should I write my own function and use DIV_RESULT64?
What would you guys do for a solution?
#153719 - elhobbs - Fri Apr 04, 2008 1:31 pm
it really depends on what you are trying to accomplish and what the results are being used for. can you provide a little background?
#153720 - Rajveer - Fri Apr 04, 2008 1:45 pm
Yep, it's for use during my swept collision intersection test. As part of my test, I project the player's OBB and the triangle onto several axis and use the separating axis test, I also project the player's velocity (for sweeping). However there are cases where the projected velocity gives small numbers for the speed along the axis, even around the size of 1 and -1. In some cases I'll be finding the time to intersect by dividing the difference between the projected OBB's range and the projected triangle's range by this speed, which is where it messes up!
The results will be used to keep track of the first and last collision times, so that after the whole routine has finished I can move the player the correct amount, so it's pretty critical that I get this part right :)
#153730 - elhobbs - Fri Apr 04, 2008 5:19 pm
when you say 1 or -1, is this value already in fixed point format?
you could try clamping the velocity 1/4096 is pretty slow. or you could do your calulations in 64 bit values. you may need to rearrange some of the math to get it right though.
#153747 - Rajveer - Sat Apr 05, 2008 1:49 am
Yep, the projected speed is in fixed point format. I'm looking into clamping the values, but also process some of my math with 64-bit values. Since the ARM9 is a 32-bit processor, is it slower at processing 64-bits?
#153750 - sajiimori - Sat Apr 05, 2008 2:30 am
Well, you already have a special case for zero to avoid dividing by zero, right? Just treat small numbers as if they're zero. That is, if you collide at all, just say it's at t=0.
This case should be handled inside the collision test, not outside.