ах + (cx-ax)t _ 1
Решая это уравнение относительно г, получим:
' = 7-а-ЖГТ-V <7Л5>
\аш-ах)-(сш-сх)
Отметим, что thjt зависит только от двух граничных координат. Пересечения с другими плоскостями дают аналогичные формулы.
Все вышеприведенные формулы легко перевести в программный код, как показано в листинге 7.4. В своей основе это алгоритм Лианга-Барски (Liang-Barsky - [Liang, 131]) с некоторыми тонкостями, предложенными Блинном [Blinn, 30].
Листинг 7.4. Отсекатель ребер (усовершенствованный Блинном)
int clipEdge(Point4& A. Point4& С) {
double tin = 0.0. tOut = 1.0. tHit:
double aBC[6], cBC[6]:
int aOutcode = 0. cOutcode = 0:
.. find ВС's for A and С .. II .. нахождение ВС для А и С ..
.. form outcodes for A and С .. // .. формирование выходных кодов для А и С
if ((aOutcode & cOutcode) !- 0) // trivial reject // тривиальное отклонение return 0:
7.4. Перспективные проекции трехмерных объектов
if((aOutcode | cOutcode) - 0) // trivial accept // тривиальный прием return 1;
for(int i = 0; i < 6: i++) // clip against each plane // отсекаем относительно каждой плоскости
{
if(cBC[i] < 0) // exits:C is outside // выходит: С находится снаружи
{
tHit - аВС[1]/(аВС[1] - cBC[i]): tOut - MINCtOut. tHit):
}
else if(aBC[i] < 0) // enters:A is outside // входит: А находится снаружи
{
tHit - aBC[1]/(aBC[1] - cBC[i]): tin - MAXCtln. tHit):
}
if(tln > tOut) return 0: // CI is empty:early out // CI пуст: досрочный выход }
// update the endpoints as necessary
// обновляем конечные точки
Point4 tmp:
if(aOutcode !- 0)
// A is out: tin has changed
// А выходит: tin изменено
{
// find updated A. (but don't change A yet)
// находим обновленную А (однако пока не меняем А)
tmp.x - А.х + tin * (С.х - А.х):
tmp.у - А.у + tin * (Су - А.у);
tmp.z - A.z + tin * (C.z - A.z):
tmp.w - A.w + tin * (C.w - A.w):
}
if(cOutcode != 0)
// С is out: tOut has changed
// С выходит: tOut изменен
{
// update С (using original value of A)
// обновляем С (используя исходное значение А)
С.х - А.х + tOut * (С.х - А.х): Су - А.у + tOut * (Су - А.у):