# Calculating a spaceship position.

**URL:** <https://boards.straightdope.com/t/calculating-a-spaceship-position/714602>\
**Category:** Factual Questions\
**Created:** [March 9, 2015, 3:17pm UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602 "2015-03-09T15:17:49Z")\
**Posts on this page:** 7\
**Page:** 3

<div class="post-metadata">

**Author:** ![Dr.Strangelove](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/dr.strangelove/32/6613_2.png) [@Dr.Strangelove](https://boards.straightdope.com/u/Dr.Strangelove)\
**Post date:** [March 19, 2015, 12:05am UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602/41 "2015-03-19T00:05:34Z")

</div>

> [@Frodo](#):
>
> PlanetMass is a number out my hat, without units, for game purposes it only matters in relation to other planets, thus the Sun has mass = 10, Jupiter = 1, and Earth = 0.1.

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.

> [@Frodo](#):
>
> I wonder if that PlanetDirection \* PlanetMass / Distance ^ 2 equation could be refactored somewhat to make it more efficient? currently is being calculated 7 times per step.

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.x_dir.x + dir.y_dir.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.x_dir.x + dir.y_dir.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).

---

<div class="post-metadata">

**Author:** ![Frodo](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/frodo/32/302_2.png) [@Frodo](https://boards.straightdope.com/u/Frodo)\
**Post date:** [March 19, 2015, 1:15am UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602/42 "2015-03-19T01:15:50Z")

</div>

> [@Dr.Strangelove](#):
>
> 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.x_dir.x + dir.y_dir.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.x_dir.x + dir.y_dir.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.

---

<div class="post-metadata">

**Author:** ![Frodo](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/frodo/32/302_2.png) [@Frodo](https://boards.straightdope.com/u/Frodo)\
**Post date:** [March 19, 2015, 1:55am UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602/43 "2015-03-19T01:55:08Z")

</div>

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.

thank you very much for your help.

---

<div class="post-metadata">

**Author:** ![Dr.Strangelove](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/dr.strangelove/32/6613_2.png) [@Dr.Strangelove](https://boards.straightdope.com/u/Dr.Strangelove)\
**Post date:** [March 19, 2015, 4:36am UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602/44 "2015-03-19T04:36:06Z")

</div>

Good to hear, and glad to help!

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:

```auto

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.

---

<div class="post-metadata">

**Author:** ![Frodo](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/frodo/32/302_2.png) [@Frodo](https://boards.straightdope.com/u/Frodo)\
**Post date:** [March 19, 2015, 12:52pm UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602/45 "2015-03-19T12:52:56Z")

</div>

> [@Dr.Strangelove](#):
>
> Good to hear, and glad to help!
> 
> 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:
> 
> ```auto
> 
> 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 :).

---

<div class="post-metadata">

**Author:** ![Dr.Strangelove](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/dr.strangelove/32/6613_2.png) [@Dr.Strangelove](https://boards.straightdope.com/u/Dr.Strangelove)\
**Post date:** [March 19, 2015, 9:55pm UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602/46 "2015-03-19T21:55:32Z")

</div>

> [@Frodo](#):
>
> 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.

---

<div class="post-metadata">

**Author:** ![Frodo](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/frodo/32/302_2.png) [@Frodo](https://boards.straightdope.com/u/Frodo)\
**Post date:** [March 21, 2015, 1:55am UTC](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602/47 "2015-03-21T01:55:10Z")

</div>

> [@Dr.Strangelove](#):
>
> 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.

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.

> [@Dr.Strangelove](#):
>
> 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.

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.

[Previous page](https://boards.straightdope.com/t/calculating-a-spaceship-position/714602.md?page=2)
