Программа демонстрирует, как использовать буфер трафарета для реализации логических операций с твердыми телами, на примере трех базовых фигур: куб, сфера и конус. Рисование фигур вынесено в отдельные процедуры, для манипуляций с ними введен процедурный тип:
type
proctype = procedure;
var
а: proctype = procCube;
b: proctype = procSphere;
Логическая операция OR заключается в том, что воспроизводятся обе фигуры
procedure procOR (a, b: proctype);
begin
glPushAttrib(GL_ALL_ATTRIB_BITS);
glEnable(GL_DEPTH_TEST);
а;
b;
glPopAttrib;
end;
Для получения части фигуры А, находящейся внутри В, предназначена следующая процедура:
procedure inside(a, b: proctype; face, test: GLenum);
begin
// рисуем А в буфере глубины, но не в буфере кадра
glEnable(GL_DEPTH_TEST);
glColorMask(FALSE, FALSE, FALSE, FALSE};
glCullFace(face);
а;
// буфер трафарета используется для нахождения части А, находящейся
// внутри В. Во-первых, увеличиваем буфер трафарета для передней
// поверхности В.
glDepthMask{FALSE);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 0, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glCullFace(GL_BACK); // отсекаем заднюю часть В
b;
// затем уменьшаем буфер трафарета для задней поверхности
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
glCullFace(GL_FRONT); // отсекаем переднюю часть В
b;
// теперь рисуем часть фигуры А, находящуюся внутри В
glDepthMask(TRUE);
glColorMask(TRUE, TRUE, TRUE, TRUE);
glStencilFunc(test, 0, 1);
glDisable(GL_DEPTH_TEST);
glCullFace(face);
glDisable(GL_STENCIL_TEST); // отключаем буфер трафарета
end;
Вспомогательная процедура fixup предназначена для регулирования содержимого буфера глубины, фигура выводится только в этот буфер:
procedure fixup (а: proctype);
begin
glColorMask(FALSE, FALSE, FALSE, FALSE); // отключаем вывод в кадр
glEnable(GL_DEPTH_TEST); // включаем тестирование глубины
glDisable(GL_STENCIL_TEST); // отключаем операции с трафаретом
glDepthFunc(GL_ALWAYS); // все точки фигуры - в буфер глубины а;
// рисуем фигуру только в буфер глубины
glDepthFunc(GL_LESS); // отключаем буфер глубины
end;
Логическая операция AND состоит в нахождении пересечения двух фигур: находим часть А, находящуюся внутри В, затем находим часть В, находящуюся внутри А:
procedure procAND (a, b: proctype);
begin
inside(a, b, GL_BACK, GL_NOTEQUAL);
fixup(b); // рисуем фигуру В в буфер глубины
inside(b, a, GL_BACK, GL_NOTEQUAL);
end;
Вычитание фигур реализовано так: находим часть А, находящуюся внутри В, затем находим ту часть задней поверхности В, что не находится в А.
procedure sub (a, b: proctype);
begin
inside(a, b, GL_FRONT, GL_NOTEQUAL);
fixup(b);
inside(b, a, GL_BACK, GL_EQUAL);
end;
Клавиши управления курсором предназначены для перемещения фигур в пространстве, регистровые клавиши <Shift> и <Alt> используются для выбора перемещаемой фигуры. Клавиша 'Z' ответственна за приближение точки зрения, набор фигур меняется при нажатии 'C' Здесь обратите внимание на то, как анализируется значение переменных процедурного типа:
If (@A = @procCube) and (@B = @procSphere) then begin
A: = procSphere;
В: = procCone;
end
else begin If (@A = SprocSphere) and (@B = @procCone) then begin
A := procCone;
В .= procCube,
end
else begin
A o= procCube;
В := procSphere;
end
end;
Думаю, этот пример окажется очень полезным для многих читателей
Рис 4.26 демонстрирует результат работы еще одного примера на буфер трафарета, проекта из подкаталога Ех38, в котором красиво переливается поверхность додекаэдра с приклеенной буквой "Т".