комнатах не видно через портал и выполнять все преобразования над ними, чтобы установить их невидимость, является слишком расточительным. Отсечение сразу в трехмерном пространстве позволит быстро отбросить все такие грани. Для дальнейшего ускорения отсечения граней можно организовать их в иерархическую структуру.
При этом возникает необходимость построения усеченной пирамиды по положению наблюдателя и видимой части портала. Это делает метод build-Frustrum, исходный текст которого приводится ниже. Обратите внимание на необходимость добавления в качестве ближней плоскости отсечения плоскости самого портала.
void SubScene :: buildFrustrum ( const Vector3D& pos,
const Polygon3DS clipPoly, Frustrums frustrum ) const
{
int numVertices = clipPoly.getNumVertices ();
Vector3D newPos ( pos );
frustrum.set ( newPos, numVertices, poly.getVertices () );
// near clipping plane Plane clipPlane ( *poly.getPlane () );
// flip if camera is in positive halfspace if ( clipPlane.classify ( pos ) != IN_BACK ) clipPlane. flip () ,-
frustrum.setNearPlane ( clipPlane );
}
Считая все грани непрозрачными и выпуклыми, мы можем реализовать метод render уже на языке С++ следующим образом:
in
void SubScene :: render ( Views view, const Cameras camera,
const Frustrums viewFrustrum ) const
{
// polygon to keep clipped poly Polygon3D tempPoly ( "tempPoly", MAX_VERTICES );
view, lock () ,- // prepare view for drawing
view.apply ( camera ); // render through portals
for ( Array :: Iterator it = polys .getlterator () ,-! it. end () ,- ++it )
Пишем портальныйрендерер (часть I)
{
Polygon3D * po]y = (Polygon3D *) it,value () ;
if ( Ipoly -> isFront.Facing ( camera. getPos () ) ) continue;
// if lies outside frustrum => reject it if ( !viewFrustrum.contains ( poly -> getBoundingBox () ) ) continue;
renderPoly ( view, camera, poly, tempPoly, viewFrustrum, ob ) ;
}
view.unlock (); // commit: drawing