Ładowanie
popup

Przyspieszanie Frustum Culling

2010-12-01 15:37:00

Dziś mały tip o optymalizacji Frustum Culling(zdefiniowany jest na 6 płaszczyznach) dla OBBox i AABBox (Prostopadłościan dowolnie zorientowany i 'wyrównany' do osi układu współrzędnych). Zacznę od struktury boxów:

class AABBox{ Vec3f min; // maksymalne wartości dla każdej z osi Vec3f max; // minimalne wartości dla każdej z osi }; class OBBox{ Vec3f center; // środek prostopadłościanu Vec3f axis[3]; // wektory opisujące układ współrzędnych Vec3f size; // długośći dla każdej z osi };

Najprostszym sposobem na sprawdzenie zawierania takich boxów w frustumie jest sprawdzenie zawierania każdego z jego wierzchołków dla każdej z 6 płaszczyzn frustuma. Żeby to troszkę przyspieszyć wyznaczam jeden wierzchołek (punkt p), który jest "najdalej" wysunięty względem normalnej danej płaszczyzny i sprawdzam relację tego punktu względem tej płaszczyzny. Jeśli dany wierzchołek znajduje się "nad" płaszczyzną - box znajduje się w zasięgu widzenia. Większość tego typu implementacji np. http://www.lighthouse3d.com/opengl/viewfrustum/index.php?gatest3 oblicza niepotrzebnie czy box przecina się z płaszczyzną - co narzuca niepotrzebny drugi test punkt-płaszczyzna i jest w większości przypadków niepotrzebne.

Wyliczanie punktu p dla AABBox:

// aabb - nasz box // normal - normalna płaszczyzny Point3f p=aabb.min; if(normal.x>=0) p.x=aabb.max.x; if(normal.y>=0) p.y=aabb.max.y; if(normal.z>=0) p.z=aabb.max.z;

Wyliczanie punktu dla OBBox:

// obb - nasz box // normal - normalna płaszczyzny // definiuje punkt poczatkowy (bedziemy go przesuwac wzgledem kazdej osi o odpowienie wartosci) Point3f p=obb.center; for(int i=0;i<3;++i){ float d=obb.axis[i]^normal; // projekcja normalnej wzdluz tej osi (operator ^ wykonuje iloczyn skalarny) // jesli d jest mniejsze od 0 - szukany punkt jest po negatywnej stronie danej osi (-axis[i]) if(d>0.f) p+=obb.axis[i]*obb.size[i]; else p-=obb.axis[i]*obb.size[i]; }

Dysponując takim punktem p, wystarczy sprawdzić czy znajduje się on "nad" płaszczyznami frustuma. Przykładowy kod sprawdzający:

// dla każdej płaszczyzny frustuma: for(int i=0;i<6;++i){ // m_planes - tablica z płaszczyznami if(!m_planes[i].Distance(p)>0) // sprawdzam czy punkt p znajduje się nad płaszczyzną return false; // jeśli nie - box napewno jest niewidoczny (można przerwać sprawdzanie) } return true;

Wykonałem prosty programik testowy, gdzie można sobie sprawdzić działanie tego kodu: frustm.culling.2.zip

Demo Frustum Culling...
Demo Frustum Culling...

Jak widać na tym screenie - przyrost wydajnosci jest, ale oczywiście nie ma większego sensu się bawić w takie optymalizacje - chyba że "dla sportu" ;)

Tagi: Programowanie Engine Optymalizacja

Komentarze:

avatar
ankac
Witam, proszę o kontakt na podany adres mailowy. Wielka prośba !
Data: 2011-11-21 13:34:09