Browse Source

Fixed view frustum calculation and culling

Thomas Buck 9 years ago
parent
commit
7f4de9d5a7
3 changed files with 73 additions and 87 deletions
  1. 3
    0
      ChangeLog.md
  2. 14
    10
      include/RoomData.h
  3. 56
    77
      src/Camera.cpp

+ 3
- 0
ChangeLog.md View File

@@ -2,6 +2,9 @@
2 2
 
3 3
 ## OpenRaider (0.1.3) xythobuz <xythobuz@xythobuz.de>
4 4
 
5
+    [ 20141223 ]
6
+    * View frustum calculation now working
7
+
5 8
     [ 20141222 ]
6 9
     * Added basic (not yet working) view frustum culling
7 10
 

+ 14
- 10
include/RoomData.h View File

@@ -14,7 +14,16 @@
14 14
 
15 15
 class BoundingBox {
16 16
   public:
17
-    BoundingBox(glm::vec3 min, glm::vec3 max) : a(min), b(max) { }
17
+    BoundingBox(glm::vec3 min, glm::vec3 max) : a(min), b(max) {
18
+        corner[0] = glm::vec3(a.x, a.y, a.z);
19
+        corner[1] = glm::vec3(b.x, a.y, a.z);
20
+        corner[2] = glm::vec3(a.x, b.y, a.z);
21
+        corner[3] = glm::vec3(a.x, a.y, b.z);
22
+        corner[4] = glm::vec3(b.x, b.y, a.z);
23
+        corner[5] = glm::vec3(a.x, b.y, b.z);
24
+        corner[6] = glm::vec3(b.x, a.y, b.z);
25
+        corner[7] = glm::vec3(b.x, b.y, b.z);
26
+    }
18 27
 
19 28
     bool inBox(glm::vec3 p) {
20 29
         return ((p.y >= a.y) && (p.y <= b.y) && inBoxPlane(p));
@@ -24,19 +33,14 @@ class BoundingBox {
24 33
         return ((p.x >= a.x) && (p.x <= b.x) && (p.z >= a.z) && (p.z <= b.z));
25 34
     }
26 35
 
27
-    glm::vec3 getVertexP(glm::vec3 normal) {
28
-        glm::vec3 p = a;
29
-        if (normal.x >= 0.0f)
30
-            p.x = b.x;
31
-        if (normal.y >= 0.0f)
32
-            p.y = b.y;
33
-        if (normal.z >= 0.0f)
34
-            p.z = b.z;
35
-        return p;
36
+    glm::vec3 getCorner(int i) {
37
+        assert((i >= 0) && (i < 8));
38
+        return corner[i];
36 39
     }
37 40
 
38 41
   private:
39 42
     glm::vec3 a, b;
43
+    glm::vec3 corner[8];
40 44
 };
41 45
 
42 46
 // --------------------------------------

+ 56
- 77
src/Camera.cpp View File

@@ -28,32 +28,19 @@
28 28
 #define FBR 6
29 29
 #define FTR 7
30 30
 
31
-struct Plane {
32
-    glm::vec3 normal, pos;
33
-    float d;
34
-
35
-    Plane(glm::vec3 n = glm::vec3(0.0f, 0.0f, 0.0f),
36
-          glm::vec3 p = glm::vec3(0.0f, 0.0f, 0.0f)) {
37
-        set(n, p);
38
-    }
39
-
40
-    void set(glm::vec3 a, glm::vec3 b, glm::vec3 c) {
41
-        glm::vec3 aux1 = a - b;
42
-        glm::vec3 aux2 = c - b;
43
-        normal = glm::normalize(glm::cross(aux2, aux1));
44
-        pos = b;
45
-        d = -glm::dot(normal, pos);
31
+class Plane {
32
+  public:
33
+    Plane() : normal(glm::vec3(0.0f, 0.0f, 0.0f)), d(0.0f) { }
34
+    void set(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3) {
35
+        normal = glm::normalize(glm::cross(v3 - v2, v1 - v2));
36
+        d = -glm::dot(normal, v2);
46 37
     }
47
-
48
-    void set(glm::vec3 n, glm::vec3 p) {
49
-        normal = n;
50
-        pos = p;
51
-        d = -glm::dot(normal, pos);
52
-    }
53
-
54 38
     float distance(glm::vec3 p) {
55 39
         return d + glm::dot(normal, p);
56 40
     }
41
+  private:
42
+    glm::vec3 normal;
43
+    float d;
57 44
 };
58 45
 
59 46
 // ----------------------------------------------------------------------------
@@ -76,12 +63,12 @@ bool Camera::updateViewFrustum = true;
76 63
 static Plane planes[6];
77 64
 
78 65
 static glm::vec3 frustumColors[6] = {
79
-    glm::vec3(1.0f, 0.0f, 0.0f),
80
-    glm::vec3(0.0f, 1.0f, 0.0f),
81
-    glm::vec3(0.0f, 0.0f, 1.0f),
82
-    glm::vec3(1.0f, 1.0f, 0.0f),
83
-    glm::vec3(0.0f, 1.0f, 1.0f),
84
-    glm::vec3(1.0f, 0.0f, 1.0f)
66
+    glm::vec3(1.0f, 0.0f, 0.0f), // NEAR, red
67
+    glm::vec3(0.0f, 1.0f, 0.0f), // FAR, green
68
+    glm::vec3(0.0f, 0.0f, 1.0f), // TOP, blue
69
+    glm::vec3(1.0f, 1.0f, 0.0f), // BOTTOM, yellow
70
+    glm::vec3(0.0f, 1.0f, 1.0f), // LEFT, light-blue
71
+    glm::vec3(1.0f, 0.0f, 1.0f)  // RIGHT, pink
85 72
 };
86 73
 static glm::vec3 frustumVertices[8];
87 74
 
@@ -165,6 +152,7 @@ bool Camera::update() {
165 152
         return false;
166 153
 
167 154
     if (lastSize != size) {
155
+        //! \fixme TODO instead of mirroring the axes in the shader, scale here
168 156
         projection = glm::perspective(fov, size.x / size.y, nearDist, farDist);
169 157
         lastSize = size;
170 158
     }
@@ -187,55 +175,31 @@ bool Camera::update() {
187 175
     if (!updateViewFrustum)
188 176
         return false;
189 177
 
190
-    dir = glm::normalize(dir);
191
-    right = glm::normalize(right);
192
-    up = glm::normalize(up);
193
-
194
-    static float tang = glm::tan(glm::radians(fov * 0.5f));
195
-    static float nh = nearDist * tang;
196
-    float nw = nh * (size.x / size.y);
197
-    static float fh = farDist * tang;
198
-    float fw = fh * (size.x / size.y);
199
-
200
-    glm::vec3 nearCenter = pos + dir * nearDist;
201
-    glm::vec3 farCenter = pos + dir * farDist;
202
-
203
-    frustumVertices[NTL] = nearCenter + up * nh - right * nw;
204
-    frustumVertices[NTR] = nearCenter + up * nh + right * nw;
205
-    frustumVertices[NBL] = nearCenter - up * nh - right * nw;
206
-    frustumVertices[NBR] = nearCenter - up * nh + right * nw;
207
-    frustumVertices[FTL] = farCenter + up * fh - right * fw;
208
-    frustumVertices[FTR] = farCenter + up * fh + right * fw;
209
-    frustumVertices[FBL] = farCenter - up * fh - right * fw;
210
-    frustumVertices[FBR] = farCenter - up * fh + right * fw;
211
-
212
-#if 1
178
+    glm::mat4 combo = projection * view;
179
+
180
+    // Calculate frustum corners to display them
181
+    glm::mat4 inverse = glm::inverse(combo);
182
+    frustumVertices[NTL] = glm::vec3( 1.0f,  1.0f, 0.0f);
183
+    frustumVertices[NTR] = glm::vec3(-1.0f,  1.0f, 0.0f);
184
+    frustumVertices[NBL] = glm::vec3( 1.0f, -1.0f, 0.0f);
185
+    frustumVertices[NBR] = glm::vec3(-1.0f, -1.0f, 0.0f);
186
+    frustumVertices[FTL] = glm::vec3( 1.0f,  1.0f, 1.0f);
187
+    frustumVertices[FTR] = glm::vec3(-1.0f,  1.0f, 1.0f);
188
+    frustumVertices[FBL] = glm::vec3( 1.0f, -1.0f, 1.0f);
189
+    frustumVertices[FBR] = glm::vec3(-1.0f, -1.0f, 1.0f);
190
+    for (int i = 0; i < 8; i++) {
191
+        glm::vec4 t = inverse * glm::vec4(frustumVertices[i], 1.0f);
192
+        frustumVertices[i] = glm::vec3(t) / t.w;
193
+        frustumVertices[i].y *= -1.0f;
194
+    }
195
+
196
+    // Set planes used for frustum culling
213 197
     planes[TOP].set(frustumVertices[NTR], frustumVertices[NTL], frustumVertices[FTL]);
214 198
     planes[BOTTOM].set(frustumVertices[NBL], frustumVertices[NBR], frustumVertices[FBR]);
215 199
     planes[LEFT].set(frustumVertices[NTL], frustumVertices[NBL], frustumVertices[FBL]);
216 200
     planes[RIGHT].set(frustumVertices[NBR], frustumVertices[NTR], frustumVertices[FBR]);
217 201
     planes[NEAR].set(frustumVertices[NTL], frustumVertices[NTR], frustumVertices[NBR]);
218 202
     planes[FAR].set(frustumVertices[FTR], frustumVertices[FTL], frustumVertices[FBL]);
219
-#else
220
-    planes[NEAR].set(-dir, nearCenter);
221
-    planes[FAR].set(dir, farCenter);
222
-
223
-    glm::vec3 aux = glm::normalize((nearCenter + up * nh) - pos);
224
-    glm::vec3 normal = glm::cross(aux, right);
225
-    planes[TOP].set(normal, nearCenter + up * nh);
226
-
227
-    aux = glm::normalize((nearCenter - up * nh) - pos);
228
-    normal = glm::cross(right, aux);
229
-    planes[BOTTOM].set(normal, nearCenter - up * nh);
230
-
231
-    aux = glm::normalize((nearCenter - right * nw) - pos);
232
-    normal = glm::cross(aux, up);
233
-    planes[LEFT].set(normal, nearCenter - right * nw);
234
-
235
-    aux = glm::normalize((nearCenter + right * nw) - pos);
236
-    normal = glm::cross(up, aux);
237
-    planes[RIGHT].set(normal, nearCenter + right * nw);
238
-#endif
239 203
 
240 204
     lastPos = pos;
241 205
     lastRot = rot;
@@ -244,9 +208,18 @@ bool Camera::update() {
244 208
 
245 209
 bool Camera::boxInFrustum(BoundingBox b) {
246 210
     for (int i = 0; i < 6; i++) {
247
-        if (planes[i].distance(b.getVertexP(planes[i].normal)) < 0)
211
+        int out = 0, in = 0;
212
+        for (int c = 0; (c < 8) && ((in == 0) || (out == 0)); c++) {
213
+            if (planes[i].distance(b.getCorner(c)) < 0)
214
+                out++;
215
+            else
216
+                in++;
217
+        }
218
+
219
+        if (in == 0)
248 220
             return false;
249 221
     }
222
+
250 223
     return true;
251 224
 }
252 225
 
@@ -255,31 +228,37 @@ void Camera::displayFrustum(glm::mat4 MVP) {
255 228
     std::vector<glm::vec3> cols;
256 229
     std::vector<unsigned short> inds;
257 230
 
231
+    // Near
258 232
     verts.push_back(frustumVertices[NTL]);
259 233
     verts.push_back(frustumVertices[NTR]);
260 234
     verts.push_back(frustumVertices[NBR]);
261 235
     verts.push_back(frustumVertices[NBL]);
262 236
 
237
+    // Far
263 238
     verts.push_back(frustumVertices[FTR]);
264 239
     verts.push_back(frustumVertices[FTL]);
265 240
     verts.push_back(frustumVertices[FBL]);
266 241
     verts.push_back(frustumVertices[FBR]);
267 242
 
268
-    verts.push_back(frustumVertices[NBL]);
269
-    verts.push_back(frustumVertices[NBR]);
270
-    verts.push_back(frustumVertices[FBR]);
271
-    verts.push_back(frustumVertices[FBL]);
272
-
243
+    // Top
273 244
     verts.push_back(frustumVertices[NTR]);
274 245
     verts.push_back(frustumVertices[NTL]);
275 246
     verts.push_back(frustumVertices[FTL]);
276 247
     verts.push_back(frustumVertices[FTR]);
277 248
 
249
+    // Bottom
250
+    verts.push_back(frustumVertices[NBL]);
251
+    verts.push_back(frustumVertices[NBR]);
252
+    verts.push_back(frustumVertices[FBR]);
253
+    verts.push_back(frustumVertices[FBL]);
254
+
255
+    // Left
278 256
     verts.push_back(frustumVertices[NTL]);
279 257
     verts.push_back(frustumVertices[NBL]);
280 258
     verts.push_back(frustumVertices[FBL]);
281 259
     verts.push_back(frustumVertices[FTL]);
282 260
 
261
+    // Right
283 262
     verts.push_back(frustumVertices[NBR]);
284 263
     verts.push_back(frustumVertices[NTR]);
285 264
     verts.push_back(frustumVertices[FTR]);

Loading…
Cancel
Save