Случайный вектор в полусфере в пределах заданного угла (наиболее оптимальный алгоритм)

При трассировке лучей нередко возникает необходимость генерировать случайный вектор в пределах полусферы, отклоненный от исходного на какой-то заданный угол. На просторах интернета не нашлось внятных и развернутых ответов на данный вопрос. Хоть в математике я не шибко силен, все же хотелось бы понимать что происходит, а не просто брать готовую формулу.

Еще раз вкратце о сути задачи:

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

Понимаю, что задача стара как мир, но все же, хотелось бы, чтобы кто-то разжевал тупому гуманитарию как это правильно делается. Причем можно привести наиболее оптимальный с точки зрения математики пример, а также пример наиболее оптимальный с точки зрения кода. Нередко они разнятся. Спасибо.


Ответы (1 шт):

Автор решения: MBo

Вначале сгенерируем вектор, перпендикулярный данному A

Для этого найдём наибольший и второй по амплитуде компоненты A. Пусть это A.Y и A.Z.

Теперь создадим вектор B = (0, A.Z, -A.Y) - т.е. обнулим наименьший компонент, а два больших обменяем и изменим знак одного из компонентов. Можно заметить, что скалярное произведение A.dot.B равно нулю, т.е. векторы перпендикулярны.

Теперь создадим ещё один вектор C = A x B, используя векторное произведение. Он перпендикулярен как A, так и B.

Нормализуем B и С (разделим на длину)

Выберем случайный угол fi в диапазоне 0..2*Pi и создадим вектор

D = B * cos(fi) + C * sin(fi)

Получился случайный единичный вектор, который лежит в плоскости, нормальной A

Теперь выберем случайный угол theta в в пределах этого самого угла (т.е. до Pi/2 или меньше) и сделаем искомый вектор (да, A нормализован)

E = A * cos(theta) + D * sin(theta)
→ Ссылка