Гшва 2. Удаление невидимых поверхностей
Так, портал В в антитень не попадает и поэтому сразу же может быть отброшен. С другой стороны, портал А частично попадает в антитень и поэтому через него может быть видна лежащая за ним комната.
Следующим шагом будет определение видимости за порталом А. Для этого портал А сначала обрезается по границе антитени, и комната, лежащая за ним, становится новым generatorLeaf. После этого описанная процедура применяется снова.
Обратите внимание, что на рис. 2.32 вместо портала Л используется обрезанный на предыдущем шаге портал А'.
В результате мы получаем рекурсивную процедуру определения видимости. Она может быть выражена при помощи следующего фрагмента псевдокода:
def buildPvs (leaf, pvs): pvs = [leaf]
for srcPortal in leaf.portals: dstLeaf = srcPortal.leafs [0]
if dstLeaf == leaf:
dstLeaf = srcPortal.leafs [1]
for dstPortal in dstLeaf.portals:
if dstPortal.plane != srcPortal.plane: recursePvs ( leaf, srcPortal, dstLeaf, dstPortal, pvs )
Функция recursePvs служит для рекурсивного обхода цепочки комнат и порталов. В ходе ее работы по очереди выбирается genLeaf п проверяются все его порталы.
W
def recursePvs ( srcLeaf, srcPortal, dstLeaf, dstPortal, pvs ): genLeaf = dstPortal.leafs [0]
if genLeaf == dstLeaf:
genPortal = dstPortal.leafs [1]
pvs.insert ( genLeaf )
for genPortal in genLeaf.portals:
if dstPortal.plane == genPortal.plane: continue
clippedPortal = clipPortalToAntiPenumbrae ( srcPortal,
dstPortal, genPortal )
if clippedPorta.isEmpty: continue
recursePvs ( srcLeaf, srcPortal, clippedPortal, genLeaf, pvs )
Удаление невидимых поверхностей
Процедура clipPortalToAntiPenumbrae служит для отсечения портала по антитени, построенной по двум другим порталам.
.а
def clipPortalToAntiPenumbrae ( srcPortal, dstPortal, portal ): planes = []
addClipPlanes ( srcPortla, dstPortal, planes ) addClipPlanes ( dstPortal, srcPortal, planes )
for plane in planes:
loc = plane.classify ( portal ) sloe = plane.classify ( srcPortal )