Okay, then–that is effectively identical to the optimization I suggested, where the gravitational constant, timestep, and mass are all folded together into one constant.
I don’t think you can get rid of it completely. However:
PlanetDirection needs to be normalized. There must be something like this:
dir = ship - planet
dist = sqrt(dir.xdir.x + dir.ydir.y)
dir = dir / dist
And then you compute:
force = dir * mass / (dist * dist)
There are some extra divides there! This can be refactored as:
dir = ship - planet
norm = 1.0f / sqrt(dir.xdir.x + dir.ydir.y)
scale = mass * norm * norm * norm
force = dir * scale
(I separated out scale since I’m not sure if the C# optimizer will do that for you when working with vectors).
I’m using an internal unity operation to normalize PlanetDirection, but it must be doing something similar to that, I’ll try your suggestion and report back.
It works! :D, it’s shaving about 70 milliseconds in the complete Saturn - > Sun calculation, about 4 milliseconds from each 60000 step course prediction,
With this and other things I’ve been fixing, the program now calculates the necessary angle and impulse to reach the sun in about 160-190 milliseconds and that in debug mode.
I’ve downloaded Unity 5 now and it comes with a profiler (Unity 4 had it only in the pay version) so I’ll try it now and see what else can be optimized.
I did some quick tests, and I’m pretty sure the remaining square root is still the slow part.
Optimizing that further gets… tricky. If you aren’t opposed to using some deep magic, try plugging in this little gem:
unsafe static float FastInvSqrt(float n)
{
float y = n;
uint i = *(uint *)&y;
i = 0x5f3759df - (i >> 1);
y = *(float*)&i;
y = 0.5f * y * (3.0f - (n * y * y));
return y;
}
You have to compile with the unsafe flag. And the precision isn’t as good as the real inverse square root. But since this only affects the shape of your potential energy wells, maybe it’s not so big a deal.
That’s John Carmack’s (not really him it seems) hack, isn’t it?, I’ll try it once I’m no longer slaving in the code mines, if it becomes self aware I’ll try to warn you all in time :).
Yep–good eye! It’s one of those hacks that you should avoid if at all possible, but in this situation you have a tight inner loop that’s largely dependent on 1/sqrt perf. So it’s a perfect application.
I’m very curious how much it affects the results, though. As I mentioned, it really only affects the shape of the gravitational wells. It shouldn’t cause any problems like violating conservation of energy or something, so I believe it will just slightly alter the shape of your orbits and not cause anything like spiraling in to your doom.
Speaking of energy, you might consider tracking that separately so that you can keep it constant. When the engines are off, your kinetic+potential energy will be constant. So you can store that in a separate variable. Every so often (maybe 100 timesteps), you tweak your velocity slightly so that the KE is the difference between your stored energy value and your current potential energy. Your orbits may change phase over time but they will at least be stable.
It works, but it doesn’t seems to be speeding things up too much, perhaps 1 millisecond per 6000 step calculation, I’ll consider it as an option but, since Unity Web Player does not work with unsafe code, I won’t use it for now.
In part to make calculating course easier and in part to help the AI I’ve modeled things so there are no constant acceleration engines, you impart a new speed of a given vector to your ship and see the results, correcting as needed with new “kicks” of new vectors.