2015-04-17 3 views
9

Я пытаюсь реализовать текстуры для сфер в моем лучом. Мне удалось что-то сделать, но я не уверен в его правильности. Ниже приведен код для получения координат текстуры. На данный момент текстура является случайной и генерируется во время выполнения.Реализация текстуры трассировки лучей для сфер

virtual void GetTextureCoord(Vect hitPoint, int hres, int vres, int& x, int& y) { 
    float theta = acos(hitPoint.getVectY()); 
    float phi = atan2(hitPoint.getVectX(), hitPoint.getVectZ()); 

    if (phi < 0.0) { 
     phi += TWO_PI; 
    } 

    float u = phi * INV_TWO_PI; 
    float v = 1 - theta * INV_PI; 

    y = (int) ((hres - 1) * u); 
    x = (int) ((vres - 1) * v); 
} 

Это как сферы теперь посмотрите: enter image description here

Я должен был нормализовать координаты точки попадания, чтобы получить сферы, чтобы выглядеть. В противном случае они будут выглядеть следующим образом:

enter image description here

Был нормализацию точки попадания координат правильного подхода, или еще что-то нарушается в моем коде? Спасибо!

Вместо нормализации хитпоинта, я пытался переводить ее на мировом происхождение (если сфера центр был там), и был получен следующий результат:

enter image description here

Я использую разрешение 256x256 текстура кстати.

+0

Является ли 'hitPoint' всегда вычисляемым, как если бы сфера была в начале координат (а затем преобразована в другое место), или вы напрямую поддерживаете сферы, не связанные с началом координат, в вашем тесте пересечения? Вычисление phi и theta с использованием косинуса и касательной дает вам значения, соответствующие шаре, центрированному в начале координат, поэтому, если на самом деле сферы нет, отображение координаты текстуры не будет тем, что вы, вероятно, запланировали. – Wyzard

+0

BTW, 'u' и' v' - это координаты текстуры, и функция для вычисления координат текстур обычно просто возвращает их. Сопоставление их с целыми индексами texel не относится к сферам и должно выполняться в другом месте. – Wyzard

+0

У меня была аналогичная проблема, когда я генерировал текстуры во время выполнения для алгоритма штриховки в реальном времени. Моя ошибка заключалась в том, чтобы вычислить координаты текстуры в мировом пространстве, в то время как их нужно рассматривать в локальном пространстве. hitPoint находится в мире/в представлении или в локальном пространстве? – codingadventures

ответ

4

Непонятно, что вы подразумеваете под «нормализацией» точки попадания, поскольку в коде, который вы опубликовали, ничего не нормализуете, но вы упомянули, что ваша точка попадания находится в мировом пространстве.

Кроме того, вы не сказали, какое текстурирование вы пытаетесь реализовать, но я предполагаю, что вы хотите, чтобы ваши координаты текстуры U и V отображали широту и долготу на поверхности сферы.

Ваша первая проблема заключается в том, что для преобразования декартовых координат в сферические координаты требуется, чтобы сфера была центрирована в начале координат в декартовом пространстве, что не соответствует действительности в мировом пространстве. Если точка попадания находится в мировом пространстве, вы должны вычесть точку центра мира в космосе, чтобы получить эффективную точку в локальных координатах. (Вы уже поняли эту часть и обновили вопрос с новым изображением.)

Вторая проблема заключается в том, что способ вычисления theta требует, чтобы сфера имела радиус 1, что неверно даже после перемещения центра сферы в начало координат. Вспомните свою тригонометрию: аргумент acos - это отношение со стороны треугольника к его гипотенузе и всегда находится в диапазоне (-1, +1). В этом случае ваша координата Y - это сторона, а радиус сферы - гипотенуза. Поэтому вы должны разделить радиус сферы при вызове acos. Также неплохо закрепить значение в диапазоне (-1, +1), если ошибка округления с плавающей запятой помещает его немного снаружи.

(В принципе вам также необходимо разделить координаты X и Z на радиус, но вы используете только те, которые используются для обратного касания, и их разделение радиусом не изменяет их коэффициент и, следовательно, не изменится phi.)


Прямо сейчас ваша сфера пересечение и текстурные координаты функция работает в мировом пространстве, но вы, вероятно, будет полезно позже реализовать transformation matrices, которые позволяют трансформировать вещи из одного координатное пространство к другому.Затем вы можете изменить свои сферические функции для работы в локальном координатном пространстве, где центр - это начало координат, а радиус равен 1, и придать каждому объекту связанную матрицу преобразования, которая отображает локальное координатное пространство в мировое координатное пространство. Это упростит ваш код пересечения лучей/сфер и позволит удалить вычитание из начала и радиус из GetTextureCoord (так как они всегда (0, 0, 0) и 1 соответственно).

Чтобы пересечь луч с объектом, вы должны использовать матрицу преобразования объекта для преобразования луча в локальное координатное пространство объекта, выполнить пересечение (и вычислить координаты текстуры) там, а затем преобразовать результат (например, нажать точка и поверхность нормальная) обратно в мировое пространство.

Смежные вопросы