32-bitowy float ma 23-bitową mantysę .
Oznacza to, że każda liczba jest reprezentowana jako 1.xxx xxx xxx xxx xxx xxx xxx xxx xx razy potęga 2, gdzie każda x jest cyfrą binarną, 0 lub 1. (Z wyjątkiem bardzo małych zdenormalizowanych liczb mniejszych niż - zaczynają się od 0. zamiast 1., ale zignoruję to dla poniższych)2)- 126
Tak w zakresie od i , można reprezentować dowolną liczbę z dokładnością2)ja2)( i + 1 )± 2( i - 24 )
Na przykład dla najmniejszą liczbą w tym zakresie jest . Kolejna najmniejsza liczba to . Jeśli chcesz reprezentować , musisz zaokrąglić w górę lub w dół, dla błędu obu przypadkach.i = 0( 20) ⋅ 1 = 1( 20) ⋅ ( 1 + 2- 23)1 + 2- 242)- 24
In this range: You get accuracy within:
-----------------------------------------------
0.25 - 0.5 2^-26 = 1.490 116 119 384 77 E-08
0.5 - 1 2^-25 = 2.980 232 238 769 53 E-08
1 - 2 2^-24 = 5.960 464 477 539 06 E-08
2 - 4 2^-23 = 1.192 092 895 507 81 E-07
4 - 8 2^-22 = 2.384 185 791 015 62 E-07
8 - 16 2^-21 = 4.768 371 582 031 25 E-07
16 - 32 2^-20 = 9.536 743 164 062 5 E-07
32 - 64 2^-19 = 1.907 348 632 812 5 E-06
64 - 128 2^-18 = 0.000 003 814 697 265 625
128 - 256 2^-17 = 0.000 007 629 394 531 25
256 - 512 2^-16 = 0.000 015 258 789 062 5
512 - 1 024 2^-15 = 0.000 030 517 578 125
1 024 - 2 048 2^-14 = 0.000 061 035 156 25
2 048 - 4 096 2^-13 = 0.000 122 070 312 5
4 096 - 8 192 2^-12 = 0.000 244 140 625
8 192 - 16 384 2^-11 = 0.000 488 281 25
16 384 - 32 768 2^-10 = 0.000 976 562 5
32 768 - 65 536 2^-9 = 0.001 953 125
65 536 - 131 072 2^-8 = 0.003 906 25
131 072 - 262 144 2^-7 = 0.007 812 5
262 144 - 524 288 2^-6 = 0.015 625
524 288 - 1 048 576 2^-5 = 0.031 25
1 048 576 - 2 097 152 2^-4 = 0.062 5
2 097 152 - 4 194 304 2^-3 = 0.125
4 194 304 - 8 388 608 2^-2 = 0.25
8 388 608 - 16 777 216 2^-1 = 0.5
16 777 216 - 33 554 432 2^0 = 1
Więc jeśli twoje jednostki są w metrach, stracisz milimetrową precyzję wokół pasma 16 484 - 32 768 (około 16-33 km od miejsca pochodzenia).
Powszechnie uważa się, że można obejść ten problem przy użyciu innej jednostki bazowej, ale nie jest to prawdą, ponieważ liczy się względna precyzja.
Jeśli użyjemy centymetrów jako jednostki, tracimy milimetrową precyzję w paśmie 1 048 576-2 097 152 (10-21 km od miejsca pochodzenia)
Jeśli użyjemy hektametrów jako jednostki, tracimy milimetrową precyzję w paśmie 128-256 (13-26 km od źródła)
... więc zmiana jednostki na ponad cztery rzędy wielkości wciąż kończy się utratą milimetrowej precyzji gdzieś w zasięgu dziesiątek kilometrów. Zmieniamy tylko to, gdzie dokładnie w tym paśmie uderza (z powodu niedopasowania numeracji base-10 i base-2), nie rozszerzając drastycznie naszego obszaru gry.
Dokładność, na jaką niedokładność może tolerować twoja gra, zależy od szczegółów rozgrywki, symulacji fizyki, rozmiaru jednostki / odległości rysowania, rozdzielczości renderowania itp., Więc ustalenie dokładnego limitu jest trudne. Być może renderowanie wygląda dobrze 50 km od miejsca pochodzenia, ale pociski teleportują się przez ściany lub wrażliwy skrypt rozgrywki oszaleje. Lub może się okazać, że gra gra dobrze, ale wszystko ma ledwo wyczuwalne wibracje wynikające z niedokładności w transformacji aparatu.
Jeśli znasz poziom dokładności, którego potrzebujesz (powiedzmy, rozpiętość 0,01 jednostek odwzorowuje do około 1 piksela przy typowej odległości oglądania / interakcji, a każde mniejsze przesunięcie jest niewidoczne), możesz skorzystać z powyższej tabeli, aby znaleźć miejsce, w którym go stracisz dokładność i cofnij się o kilka rzędów wielkości dla bezpieczeństwa w przypadku operacji stratnych.
Ale jeśli w ogóle myślisz o dużych odległościach, lepiej może to wszystko ominąć, ponownie skupiając swój świat na ruchu gracza. Wybieramy konserwatywnie mały kwadratowy lub sześcianowy region wokół początku. Ilekroć gracz porusza się poza ten region, tłumacz go i wszystko na świecie, cofnij się o połowę szerokości tego regionu, trzymając gracza w środku. Ponieważ wszystko porusza się razem, Twój gracz nie zobaczy zmiany. Niedokładności mogą wciąż zdarzać się w odległych częściach świata, ale generalnie są one znacznie mniej zauważalne niż dzieje się tuż pod stopami, a masz gwarancję, że zawsze będziesz mieć wysoką precyzję w pobliżu gracza.
Trudno odpowiedzieć, ponieważ zależy to od skali twojej fizyki: Jaka jest dopuszczalna minimalna prędkość ruchu, której NIE trzeba zaokrąglać do zera?
Jeśli potrzebujesz dużego świata i spójnej fizyki, lepiej użyć klasy punktów stałych.
Na przykład wystrzelenie kuli armatniej z dowolnego miejsca na świecie da ten sam wynik, a 64-bitowy punkt stały (32,32) zapewni ogromną precyzję i więcej niż cokolwiek zauważalnego w większości gier. Jeśli twoja jednostka ma 1 metr, nadal jesteś w odległości 232 pikometrów z dokładnością 2147483 km od źródła.
Nadal możesz wykonywać fizykę lokalną w zmiennoprzecinkowych komórkach lokalnych, aby zaoszczędzić na programowaniu i korzystać z gotowego silnika fizyki. Nadal będzie w miarę spójny we wszystkich praktycznych celach.
Jako dodatkowa faza szeroka i AABB wydają się być szybsze w ustalonym punkcie ze względu na opóźnienia FPU. Szybsze jest także przekształcanie stałego punktu na indeks oktawy (lub kwadratu), ponieważ można wykonać proste maskowanie bitów.
Operacje te nie korzystają tak bardzo z instrukcji SIMD i potokowania, które normalnie ukrywają opóźnienia FPU.
Możesz przekonwertować pozycje na zmiennoprzecinkowe PO odejmując pozycję kamery w stałym punkcie, aby renderować wszystko, unikając problemów ze zmiennoprzecinkowymi w dużym świecie i nadal używając zwykłego renderera używającego zmiennoprzecinkowych.
źródło
Można tego całkowicie uniknąć przez pomnożenie.
Zamiast pracować z liczbami zmiennoprzecinkowymi, wystarczy pomnożyć je przez 10 ^ (x), zapisać je, a w razie potrzeby pomnożyć ponownie przez 10 ^ (- x).
Od tego zależy, jakiego typu int chcesz użyć.
źródło