About fixed points

Started by
11 comments, last by chrisendymion 10 years ago

What about doubles instead of floats?

That may help, but it probably only kicks the can down the road a little further.

The fundamental problem you are facing is the way that floating point formats -- essentially a base-two form of scientific notation -- encode their magnitude. They're designed to represent very small measures with very high precision, and very large numbers with very low precision. If you're measuring the width of a human hair, you obviously need to be very precise, but if you're measuring the distance between planets, what's a few hundred kilometers error here and there? In fact, there's as many divisable units in a floating-point format between 0 and 1 as there are between 1 and the largest re presentable number. Unlike integral or fixed-point arithmetic, the divisible units are not equally-sized -- the space between them increases the further you get from 0.

In a space game I was involved with some time ago, there were similar problems -- planets in this game were actually held in their orbits by the gravity of their local sun, all based on physics. use of a single floating-point coordinate system would cause enough precision error in further-away solar systems that the physics would fall apart and planets would fall out of orbits that they should have maintained. The problem was solved by having multiple coordinate systems -- One that was used to describe the location solar systems themselves, and one local space for every solar system -- basically the suns/stars were in the 'universal' coordinate system, and each sun/star was also the center of its own local coordinate system.

Fixed-point could serve as the basis for a single universal coordinate system with uniform precision, but the trouble is that you need an awful lot of bits to represent the number of centimeters between here and Proxima Centauri.

Finally, bare in mind that when you work with floating-point, the scale you choose to work at has a great effect on precision over the range of values you encounter. Simply changing 1.0 to mean 1 kilometer instead of 1 meter would have a noticable impact on how the precision errors are manifested (though, I'm not proposing that this simple change would fix your problems).

throw table_exception("(? ???)? ? ???");

Advertisement

space is truly huge. a light year is 9.46 quadrillion meters. a parsec is 3.2616 light years. and astronomers use units of kilo parsecs and mega parsecs for measuring the most distant heavenly bodies.

Luckily, these huge distances don't matter much.

If you look at a nearby stellar object (let's say Proxima Centauri, which is a mere 4.2 lightyears), it doesn't matter whether you measure the distance with micrometer or kilometer precision because you can't tell the difference. If you travel at "normal" speeds, then travelling for the entire duration of your life will bring you none closer to Proxima Centauri than about 4.2 light years. It is exactly the same in every respect.

On the other hand, if you have some form of "hyperdrive" (or any other fictional faster-than-light travel. wormholes or whatever) then you can reach Proxima Centauri no problem, but you still cannot tell the difference between a micrometer or a hundred thousand kilometers. There's no way you could hit the "stop starship" button fast enough to travel less than a hundred thousand kilometers, and there is nothing interesting but ... empty space... anyway. There is also no way of telling, after travelling 4.2 lightyears, whether that was really 4.2 lightyears or 4.2 lightyears, 33.7 kilometers and 20.0052 meters. Our sun is the same tiny spot when looked at from over 4 lightyears away whether or not it's a few kilometers off or not.

In other words, you can conveniently use a coarse coordinate system with a resolution of thousands (ten thousands, if you will) of kilometers to model the huge empty space between interesting things, which is convenient for modelling entire galaxies. And then again, use a different coordinate system at planet or solar-system scale (say, 64bit integers, micrometer precision) to model the "interesting stuff". Switch between them whenever you swich hyperdrive on/off.

This. Sometimes, your relative distances look like this*:


union distance
{
  int parsecs;
  int lightyears;
  int meters;
};

Rather than This:


UnGodlyHugeArbitraryPrecisionType distance;

Embrace the fact that not all scales of distance ever matter at the exact same time. Treat units the same way scientists do; don't try to convert everything to a uniform metric.

*I'm not actually sure I'd use a union in this kind of situation. That's just an example.


In other words, you can conveniently use a coarse coordinate system with a resolution of thousands (ten thousands, if you will) of kilometers to model the huge empty space between interesting things, which is convenient for modelling entire galaxies. And then again, use a different coordinate system at planet or solar-system scale (say, 64bit integers, micrometer precision) to model the "interesting stuff". Switch between them whenever you swich hyperdrive on/off.

This is exactly the approach used in all previous versions of SIMTrek / SIMSpace. as you say it works just fine.

now the _int64 makes it possible to use world coordinate systems of light years and decimeters and cover the size of about 3 galaxies. this allows huge game worlds with high precision, and little muss and fuss about multiple coordinate systems, sector/quadrant stuff etc. just a simple "draw whats around the camera, relative to the camera" approach to things, with a little LOD thrown in. SIMSpace 8 will be the 6th title i've done with a game world so large it required world coordinates. and at last, i almost have data types big enough to store the positions etc without a lot of hassle.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php


The problem was solved by having multiple coordinate systems -- One that was used to describe the location solar systems themselves, and one local space for every solar system -- basically the suns/stars were in the 'universal' coordinate system, and each sun/star was also the center of its own local coordinate system.

this is the precise method used by previous versions of SIMTrek / SIMSpace.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Whoah ! Thank you all so much for all your help !
I start to understand. There is just some things to learn more...
For the moment, I will concentrate myself on only a planet, I will see later for solar system, galaxies, etc.
For very high precision, you say it's better to use int64. I think I need to create a class for converting it to better readable numbers (for coding) ?
If not, with micrometers precision, I will deal with very very big numbers (without digits as it's integer), not very convenient.. ? Some tips ?
I understand the concept of using camera position as the center, for more precision when converting to float.
But subtracting the vertices x,y,z from the camera position in the CPU will be huge ?! There is lot of vertices in the node's grid (x 6 faces)...
Better to do that in the vertex shader, no ? But if I do that, how to send the coordinates to the shader ?
As the max input is R32B32G32 and I will use 3 x int64... ?
My grids are allways the same, they are offseting and scaling in vertex shader based on node position and LOD.
In conclusion, when to convert to float and where ? What format to send to the shaders ?
Again, thank you for all your help ;)
PS : I know it's a hard concept for a beginner, but I'm here for learning and not affraid to spend hours on that.

This topic is closed to new replies.

Advertisement