32-битное число имеет 23-битную мантиссу .
Это означает, что каждое число представлено как 1.xxx xxx xxx xxx xxx xxx xxx xx, умноженное на некоторую степень 2, где каждый x - двоичная цифра, 0 или 1. (За исключением очень маленьких денормализованных чисел, меньших 2- 126 - они начинаются с 0. вместо 1., но я буду игнорировать их в дальнейшем)
Таким образом, в диапазоне от 2я и 2( я + 1 ) вы можете представить любое число с точностью ± 2( я - 24 )
Например, для я = 0 наименьшее число в этом диапазоне равно ( 20) ⋅ 1 = 1 . Следующее наименьшее число - ( 20) ⋅ ( 1 + 2- 23) . Если вы хотите представить 1 + 2- 24 , вам придется округлить в большую или меньшую сторону, чтобы получить ошибку 2- 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
Поэтому, если ваши единицы измерения - метры, вы потеряете миллиметровую точность в диапазоне 16 484 - 32 768 (примерно 16-33 км от начала координат).
Обычно считается, что вы можете обойти это, используя другую базовую единицу, но это не совсем так, так как важна относительная точность.
Если мы используем сантиметры в качестве нашей единицы, мы теряем миллиметровую точность в диапазоне 1 048 576-2 097 152 (10-21 км от начала координат)
Если мы используем гектаметры в качестве нашей единицы, мы теряем миллиметровую точность в диапазоне 128-256 (13-26 км от начала координат)
... поэтому изменение единицы измерения на четыре порядка по-прежнему приводит к потере миллиметровой точности где-то в диапазоне десятков километров. Все, что мы сдвигаем, это то, где именно в этой полосе он попадает (из-за несоответствия между нумерацией base-10 и base-2), не сильно расширяя нашу игровую зону.
Точность, с которой допускает ваша игра, будет зависеть от деталей вашего игрового процесса, физического моделирования, размера объекта / расстояния прорисовки, разрешения рендеринга и т. Д., Поэтому сложно установить точное обрезание. Может быть, ваш рендеринг выглядит хорошо в 50 км от начала координат, но ваши пули телепортируются через стены, или чувствительный сценарий геймплея становится бесполезным. Или вы можете найти игру играет хорошо, но все имеет едва ощутимую вибрацию из-за неточностей в преобразовании камеры.
Если вы знаете требуемый уровень точности (скажем, интервал от 0,01 единицы до примерно 1 пикселя на вашем типичном расстоянии просмотра / взаимодействия, а любое меньшее смещение невидимо), вы можете использовать таблицу выше, чтобы найти, где вы теряете это точность и отступить на несколько порядков для обеспечения безопасности в случае операций с потерями.
Но если вы вообще думаете об огромных расстояниях, может быть лучше обойти все это, перецентрировав свой мир по мере движения игрока. Вы выбираете консервативно маленький квадрат или область в форме куба вокруг начала координат. Всякий раз, когда игрок выходит за пределы этого региона, переводите их и все в мире обратно на половину ширины этого региона, сохраняя игрока внутри. Поскольку все движется вместе, ваш игрок не увидит изменений. Неточности все еще могут возникать в отдаленных частях мира, но они там, как правило, гораздо менее заметны, чем происходящие прямо у вас под ногами, и вы всегда будете иметь высокую точность, доступную рядом с игроком.
Трудно ответить, так как это зависит от масштаба вашей физики: какова допустимая минимальная скорость движения, которую НЕ нужно округлять до нуля?
Если вам нужен большой мир и последовательная физика, лучше использовать класс с фиксированными точками.
Например, стрельба из пушечного ядра из любой точки мира даст вам тот же результат, а 64-битная фиксированная точка (32,32) дает вам огромную точность и больше, чем что-либо воспринимаемое в большинстве игр. Если ваше устройство составляет 1 метр, вы по-прежнему на 232 пикометра с точностью 2147483 км от источника.
Вы по-прежнему можете выполнять локальную физику с плавающей точкой в локальной ячейке, чтобы сэкономить на программировании и использовать готовый физический движок. Это все еще будет достаточно последовательным для всех практических целей.
В качестве бонуса широкая фаза и AABB имеют тенденцию быть быстрее в фиксированной точке из-за задержки FPU. Также быстрее преобразовать фиксированную точку в индекс октодерева (или квадродерева), поскольку вы можете выполнять простую битовую маскировку.
Эти операции не получают столько пользы от инструкций SIMD и конвейерной обработки, которые обычно скрывают задержку FPU.
Вы можете преобразовать позиции в плавающую точку ПОСЛЕ вычитания положения камеры в фиксированной точке, чтобы отобразить все, избегая проблем с плавающей точкой в большом мире и все еще используя обычный рендерер с использованием плавающих точек.
источник
Вы можете избежать всего этого путем умножения.
Вместо того, чтобы работать с плавающими числами, просто умножьте их на 10 ^ (x), сохраните их, а при необходимости снова умножьте на 10 ^ (- x).
От этого зависит, какой тип int вы хотите использовать.
источник