14.9. Использование экстентов В следующих разделах мы будем генерировать лучи для затенения, отражения и преломления; а поскольку эти лучи испускаются из произвольных точек сцены, то не существует такого экрана, на котором можно было бы поместить проекцию. Однако данная технология прекрасно работает для лучей глаза и способна многократно ускорить процесс трассировки лучей.
Проекционные экстенты для каждого объекта сцены создаются на этапе предварительной подготовки и записываются вместе со своими объектами так же, как это делалось для прямоугольного и сферического экстентов. Для того чтобы обеспечить эту запись, добавим к классу GeomObj поле IntRect screenExtent. Кроме того, расширим класс Ray так, чтобы луч «знал», через какие строку и столбец на экране он проходит. Придадим лучу дополнительную информацию: его так называемый «рекурсивный уровень» («recursion level»), который будет играть важную роль в нашей дальнейшей работе с отражением и преломлением лучей. Здесь же этот уровень просто фиксирует, является или нет данный луч лучом глаза. Для лучей глаза рекурсивный уровень задается равным нулю.
Листинг 14.14. Тестирование относительно сферических экстентов внутри метода hit() для цилиндра
bool TaperedCylinder::hit(Ray Sr. Intersection Sinter) {
ifCr.recurseLevel == 0 &&
r.col < projExtnt.left ! I
r.col > projExtnt.right| |
r.row < projExtnt.bottom ||
r.row > projExtnt.top ) return false; // misses screen extent // проходит мимо экранного экстента
if(!rayHitsSphereExtent(г.worldSphereExtent)) return false:
make, and inverse transform, the generic ray II создаем луч с его обратным преобразованием в базог г< // системе координат
if(!rayHitsSphereExtent(genRay.genSphereExtent)) return false:
…do expensive full testing with the generic cylinder… II делаем дорогое полное тестирование относительно // базового цилиндра }
В процессе трассировки лучей в начале метода hit О для каждого типа объекта выполняется новый тест - перед тестами относительно сферических или прямоугольных экстентов. В листинге 14.14 показано, где расположен этот тест для класса TaperedCyl i nder. (Такой же тест используется для всех типов объектов, за исключением сферы.) Сравните этот листинге листингом 14.13. В этом тесте проверяется, является ли данный луч лучом глаза, и если да, то строка и столбец этого луча сравниваются с соответствующими элементами проекционного экстента, хранящимися вместе с объектом. Если строка или столбец луча лежат вне проекционного экстента, то такой луч должен пройти мимо данного объекта; следовательно, метод hit немедленно возвращает false. Этот тест действительно выполняется очень быстро.