Hallo zusammen!
Zurzeit beschäftige ich mich mit dem Frustum Culling. Ich möchte dazu den
Clip Space Ansatz verwenden.
Jetzt habe ich dabei eine Verständnisfrage.
Ich verwalte die Szene mit einen Szenegraphen, wobei jeder Knoten eine Model-Matrix hat. Die Kamera ist auch ein Knoten in dem Graphen. Die View-Matrix ist dabei die Inverse der Model-Matrix der Kamera.
Die Projektions-Matrix sieht so aus:
|
C#-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
float fov = 45.0f;
float aspect = 1.0f;
float near = 0.1f;
float far = 100.0f;
float y_scale = (float) (1f / Math.tan(Math.toRadians(fov / 2f)));
float x_scale = y_scale / aspect;
float frustum_length = far - near;
// Matrix ist eine Einheitsmatrix 4x4
matrix.m00 = x_scale;
matrix.m11 = y_scale;
matrix.m22 = -((far + near) / frustum_length);
matrix.m23 = -1;
matrix.m32 = -((2 * near * far) / frustum_length);
matrix.m33 = 0;
|
Die Koeffizienten der Ebenen erstelle ich dann, wie in der Webseite beschrieben.
|
C#-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
Matrix4f a = Matrix4f.mul(projection, view, null);
// left
coefficients[0] = new Vector4f(
a.m00 + a.m30,
a.m01 + a.m31,
a.m02 + a.m32,
a.m03 + a.m33);
// right
coefficients[1] = new Vector4f(
-a.m00 + a.m30,
-a.m01 + a.m31,
-a.m02 + a.m32,
-a.m03 + a.m33);
// bottom
coefficients[2] = new Vector4f(
a.m10 + a.m30,
a.m11 + a.m31,
a.m12 + a.m32,
a.m13 + a.m33);
// top
coefficients[3] = new Vector4f(
-a.m10 + a.m30,
-a.m11 + a.m31,
-a.m12 + a.m32,
-a.m13 + a.m33);
// near
coefficients[4] = new Vector4f(
a.m20 + a.m30,
a.m21 + a.m31,
a.m22 + a.m32,
a.m23 + a.m33);
// far
coefficients[5] = new Vector4f(
-a.m20 + a.m30,
-a.m21 + a.m31,
-a.m22 + a.m32,
-a.m23 + a.m33);
for (int i = 0; i < 6; i++) {
coefficients[i].normalise();
}
|
Wenn ich dann prüfen möchte, ob ein Punkt in dem Frustum liegt, muss ich den Punkt mit den Koeffizienten multiplizieren (Skalarprodukt).
|
C#-Quelltext
|
1
2
3
4
5
6
7
8
9
|
public boolean contains(final Vector4f v) {
for (int i = 0; i < 6; i++) {
if (Vector4f.dot(coefficients[i], v) < 0.0f) {
return false;
}
}
return true;
}
|
Eigentlich beziehen sich die Ebenen doch auf das Weltkoordinatensystem (WKS). Dann müsste ich doch auch den zu überprüfenden Punkt in das WKS überführen, bevor ich ihn überprüfen kann. Oder mache ich das mit Hilfe dieser Koeffizienten? Eigentlich ja schon, oder? Da stehe ich im Moment auf dem Schlauch.
Ich hoffe ihr könnt mir da weiterhelfen.
Gruß,
wozzy