При таких многочисленных возможностях нам требуется организованный подход, в котором не будет большого количества тестов вида if О. .else. Решение состоит в идентификации соударений в каком-либо удобном порядке и помещении их в список inter.hit[] вне зависимости от порядка. В конце концов, если два соударения в списке inter.hit[] не соответствуют установленному порядку, то эти элементы списка переставляются местами. Хорошо бы, чтобы к этому моменту уже был список, в который можно поместить эти соударения.
Отдельные тесты вполне очевидны. Для того чтобы определить, попадает ли луч в бесконечную стенку, мы просто подставляем S + ct в неявную форму конического цилиндра и получаем квадратное уравнение At2 + 2Bt + С - 0. Нетрудно показать, что
A = c2x+c2y-d2,
B = Sxcx+Sycy-Fd, (14.16) C = S2x+S2y-F2.
где d = (s - 1) сг и F- 1 + (s - 1) S2. (Какой вид принимают эти уравнения для цилиндра и для конуса?)
Используем полученные коэффициенты так же, как в случае сферы. Если дискриминант В2 - Л С отрицателен, то луч проходит мимо стенки конического цилиндра. Если же дискриминант не отрицателен, то луч соударяется со стенкой, и тогда моменты соударения могут быть найдены путем решения данного квадратного уравнения. Для проверки того, происходит ли каждое соударение на стенке заданного конечного цилиндра, следует найти z-компонент точки соударения. Луч соударяется с цилиндром только в том случае, если этот 2-компонент находится в пределах от 0 до 1.
14.6. Пересечение лучей с другими примитивами Для проверки пересечения с основанием рассмотрим пересечение данного луча с плоскостью 2 = 0. Пусть соударение происходит в точке (х, у, 0). Точка соударения лежит в пределах основания, если х2 + у2 < 1. (Почему?) Аналогично для проверки пересечения с крышкой рассмотрим пересечение данного луча с плоскостью 2=1. Предположим, что соударение происходит в точке (х, у, 1). Точка соударения лежит в пределах крышки, если х2 + у2 < s2.
Цилиндр имеет более одной поверхности, и впоследствии нам захочется знать, с какой именно поверхностью происходит соударение. (Например, нам захочется наложить на стенку и на крышку различные текстуры.) Поэтому мы принимаем следующую нумерацию: стенка является поверхностью 0, основание - поверхностью 1, а крышка - поверхностью 2. Соответствующее значение помещается в поле surface каждой записи соударения.