Самая большая проблема с работой с позициями с плавающей запятой в больших масштабах заключается в том, что вы быстро теряете точность по мере того, как вы все дальше и дальше отдаляетесь от источника.
Чтобы исправить это, вам необходимо выразить все позиции по сравнению с чем-то другим, кроме источника. Самый простой способ сделать это, чтобы разделить мир на сетку и сохранить позиции всех субъектов что-то вроде этого:
struct Position {
int kilometers[3]; // x, y and z offset in kilometers
float offset[3]; //x, y and z offset in meters
};
положение камеры хранится также, как это, и когда пришло время, чтобы сделать вас сделать что-то вроде этого:
void
getRelativePosition(float& x, float& y, float& z, const Position& origin, const Position& object) {
x = (object.kilometers[0] - origin.kilometers[0]) * 1000.0f +
(object.offset[0] - origin.offset[0]);
//Ditto for y and z
}
//Somewhere later
float x, y, z;
getRelativePosition(x, y, z, camera.position(), object.position());
renderMesh(x, y, z, object.mesh());
(Для простоты я проигнорировал ориентацию камеры и объектов в этом примере, так как нет никаких особых проблем, связанных с этим).
Если вы работаете с непрерывным миром в галактическом масштабе, вы можете заменить параметр kilometers
на long long
(64 бит), предоставляя вам эффективный диапазон в 1,8 миллиона световых лет.
EDIT: Чтобы использовать эту функцию для непрерывной геометрии, таких как рельеф местности и т.д., вы должны разделить местность на куски размера один квадратные километры, координаты вершин в куске местности должны быть в диапазоне [0, 1000].
Кроме того, в функции getRelativePosition
выше вы можете изменить его, чтобы он возвращает bool
и вернуть false
, если разница в километрах больше некоторого порогового значения (скажем, расстояние до вашей дальней плоскости отсечения).
hmmm Я не уверен, как это могло бы обойти ошибку с плавающей точкой, так как в очень больших масштабах вы все равно будете умножать 1000 на очень большое число, и ваша справедливая замена одного установленного масштаба и всех его проблем для new one =/ –
ах Теперь я вижу, что вы получаете, но он все еще оставляет проблему очень очень больших структур, например планеты/горы/луны –
@Tom Вы не можете хранить планету как одну сетку, по моему отредактированному ответу –