{
inter.hit[++iC] - nextHit: // put hit data on combined list // помещаем данные о соударении в объединенный список
comblnside - newlnside:
inter.hit[iC].isEntering - comblnside:
}
else
// smaller hit time is on right list // меньшее время соударения находится в правом списке {
nextHit - rtInter.hit[iR++]: // grab right item: inc to next // берем правый элемент; переходим к следующему
rtlnside - Irtlnside: // reverse the inside-ness
// изменяем внутреннее состояние на противоположное
newlnside - lftlnside && Irtlnside: // new combined state // новое состояние составного объекта
if(newlnside !- comblnside)
m
Введение в трассировку лучей
Листинг 14.18 (продолжение)
// has result state changed? // изменилось ли результирующее состояние? {
inter.hit[++iC] - nextHit:
comblnside - newlnside:
inter.hit[iC].isEntering - comblnside:
if(comblnside)
{
nextHit. hitNormal.flipO: // reverse normal on right object // инвертируем нормаль на правом объекте
inter.hit[iC].hitObject - leftObject:
// point to left object
// указываем на левый объект
} }
// end else // конец случая else }
// end of for - while both lists nonempty // конец цикла for - пока оба списка не пусты
while(iL < 1 ft Inter.numHi ts) // gobble rest of left list // «расправляемся» с остатком левого списка
{
nextHit - 1 ftInter.hitCiL++]:
Iftlnside - !Iftlnside:
inter.hit[++iC] - nextHit:
inter.hit[iC].isEntering - Iftlnside:
}
inter.numHits - iC + 1: return (inter.numHits > 0);
}
Отметим, что при компоновке списков необходимо следить за тем, чтобы в каждую новую запись hit[] была помещена вся необходимая информация. В частности, должны быть правильно заполнены поля isEntering и hitObject, поскольку если соударение является первым соударением луча, то мы будем искать свойства соударения с поверхностью в самом hitObject. Когда соударение при выходе из правого объекта вызывает вхождение луча в сам объект, мы должны быть уверены, что информация об этом соударении указывает на левый объект, поэтому то, что мы видим в «дыре», является свойствами левого объекта.