|
|
#1 |
|
Procrastination Incarnate
Development Director
|
In a physics engine I'm making, I have this wierd bug. I have kind of figured out where in the code it happens, but I have no idea how or why, and I only manage to reproduce it in-game about 50% of the times I try.
__________________The problem is in the numbers my debug messages are returning, which make absolutely no sense. So, before I throw the whole monstrosity of the engine at you, I first want to only know if anyone has any insight why my debug message is giving me incomprehensible gibberish. Is it a problem with R2S (which I doubt, since it doesn't only screw up the debug message, but the further vector calculations as well), or with the reals themselves? relevant functions:constant function VectorGetX takes integer vector returns real return udg_vectorX[vector] endfunction constant function VectorGetY takes integer vector returns real return udg_vectorY[vector] endfunction constant function VectorGetZ takes integer vector returns real return udg_vectorZ[vector] endfunction function VectorGetLength takes integer vector returns real return SquareRoot(udg_vectorX[vector]*udg_vectorX[vector] + udg_vectorY[vector]*udg_vectorY[vector] + udg_vectorZ[vector]*udg_vectorZ[vector]) endfunction These functions should be quite self-explanatory, at least to my target audience. debug:... call BJDebugMsg("facing vector "+R2S(VectorGetX(uFacing))+" "+R2S(VectorGetY(uFacing))+" "+R2S(VectorGetZ(uFacing))+" "+R2S(VectorGetLength(uFacing))) ... |
|
|
|
| Sponsored Links - Login to hide this ad! |
|
|
|
|
#2 |
|
Dread Lord of the Cookies
Content Director
|
What do you want us to do about it...? I'll presume that you are using an array to hold the relevent vectors, but...we really need to see a bit more of your code beyond a couple of a variables (what is uFacing by the way?).
__________________Bear in mind those 0s are probably just roundings. The reason it works out at 1 is probably due to it getting confused by the rediculous numbers you're putting into the function. |
|
|
|
|
|
#3 |
|
User
|
Are you doing anything with the Zvector that you aren't doing with the X and Y vectors. Perhaps there's an issue with the value you're assigning it if you're doing something out of the ordinary.
__________________Edit: It is probably working out to 1.000 because that is the correct length (assuming some rounding) for the sum of the X and Y vectors, but the value used for Z may be processed as a 0 because of it's abnormality. Captain_Griffen, uFacing is essentially an index with for the array of vectors. I'm assuming it's linked to a unit some how and the vector is used to determine the direction and amount of movement. Last edited by Naakaloh : 06-20-2006 at 06:47 PM. |
|
|
|
|
|
#4 |
|
Procrastination Incarnate
Development Director
|
I'm not doing anything special with the z coordinate of the vector. I work with vectors as a whole, my vector stack is kinda similar to the handle stack. I do things like sums, scalar products, vector products... the point is, the system works fine, the engine is running on a 0.02 periodic trigger and is doing thousands of vector operations per second, and all the time the unit that is being moved by all this math seems to move as it should... until at one point all terrain friction forces go to 0, which was through rigorous debugging been confirmed to be caused by this anomaly suddenly appearing in the facing vector.
__________________The problem is that all further operations with such a vector fail badly, I have no idea how various math operations I do when working with vectors treat this number, as you suggested, apparently multiplying the number with itself gives 0 or the length of the vector wouldn't still be calculated as 1, but other operations don't seem to treat it as 0 because otherwise the system would still work as it did before the anomaly occured. |
|
|
|
|
|
#5 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
That number is a bit shy of the maximum number you can represent with a single precision float. Since your dot product seems to think it's zero, it's likely that this is how NaN or -Inf is represented.
__________________NaN: Could happen if you got a divide by zero in another thread. You can detect this by making sure each thread exits cleanly. -Inf: Overflow perhaps from using an unstable time stepper. If it takes a few iterations to reach that quantity then this is responsible. Either: Uninitialized data. Look through code with a microscope. |
|
|
|
|
|
#6 |
|
Procrastination Incarnate
Development Director
|
Thanks for the feedback.
__________________I don't think I should have a divide by zero problem, because all my functions that do divisions have an if statement checking for that, unless it isn't exactly 0, but close enough to 0... however, I find that unlikely, I mostly divide stuff with vector lengths, and the vector that fails me has it's length continiously set to 1, while others with which I do similar stuff can be much smaller. How would I check if a thread exits cleanly? It doesn't take any iterations, the engine is working fine for some time then at some undetermined point the vector's z coordinate gets this strange value in one run of the periodic trigger. Uninitialised data... well, I suppose I could look for that, although I have no idea why something wouldn't initialise properly when it does so for some time. In either event, maybe I gave up on debugging too soon, I found the function where it happens but that function still has a bunch of function calls in itself, time to pin-point the problem more precisely. Edit2: Deleted the edit, figured that part out. Continiuing with the debug. Edit3: Well, it seems that the error can happen just about anywhere. I placed a couple of debug messages throughout the offending function and I managed to get the change from normal number to crazy number between just about any two debug messages. The only function that all parts of the code have in common seems to be this one, although that doesn't neccesarily mean I found my problem: JASS:function VectorScale takes integer vector1, real factor returns boolean if udg_vectorTaken[vector1] then set udg_vectorX[vector1] = udg_vectorX[vector1] * factor set udg_vectorY[vector1] = udg_vectorY[vector1] * factor set udg_vectorZ[vector1] = udg_vectorZ[vector1] * factor return true endif return false endfunction the factor is in all cases either close to 0 or close to 1. |
|
|
|
|
|
#7 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Write two functions block start and block close. Block start checks a global. If it's false, it warns that a thread died. otherwise it sets it to false. block close sets the global to true. Put them at the start of a thread and the end of a thread, or wrapped around sleeps if you got those.
__________________Doesn't look like this could matter though. Thread death from divide by zero performs no assignment. Similarly warcraft does print inf and -inf as "inf" and "-inf". *shrug* |
|
|
|
|
|
#8 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Da-bump, because it turns out Anitarf discovered a blizzard bug. Gotta love this:
__________________x = 0.000 y = 0.000 x - y = ... wait for it ... ~-2^(2^7) Yet to find the exact conditions that cause it or a work around. |
|
|
|
|
|
#10 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Oh, integers are definitely fine (haha I hope). This may not even be blizzard's fault but something to do with the compiler or x86 architecture + naivete on handling exceptions. I think underflow might be involved.
__________________Workaround (? maybe) *shudder*: a-b -> (2*a - 2*b)/2 Anitarf your problem subtraction or at least one of them is Input2Gamestate -> terrainContactFactor > 0.0 -> VectorProjectPlane -> VectorDifference -> Z term. Replacing that subtraction with the above sub seems to work. Example: JASS:function ItoR takes integer i returns real return i return 0. endfunction function Trig_test_Actions takes nothing returns nothing local integer x = 132655658 //or 132655657 local integer y = 132655433 local real a = ItoR(x) local real b = ItoR(y) local real diff = a - b call BJDebugMsg(R2S(a)+" "+R2S(b)+" "+R2S(diff)) endfunction So it's gotta be some sort of underflow thing |
|
|
|
|
|
#11 |
|
Procrastination Incarnate
Development Director
|
Well, I tried doing the (a-b -> (2*a - 2*b)/2) hack in my subtraction functions for the z coordinate, and the bug still occurs (not always, it didn't occur always before either).
__________________Edit: I tried another fix, one I have been thinking about in a while, and it seems it worked, to an extent. I still managed to get the bug once, but I tested like 15 times, which is a lot better result then before, when I got it almost every time. PipeDream, I changed the part which adapts the facing vector to the terrain plane. Before, I did it gradualy, to get a smooth transition after a jump, because while in the air, the facing vector doesn't adapt to the terrain, so when adapting it to the terrain I didn't just replace it with it's projection onto the terrain plane, but instead I took the projection and the original vector, multiplied them with the terrainContactFactor or (1-terrainContactFactor) and then added them together. As terrainContactFactor approached 1 while the unit was sliding over flat ground, (1-terrainContactFactor) approached 0 and I am guessing the small fractions I was beginning to work with were increasing the danger of causing this bug. Sometimes it was caused by this operation alone, other times by those which followed (the rotation of the facing vector). The bug is still there, I just changed my system to reduce the chance of hitting it. I still managed to hit it once, but I suppose that once I get natural terrain instead of the flatness I have now, I will eliminate the chance of hitting it alltogether, and I suppose that I wouldn't hit it then even if I would still be using the un-fixed system. |
|
|
|
|
|
#12 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
Shift it a few more bits. (1024*a-1024*b)/1024 seems to work for the single bit between ItoR(132655434)-ItoR(132655433). If it still has problems.. bump it up another power or two.
__________________ |
|
|
|
|
|
#13 |
|
Procrastination Incarnate
Development Director
|
Hey, it worked. I went back to the old version of my code and did the (1024*a-1024*b)/1024 hack when subtracting z coordinates, didn't manage to get the bug in a couple of tests.
__________________I think that, along with the fact that the conditions under which the bug appears now in the test map won't be present in the final map, is enough guarantee for me that things will work. |
|
|
|
|
|
#14 |
|
Moderator
Code Moderator
Join Date: Feb 2006
Posts: 1,405
![]() ![]() ![]()
|
By a lucky coincidence I happened to run across the subtraction routine. Turns out warcraft does all its floating point work with integer math. Maybe we'll get them to fix this bug in it. I didn't want to fuck with editing game.dll so I just made a loader that replaces the routine with one that uses the floating point unit. Don't know if you can actually use it for your project, but I'm curious if it works for you.
Edit: Here's v2 that replaces the rest of arithmetic (+ - * /). I expect this to be significantly faster as the parser doesn't have much work to do. |
|
|
|
![]() |
| Thread Tools | Search this Thread |
|
|
|
Donate |