----------------------------------------------------------------------------------
@MSGID: 1@dont-email.me> 78572401
@REPLY: 2@dont-email.me> 8ecbc9f3
@REPLYADDR BGB <cr88192@gmail.com>
@REPLYTO 2:5075/128 BGB
@CHRS: CP866 2
@RFC: 1 0
@RFC-Message-ID: 1@dont-email.me>
@RFC-References:
1@newsreader4.netcologne.de> <memo.20230917185814.16292G@jgd.cix.co.uk>
<ba7d6a5d-2373-4f55-a640-69b1ab3e00bbn@googlegroups.com> 1@dont-email.me>
<de99236c-9bd2-4c5b-98b4-c9e2985eb1b0n@googlegroups.com> <7df1b835-02e5-4988-96ef-2af73b8587d7n@googlegroups.com>
2@dont-email.me>
@TZUTC: -0500
@PID: Mozilla/5.0 (Windows NT 10.0; Win64; x64;
rv:102.0) Gecko/20100101 Thunderbird/102.15.1
@TID: FIDOGATE-5.12-ge4e8b94
On 9/19/2023 4:32 AM, Terje Mathisen wrote:
>
robf...@gmail.com wrote:
>> What kind of precision is needed for space-time co-ordinates? I tried
>> looking this
>> up and get the impression that 64-bit floats may not be enough, but
>> 128-bit floats
>> are overkill. The reference was a space game based in a galaxy.
>>
> I would use the same trick as LiDAR, with coordinates in each chunk/file
> being 32-bit integers, and the header contains the origo offset and
> scale factors needed to convert into global coords.
>
> In a game you probably only need exact coords for items which are
> reasonably close to you.
>
In my 3D engines, one common issue came up here:
OpenGL only really works with 32-bit floats;
If your game world is "bigger than Texas", this isn`t going to work...
So, typically, coordinates were often stored relative to the current
region. One would add these to the region`s address to get a location in
the world.
For rendering and local interactions, the whole coordinate space would
move, typically with the region containing the camera being used as the
local origin for the coordinate space. As the camera moves to a
different region, the whole space moves such that the current region is
now the origin.
So, there may end up being several ways to represent locations:
64-bit, 3x Float21 (Binary16+5b): Region local coordinates.
Binary16 isn`t quite sufficient even for this.
96/128-bit, 3x Binary32: Camera local coordinates
128-bit, 3x Binary42 (Binary32+10b): World-global coordinates.
This was used for currently active entities.
This was sufficient for a world size of roughly 1024km x 1024km x 256m
(in my BGBTech2 engine, 1).
In my 3D engines, the world was a torus, rather than a plane;
The way that the coordinate-space worked allowed a seamless wrap.
Some logic (like the terrain system) also used fixed point 3x 20.12
coordinates.
1: In BGBTech3, this was dropped to 64km x 64km x 128m, but was a
similar idea (region size dropping from 256x256x256 to 128x128x128;
which only needs around 1/8 as much RAM per loaded region).
Rendering would work across the seam, which was mostly invisible as far
as the player was concerned (where region coordinates would wrap across
the edge).
For things like entity collisions, there was a little bit of hacking
across the seam (seam-crossing entities would be handled as-if they
existed on both sides of the seam at the same time).
Can also note terrain-generation noise functions:
The BGBTech1 engine had used Perlin noise;
The BGBTech2 had use spatial hashing:
Hash the coordinates via arcane use of shift and xor.
shift-xor gave better results in this case
multiply-by-prime-and-add has obvious repeating patterns.
Use hash result as a random number between 0 and 1.
Interpolate between points on a 2D or 3D grid.
Scale as necessary to get desired results.
Add multiple "frequencies" at different "weights" to get results;
One can mix magic numbers into the hash for multiple.
IIRC, BGBTech3 had used an intermediate strategy.
Actual Perlin noise required an intermediate lookup table and a bunch of
extra math which was seemingly unnecessary if the noise is driven
directly by a 2D or 3D hash function.
Similarly, each sub-layer effectively needs its own lookup table for the
noise function, where the costs add up quickly.
Had to get creative with XOR, as while intuitively, one might think they
could do, say:
h=((((((((x*65521)+y)*65521)+z)*65521)+w)*65521)>>16)&255;
This actually sucks, generating obvious patterns that tend to repeat
along the diagonal axes.
Contrast with, for example:
h=w;
h=(h<<7)^(~(h>>17))^x;
h=(h<<7)^(~(h>>17))^y;
h=(h<<7)^(~(h>>17))^z;
h=(h<<7)^(~(h>>17))^w;
h=(h<<7)^(~(h>>17)); //add more mixing steps here as needed
h=h^(h>>16);
h=(h^(h>>8))&255;
Where, say, x/y/z are (integer) coordinates and w is a magic number
(say, a `w` value is generated for each sub-function as a random number
generated from the world seed or similar).
And, if one wants a floating point value from 0 .. 1, they do
"v=(h/255.0);" or similar.
Not entirely sure why seemingly this sort of strategy isn`t more common.
...
--- Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.1
* Origin: A noiseless patient Spider (2:5075/128)
SEEN-BY: 5001/100 5005/49 5015/255 5019/40 5020/715
848 1042 4441 12000
SEEN-BY: 5030/49 1081 5058/104 5075/128
@PATH: 5075/128 5020/1042 4441