#algorithm #geometry
#алгоритм #геометрия
Вопрос:
У меня есть сферическое поле высот, определяемое функцией f(x, y, z)
, которая возвращает расстояние от начала координат поверхности поля высот линии, которая проходит от начала координат до (x,y,z)
конца .
(Другими словами, изоповерхность для моего поля высоты равна |x,y,z| = f(x,y,z)
.)
(Кроме того, для обсуждения ниже я собираюсь предположить, что surface(x,y,z)
это местоположение точки на поверхности непосредственно под (x,y,z)
ней .)
При рендеринге этого мне нужно вычислить нормаль для любой точки в поле высоты. Какой самый дешевый способ сделать это?
Чтобы вычислить нормаль к точке в прямоугольном поле высот, обычный трюк заключается в (x,y,z)
небольшом смещении в двух направлениях, параллельных номинальной поверхности, вычислении трех точек на поле высот для образования треугольника, а затем использовании перекрестного произведения для вычисления нормали треугольника. Это просто, поскольку три точки могут быть просто surface(x,y,z)
surface(x 1,y,z)
и surface(x,y 1,z)
(или аналогичными). Но для сферического поля высоты это немного сложнее, потому что нормаль может указывать в любом направлении. Простое смещение на x
и y
не подойдет, потому что, если две мои точки попадают на радиус, то surface()
из них вернутся в одно и то же местоположение, и я не получу треугольник.
В прошлом я использовал вектор <x,y,z>
как радиус от начала координат сферы; затем вычислял вектор, перпендикулярный ему; затем поворачивал этот вектор вокруг <x,y,z>
, чтобы получить мои три точки. Но это неудобно и дорого, и в этом не должно быть необходимости. Должен быть более дешевый способ. Что это?
Комментарии:
1. Можете ли вы выделить случаи, когда «трюк» не сработает, так что вам нужно использовать дорогостоящую технику только в этих случаях? Это предполагает, конечно, что 1) определение того, когда трюк не срабатывает, обходится дешево, и 2) трюк работает большую часть времени.
2. У меня будут проблемы только тогда, когда радиус моей сферы совпадает с осью X, Y или Z (при условии, что я перемещаюсь в этих направлениях). Я мог бы протестировать их, но есть неприятные крайние случаи — радиус, который почти вдоль оси, в конечном итоге приведет к двум
surface()
точкам, которые находятся очень близко друг к другу, и это даст мне странные проблемы с округлением / точностью.
Ответ №1:
Вычислите surface()
точки и, если они достаточно близки, чтобы вызвать проблемы, выполните более дорогостоящий (но точный) расчет; в противном случае используйте дешевый / простой расчет.