• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

OpenGL - "frustum culling" - usuwanie niewidocznych powierzchni

VPS Starter Arubacloud
0 głosów
274 wizyt
pytanie zadane 3 kwietnia 2019 w Java przez grubix Nowicjusz (210 p.)

Witajcie,
mam problem z tzw. "frustum culling". Chciałbym obliczyć wektory normalne do powierzchni wyznaczonych na podstawie pozycji, rotacji kamery oraz jej parametrów: fov, near_plane, far_plane, lecz pomimo wielu przeczytanych toutoriali, nadal mi to nie wychodzi. Link do głównego toutorialu LINK


Klasa Camera.java

public class Camera {

	private Vector3f position;
	private Vector3f rotation = new Vector3f(0f,0f,0f);  // x - Pitch, y - Yaw, z - Roll

	private float fov = 90;
	private float nearPlane = 0.1f;
	private float farPlane = 1000f;	

}

Klasa Maths.java - tworzenie macierzy projekcji i macierzy widoku

public class Maths {	

         public static Matrix4f createProjectionMatrix(float FOV, float FAR_PLANE, float NEAR_PLANE) {

        //Main.getWindowWidth() - szerokość okna
        //Main.getWindowHeight() - wysokość okna

		float aspectRatio = (float)Main.getWindowWidth() / (float)Main.getWindowHeight();
		float y_scale = ((float)(1.0f / Math.tan(Math.toRadians(FOV / 2.0f))) * aspectRatio);
		float x_scale = y_scale / aspectRatio;
		float frustum_length = FAR_PLANE - NEAR_PLANE;
		
		Matrix4f projectionMatrix = new Matrix4f();
		projectionMatrix.m00(x_scale);
		projectionMatrix.m11(y_scale);
		projectionMatrix.m22(-((FAR_PLANE + NEAR_PLANE) / frustum_length));
		projectionMatrix.m23(-1.0f);
		projectionMatrix.m32(-((2 * NEAR_PLANE * FAR_PLANE) / frustum_length));
		projectionMatrix.m33(0.0f);
		
		return projectionMatrix;
	}
	public static Matrix4f createViewMatrix(Camera camera) {
        Matrix4f viewMatrix = new Matrix4f().identity();
        
        Vector3f cameraRotation = camera.getRotation();

        //cameraRotation.x - Pitch
        //cameraRotation.x - Yaw
        //cameraRotation.x - Roll

        viewMatrix.rotate((float) Math.toRadians(cameraRotation.x), new Vector3f(1,0,0), viewMatrix);
        viewMatrix.rotate((float) Math.toRadians(cameraRotation.y), new Vector3f(0,1,0), viewMatrix);
        viewMatrix.rotate((float) Math.toRadians(cameraRotation.z), new Vector3f(0,0,1), viewMatrix);
        
        Vector3f negCameraPos = new Vector3f(camera.getPosition()).negate();
        viewMatrix.translate(negCameraPos);
        
        return viewMatrix;	
	}

}

Przykładowe wartości macierzy: (wymiary okna 1300 x 650)

No i tutaj zaczyna się problem, bo zbytnio nie rozumiem w jaki sposób z tych macierzy wyciągnąć informacje o wektorach normalnych do odpowiednich powierzchni. Jak na razie wszystkie próby kończą się czymś takim:

Za każdą wskazówkę będę bardzo wdzięczny :)

komentarz 3 kwietnia 2019 przez Patrycjerz Mędrzec (192,340 p.)
Może tak będzie prościej... Jaki efekt graficzny chcesz uzyskać? W skrócie, po co ci te wektory normalne? Czy chcesz uzyskać ich współrzędne w koordynatach kamery?
komentarz 3 kwietnia 2019 przez grubix Nowicjusz (210 p.)
przeniesione 3 kwietnia 2019 przez Patrycjerz

Tak jak na pierwszym zdjęciu które wrzuciłem - na podstawie otrzymanych wektorów normalnych byłbym wstanie sprawdzać które obiekty znajdują się w polu widzenia kamery, a które nie. Obecnie dla wszystkich obiektów, nawet tych niewidocznych obliczana jest macierz transformacji i wiele obliczeń w shaderach co jest zupełnie bez sensu. Ostatnie wrzucone przeze mnie zdjęcie to sprawdzenie czy obliczone wektory normalne są poprawne:
 

	in vec3 vertices;
    uniform vec4 clipPlane; //Wektor zawięrający współczynniki równania płaszczyzny (Ax +By + Cz + D = 0)

    void main(void) {
        vec4 worldPosition = transformationMatrix * vec4(vertices,1.0);
        gl_ClipDistance[0] = dot(worldPosition, clipPlane);

Tak więc chodzi mi jedynie o optymalizację.

komentarz 6 kwietnia 2019 przez grubix Nowicjusz (210 p.)

@grubix, Znalazłem rozwiązanie problemu. Jeżeli ktoś tak jak ja, korzysta z toutoriali od ThinMatrix, używa biblioteki LWJGL 3 oraz JOML i ma podobny problem, otrzymywanie wektorów normalnych do kolejnych płaszczyzn wygląda nastepująco:

Matrix4f V = Maths.createViewMatrix(camera).transpose(); //TRANSPOZYCJA MACIERZY WIDOKU!!!
Matrix4f P = new Matrix4f(scene.getProjectionMatrix()).transpose();  //TRANSPOZYCJA MACIERZY PROJEKCJI!!!
Matrix4f VP = V.mul(P);

//LEFT
float a_l = VP.m00() + VP.m30();
float b_l = VP.m01() + VP.m31();
float c_l = VP.m02() + VP.m32();
float d_l = VP.m03() + VP.m33();

//RIGHT
float a_r = -VP.m00() + VP.m30();
float b_r = -VP.m01() + VP.m31();
float c_r = -VP.m02() + VP.m32();
float d_r = -VP.m03() + VP.m33();

//TOP
float a_t = -VP.m10() + VP.m30();
float b_t = -VP.m11() + VP.m31();
float c_t = -VP.m12() + VP.m32();
float d_t = -VP.m13() + VP.m33();

//BOTTOM
float a_b = VP.m10() + VP.m30();
float b_b = VP.m11() + VP.m31();
float c_b = VP.m12() + VP.m32();
float d_b = VP.m13() + VP.m33();

//NEAR
float a_n = VP.m20() + VP.m30();
float b_n = VP.m21() + VP.m31();
float c_n = VP.m22() + VP.m32();
float d_n = VP.m23() + VP.m33();

//FAR
float a_f = -VP.m20() + VP.m30();
float b_f = -VP.m21() + VP.m31();
float c_f = -VP.m22() + VP.m32();
float d_f = -VP.m23() + VP.m33();

Współczynniki a,b,c tworzą wektor normalny do odpowiedniej płaszczyzny, który ewentualnie można znormalizować. Czyli przykładowo dla "lewej" płaszczyzny:
wektor normalny V_L = { a_l , b_l, c_l }, równanie płaszczyzny: a_l * x + b_l * y + c_l * z + d_l = 0
 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
0 odpowiedzi 152 wizyt
pytanie zadane 25 października 2016 w Java przez Patryk8090 Użytkownik (520 p.)
0 głosów
0 odpowiedzi 266 wizyt
pytanie zadane 28 lutego 2016 w Java przez NTXFN Gaduła (3,430 p.)
0 głosów
1 odpowiedź 175 wizyt
pytanie zadane 6 czerwca 2020 w OpenGL, Unity przez siemaziom Nowicjusz (160 p.)

92,452 zapytań

141,262 odpowiedzi

319,085 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...