Unravel Engine C++ Reference
Loading...
Searching...
No Matches
frustum.cpp
Go to the documentation of this file.
1#include "frustum.h"
2
3namespace math
4{
5namespace
6{
7
8auto get_transformed_bbox_vertices(const bbox& AABB, const transform& t) -> std::array<vec3, 8>
9{
10 std::array<vec3, 8> vertices;
11
12 vec3 min = AABB.min;
13 vec3 max = AABB.max;
14
15 vertices[0] = t.transform_coord(vec3(min.x, min.y, min.z));
16 vertices[1] = t.transform_coord(vec3(max.x, min.y, min.z));
17 vertices[2] = t.transform_coord(vec3(min.x, max.y, min.z));
18 vertices[3] = t.transform_coord(vec3(max.x, max.y, min.z));
19 vertices[4] = t.transform_coord(vec3(min.x, min.y, max.z));
20 vertices[5] = t.transform_coord(vec3(max.x, min.y, max.z));
21 vertices[6] = t.transform_coord(vec3(min.x, max.y, max.z));
22 vertices[7] = t.transform_coord(vec3(max.x, max.y, max.z));
23
24 return vertices;
25}
26
27} // namespace
28
30{
31 // Initialize values
32 planes.fill(vec4(0.0f, 0.0f, 0.0f, 0.0f));
33 points.fill(vec3(0.0f, 0.0f, 0.0f));
34 position = vec3(0, 0, 0);
35}
36
37frustum::frustum(const transform& View, const transform& Proj, bool homogeneousDepth)
38{
39 update(View, Proj, homogeneousDepth);
40}
41
43{
44 // Compute planes
51
52 // Compute points
53 vec3 e = AABB.get_extents();
54 vec3 p = AABB.get_center();
55 points[volume_geometry_point::left_bottom_near] = vec3(p.x - e.x, p.y - e.y, p.z + e.z);
56 points[volume_geometry_point::left_bottom_far] = vec3(p.x - e.x, p.y - e.y, p.z + e.z);
57 points[volume_geometry_point::right_bottom_near] = vec3(p.x + e.x, p.y - e.y, p.z - e.z);
58 points[volume_geometry_point::right_bottom_far] = vec3(p.x + e.x, p.y - e.y, p.z + e.z);
59 points[volume_geometry_point::left_top_near] = vec3(p.x - e.x, p.y + e.y, p.z + e.z);
60 points[volume_geometry_point::left_top_far] = vec3(p.x - e.x, p.y + e.y, p.z + e.z);
61 points[volume_geometry_point::right_top_near] = vec3(p.x + e.x, p.y + e.y, p.z - e.z);
62 points[volume_geometry_point::right_top_far] = vec3(p.x + e.x, p.y + e.y, p.z + e.z);
63 position = p;
64}
65
66void frustum::update(const transform& view, const transform& proj, bool homogeneousDepth)
67{
68 // Build a combined view & projection matrix
69 const transform m = proj * view;
70
71 // Extract frustum planes from matrix
72 // Planes are in format: normal(xyz), offset(w)
73 // Expects left handed orientation and row_major matrix layout
74 planes[volume_plane::right].data.x = m[0][3] + m[0][0];
75 planes[volume_plane::right].data.y = m[1][3] + m[1][0];
76 planes[volume_plane::right].data.z = m[2][3] + m[2][0];
77 planes[volume_plane::right].data.w = m[3][3] + m[3][0];
78
79 planes[volume_plane::left].data.x = m[0][3] - m[0][0];
80 planes[volume_plane::left].data.y = m[1][3] - m[1][0];
81 planes[volume_plane::left].data.z = m[2][3] - m[2][0];
82 planes[volume_plane::left].data.w = m[3][3] - m[3][0];
83
84 planes[volume_plane::top].data.x = m[0][3] - m[0][1];
85 planes[volume_plane::top].data.y = m[1][3] - m[1][1];
86 planes[volume_plane::top].data.z = m[2][3] - m[2][1];
87 planes[volume_plane::top].data.w = m[3][3] - m[3][1];
88
89 planes[volume_plane::bottom].data.x = m[0][3] + m[0][1];
90 planes[volume_plane::bottom].data.y = m[1][3] + m[1][1];
91 planes[volume_plane::bottom].data.z = m[2][3] + m[2][1];
92 planes[volume_plane::bottom].data.w = m[3][3] + m[3][1];
93
94 planes[volume_plane::far_plane].data.x = m[0][3] - m[0][2];
95 planes[volume_plane::far_plane].data.y = m[1][3] - m[1][2];
96 planes[volume_plane::far_plane].data.z = m[2][3] - m[2][2];
97 planes[volume_plane::far_plane].data.w = m[3][3] - m[3][2];
98
99 if(homogeneousDepth)
100 {
101 planes[volume_plane::near_plane].data.x = m[0][3] + m[0][2];
102 planes[volume_plane::near_plane].data.y = m[1][3] + m[1][2];
103 planes[volume_plane::near_plane].data.z = m[2][3] + m[2][2];
104 planes[volume_plane::near_plane].data.w = m[3][3] + m[3][2];
105 }
106 else
107 {
108 planes[volume_plane::near_plane].data.x = m[0][2];
109 planes[volume_plane::near_plane].data.y = m[1][2];
110 planes[volume_plane::near_plane].data.z = m[2][2];
111 planes[volume_plane::near_plane].data.w = m[3][2];
112 }
113
114 for(auto& plane : planes)
115 {
116 plane.data *= -1.0f;
117 }
118 // Normalize and compute additional information.
120
121 // Compute the originating position of the frustum.
122 position = vec3(view[0][0], view[1][0], view[2][0]) * -view[3][0];
123 position += vec3(view[0][1], view[1][1], view[2][1]) * -view[3][1];
124 position += vec3(view[0][2], view[1][2], view[2][2]) * -view[3][2];
125
126 // Extract the camera forward vector (assuming left-handed and row-major)
127 vec3 forward = -vec3(view[0][2], view[1][2], view[2][2]);
128
129 // Compute near distance
132 dot(vec3(planes[volume_plane::near_plane].data), forward);
133
134 // Compute far distance
137 dot(vec3(planes[volume_plane::far_plane].data), forward);
138}
139
140void frustum::set_planes(const std::array<plane, 6>& new_planes)
141{
142 planes = new_planes;
143 // Copy and normalize the planes
144 for(auto& plane : planes)
145 {
147 }
148
149 // Recompute the frustum corner points.
151}
152
154{
155 // Compute the 8 corner points
156 for(std::size_t i = 0; i < 8; ++i)
157 {
158 const plane& p0 =
162
163 // Compute the point at which the three planes intersect
164 vec3 n0(p0.data);
165 vec3 n1(p1.data);
166 vec3 n2(p2.data);
167
168 vec3 n1_n2 = glm::cross(n1, n2);
169 vec3 n2_n0 = glm::cross(n2, n0);
170 vec3 n0_n1 = glm::cross(n0, n1);
171
172 float cosTheta = glm::dot(n0, n1_n2);
173 float secTheta = 1.0f / cosTheta;
174
175 n1_n2 = n1_n2 * p0.data.w;
176 n2_n0 = n2_n0 * p1.data.w;
177 n0_n1 = n0_n1 * p2.data.w;
178
179 points[i] = -(n1_n2 + n2_n0 + n0_n1) * secTheta;
180
181 } // Next Corner
182}
183
184auto frustum::classify_vertices(const vec3* vertices, size_t count) const -> volume_query
185{
186 // Initialize the result as inside
188
189 // Loop through all the planes
190 for(const auto& plane : planes)
191 {
192 bool allOutside = true;
193 bool anyOutside = false;
194
195 // Check each vertex
196 for(size_t i = 0; i < count; ++i)
197 {
198 float distance = plane::dot_coord(plane, vertices[i]);
199
200 if(distance > 0.0f)
201 {
202 anyOutside = true;
203 }
204 else
205 {
206 allOutside = false;
207 }
208 }
209
210 // If all vertices are outside one plane, the OBB is outside the frustum
211 if(allOutside)
212 {
214 }
215
216 // If any vertex is outside one plane, the OBB intersects the frustum
217 if(anyOutside)
218 {
220 }
221 }
222
223 // Return the classification result
224 return Result;
225}
226
227auto frustum::classify_aabb(const bbox& AABB) const -> volume_query
228{
230 vec3 nearPoint, farPoint;
231
232 for(const auto& plane : planes)
233 {
234 nearPoint.x = plane.data.x > 0.0f ? AABB.min.x : AABB.max.x;
235 farPoint.x = plane.data.x > 0.0f ? AABB.max.x : AABB.min.x;
236
237 nearPoint.y = plane.data.y > 0.0f ? AABB.min.y : AABB.max.y;
238 farPoint.y = plane.data.y > 0.0f ? AABB.max.y : AABB.min.y;
239
240 nearPoint.z = plane.data.z > 0.0f ? AABB.min.z : AABB.max.z;
241 farPoint.z = plane.data.z > 0.0f ? AABB.max.z : AABB.min.z;
242
243 if(plane::dot_coord(plane, nearPoint) > 0.0f)
244 {
246 }
247
248 if(plane::dot_coord(plane, farPoint) > 0.0f)
249 {
251 }
252 }
253
254 return result;
255}
256
257auto frustum::classify_obb(const bbox& AABB, const transform& t) const -> volume_query
258{
259 auto vertices = get_transformed_bbox_vertices(AABB, t);
260 return classify_vertices(vertices.data(), vertices.size());
261}
262
263auto frustum::classify_aabb(const bbox& AABB, unsigned int& frustumBits, int& lastOutside) const -> volume_query
264{
266 vec3 nearPoint, farPoint;
267
268 if(lastOutside >= 0 && ((frustumBits >> lastOutside) & 0x1) == 0x0)
269 {
270 const plane& plane = planes[lastOutside];
271
272 nearPoint.x = plane.data.x > 0.0f ? AABB.min.x : AABB.max.x;
273 farPoint.x = plane.data.x > 0.0f ? AABB.max.x : AABB.min.x;
274
275 nearPoint.y = plane.data.y > 0.0f ? AABB.min.y : AABB.max.y;
276 farPoint.y = plane.data.y > 0.0f ? AABB.max.y : AABB.min.y;
277
278 nearPoint.z = plane.data.z > 0.0f ? AABB.min.z : AABB.max.z;
279 farPoint.z = plane.data.z > 0.0f ? AABB.max.z : AABB.min.z;
280
281 if(plane::dot_coord(plane, nearPoint) > 0.0f)
282 {
284 }
285
286 if(plane::dot_coord(plane, farPoint) > 0.0f)
287 {
289 }
290 else
291 {
292 frustumBits |= (0x1 << lastOutside);
293 }
294 }
295
296 for(size_t i = 0; i < planes.size(); i++)
297 {
298 if(((frustumBits >> i) & 0x1) == 0x1)
299 continue;
300 if(lastOutside >= 0 && lastOutside == int(i))
301 continue;
302
303 const plane& plane = planes[i];
304
305 nearPoint.x = plane.data.x > 0.0f ? AABB.min.x : AABB.max.x;
306 farPoint.x = plane.data.x > 0.0f ? AABB.max.x : AABB.min.x;
307
308 nearPoint.y = plane.data.y > 0.0f ? AABB.min.y : AABB.max.y;
309 farPoint.y = plane.data.y > 0.0f ? AABB.max.y : AABB.min.y;
310
311 nearPoint.z = plane.data.z > 0.0f ? AABB.min.z : AABB.max.z;
312 farPoint.z = plane.data.z > 0.0f ? AABB.max.z : AABB.min.z;
313
314 if(plane::dot_coord(plane, nearPoint) > 0.0f)
315 {
316 lastOutside = int(i);
318 }
319
320 if(plane::dot_coord(plane, farPoint) > 0.0f)
321 {
323 }
324 else
325 {
326 frustumBits |= (0x1 << i);
327 }
328 }
329
330 lastOutside = -1;
331 return result;
332}
333
334auto frustum::test_aabb(const bbox& AABB) const -> bool
335{
336 // Loop through all the planes
337 vec3 nearPoint;
338 for(const auto& plane : planes)
339 {
340 nearPoint.x = plane.data.x > 0.0f ? AABB.min.x : AABB.max.x;
341 nearPoint.y = plane.data.y > 0.0f ? AABB.min.y : AABB.max.y;
342 nearPoint.z = plane.data.z > 0.0f ? AABB.min.z : AABB.max.z;
343
344 // If near extreme point is outside, then the AABB is totally outside the
345 // frustum
346 if(plane::dot_coord(plane, nearPoint) > 0.0f)
347 {
348 return false;
349 }
350
351 } // Next plane
352
353 // Intersecting / inside
354 return true;
355}
356
357auto frustum::test_vertices(const vec3* vertices, size_t vert_count) const -> bool
358{
359 for(const auto& plane : planes)
360 {
361 bool allOutside = true;
362
363 for(size_t i = 0; i < vert_count; ++i)
364 {
365 if(plane::dot_coord(plane, vertices[i]) <= 0.0f)
366 {
367 // If any vertex is inside or on the plane, we are not all outside
368 allOutside = false;
369 break;
370 }
371 }
372
373 // If all vertices are outside this plane, the vertices are outside the frustum
374 if(allOutside)
375 {
376 return false;
377 }
378 }
379
380 // If none of the planes had all vertices outside, the vertices are inside or intersecting
381 return true;
382}
383
384auto frustum::test_obb(const bbox& AABB, const transform& t) const -> bool
385{
386 auto vertices = get_transformed_bbox_vertices(AABB, t);
387 return test_vertices(vertices.data(), vertices.size());
388}
389
391{
393
394 // Test frustum planes
395 for(const auto& plane : planes)
396 {
397 float fDot = plane::dot_coord(plane, sphere.position);
398
399 // Sphere entirely in front of plane
400 if(fDot >= sphere.radius)
401 {
403 }
404
405 // Sphere spans plane
406 if(fDot >= -sphere.radius)
407 {
409 }
410
411 } // Next plane
412
413 // Return the result
414 return Result;
415}
416
417auto frustum::test_sphere(const bsphere& sphere) const -> bool
418{
419 // Test frustum planes
420 for(const auto& plane : planes)
421 {
422 float fDot = plane::dot_coord(plane, sphere.position);
423
424 // Sphere entirely in front of plane
425 if(fDot >= sphere.radius)
426 {
427 return false;
428 }
429
430 } // Next plane
431
432 // Intersects
433 return true;
434}
435
436auto frustum::test_sphere(const bsphere& sphere, const transform& t) const -> bool
437{
438 return test_sphere(bsphere(t.transform_coord(sphere.position), sphere.radius));
439}
440
441auto frustum::swept_sphere_intersect_plane(float& t0,
442 float& t1,
443 const plane& plane,
444 const bsphere& sphere,
445 const vec3& vecSweepDirection) -> bool
446{
447 float b_dot_n = plane::dot_coord(plane, sphere.position);
448 float d_dot_n = plane::dot_normal(plane, vecSweepDirection);
449
450 if(d_dot_n == 0.0f)
451 {
452 if(b_dot_n <= sphere.radius)
453 {
454 // Effectively infinity
455 t0 = 0.0f;
456 t1 = std::numeric_limits<float>::max();
457 return true;
458
459 } // End if infinity
460
461 return false;
462
463 } // End if runs parallel to plane
464
465 // Compute the two possible intersections
466 float tmp0 = (sphere.radius - b_dot_n) / d_dot_n;
467 float tmp1 = (-sphere.radius - b_dot_n) / d_dot_n;
468 t0 = glm::min<float>(tmp0, tmp1);
469 t1 = glm::max<float>(tmp0, tmp1);
470 return true;
471
472 // End if intersection
473}
474
475auto frustum::test_swept_sphere(const bsphere& sphere, const vec3& vecSweepDirection, float max_distance) const -> bool
476{
477 if(test_sphere(sphere))
478 {
479 return true;
480 }
481
482 // Robust swept-sphere vs convex frustum test using interval intersection.
483 // Plane convention in this engine:
484 // - plane::dot_coord(plane, point) > 0 means point is outside/in-front of the plane
485 // - inside is <= 0
486 //
487 // A sphere of radius r intersects the frustum iff for every plane:
488 // dot_coord(plane, center(t)) <= r
489 // where center(t) = center0 + dir * t.
490 //
491 // NOTE: max_distance is only meaningful if vecSweepDirection is normalized.
492 constexpr float sweep_parallel_epsilon = 1e-6f;
493 const float radius_tolerance = sphere.radius * 1.1f;
494
495 float t_enter = 0.0f;
496 float t_exit = (max_distance < 0.0f) ? std::numeric_limits<float>::infinity() : max_distance;
497
498 for(const auto& plane : planes)
499 {
500 const float b_dot_n = plane::dot_coord(plane, sphere.position);
501 const float d_dot_n = plane::dot_normal(plane, vecSweepDirection);
502
503 // Constraint: b_dot_n + d_dot_n * t <= radius_tolerance
504 if(glm::abs(d_dot_n) < sweep_parallel_epsilon)
505 {
506 // Moving parallel to this plane: either always satisfies, or never satisfies.
507 if(b_dot_n > radius_tolerance)
508 {
509 return false;
510 }
511 continue;
512 }
513
514 const float t_bound = (radius_tolerance - b_dot_n) / d_dot_n;
515 if(d_dot_n > 0.0f)
516 {
517 // Increasing distance to plane as t increases -> upper bound on t.
518 t_exit = glm::min(t_exit, t_bound);
519 }
520 else
521 {
522 // Decreasing distance to plane as t increases -> lower bound on t.
523 t_enter = glm::max(t_enter, t_bound);
524 }
525
526 if(t_enter > t_exit)
527 {
528 return false;
529 }
530 }
531
532 return t_exit >= 0.0f;
533}
534
535auto frustum::test_swept_aabb(const bbox& box, const vec3& vecSweepDirection, float max_distance) const -> bool
536{
537 // Early out: if box already intersects frustum
538 if(test_aabb(box))
539 {
540 return true;
541 }
542
543 // Robust swept-AABB vs convex frustum test using interval intersection.
544 // For each plane, we find the "support vertex" (corner furthest in direction of plane normal)
545 // and compute when that vertex enters/exits the plane's half-space during the sweep.
546 //
547 // NOTE: max_distance is only meaningful if vecSweepDirection is normalized.
548 constexpr float sweep_parallel_epsilon = 1e-6f;
549
550 float t_enter = 0.0f;
551 float t_exit = (max_distance < 0.0f) ? std::numeric_limits<float>::infinity() : max_distance;
552
553 for(const auto& plane : planes)
554 {
555 // Get plane normal
556 const vec3 normal(plane.data.x, plane.data.y, plane.data.z);
557
558 // Find the NEAR corner: corner of AABB closest to the plane
559 // This is the critical corner - if it's inside, the whole box can be inside
560 // Use same logic as classify_aabb (line 234)
561 vec3 near_corner(
562 (normal.x >= 0.0f) ? box.min.x : box.max.x,
563 (normal.y >= 0.0f) ? box.min.y : box.max.y,
564 (normal.z >= 0.0f) ? box.min.z : box.max.z
565 );
566
567 const float b_dot_n = plane::dot_coord(plane, near_corner);
568 const float d_dot_n = plane::dot_normal(plane, vecSweepDirection);
569
570 // Constraint: b_dot_n + d_dot_n * t <= 0 (near corner must be inside plane)
571 if(glm::abs(d_dot_n) < sweep_parallel_epsilon)
572 {
573 // Moving parallel to this plane: either always satisfies, or never satisfies.
574 if(b_dot_n > 0.0f)
575 {
576 return false; // Near corner outside, whole box never enters
577 }
578 continue;
579 }
580
581 const float t_bound = -b_dot_n / d_dot_n;
582 if(d_dot_n > 0.0f)
583 {
584 // Near corner moving away from inside → upper bound on t.
585 t_exit = glm::min(t_exit, t_bound);
586 }
587 else
588 {
589 // Near corner moving toward inside → lower bound on t.
590 t_enter = glm::max(t_enter, t_bound);
591 }
592
593 if(t_enter > t_exit)
594 {
595 return false; // No valid interval
596 }
597 }
598
599 return t_exit >= 0.0f;
600}
601
602auto frustum::test_point(const vec3& vecPoint) const -> bool
603{
604 return test_sphere(bsphere(vecPoint, 0.0f));
605}
606
607auto frustum::test_line(const vec3& v1, const vec3& v2) const -> bool
608{
609 int nCode1 = 0, nCode2 = 0;
610 float fDist1, fDist2, t;
611 int nSide1, nSide2;
612 vec3 vDir, vIntersect;
613 unsigned int i;
614
615 // Test each plane
616 for(i = 0; i < 6; ++i)
617 {
618 // Classify each point of the line against the plane.
619 fDist1 = plane::dot_coord(planes[i], v1);
620 fDist2 = plane::dot_coord(planes[i], v2);
621 nSide1 = (fDist1 >= 0) ? 1 : 0;
622 nSide2 = (fDist2 >= 0) ? 1 : 0;
623
624 // Accumulate the classification info to determine
625 // if the edge was spanning any of the planes.
626 nCode1 |= (nSide1 << i);
627 nCode2 |= (nSide2 << i);
628
629 // If the line is completely in front of any plane
630 // then it cannot possibly be intersecting.
631 if(nSide1 == 1 && nSide2 == 1)
632 {
633 return false;
634 }
635
636 // The line is potentially spanning?
637 if((nSide1 ^ nSide2) != 0)
638 {
639 // Compute the point at which the line intersects this plane.
640 vDir = v2 - v1;
641 t = -plane::dot_coord(planes[i], v1) / plane::dot_normal(planes[i], vDir);
642
643 // Truly spanning?
644 if((t >= 0.0f) && (t <= 1.0f))
645 {
646 vIntersect = v1 + (vDir * t);
647 if(test_sphere(bsphere(vIntersect, 0.01f)))
648 {
649 return true;
650 }
651
652 } // End if spanning
653
654 } // End if different sides
655
656 } // Next plane
657
658 // Intersecting?
659 return (nCode1 == 0) || (nCode2 == 0);
660}
661
663{
664 unsigned int nInFrontCount = 0;
665 unsigned int nBehindCount = 0;
666
667 // Test frustum points
668 for(unsigned int i = 0; i < 8; ++i)
669 {
670 float fDot = plane::dot_coord(plane, points[i]);
671 if(fDot > 0.0f)
672 {
673 nInFrontCount++;
674 }
675 else if(fDot < 0.0f)
676 {
677 nBehindCount++;
678 }
679
680 } // Next plane
681
682 // frustum entirely in front of plane
683 if(nInFrontCount == 8)
684 {
686 }
687
688 // frustum entire behind plane
689 if(nBehindCount == 8)
690 {
692 }
693
694 // Return intersection (spanning the plane)
696}
697
698auto frustum::test_frustum(const frustum& f) const -> bool
699{
700 // clang-format off
701 // A -> B
702 bool bIntersect1 =
703 test_line(f.points[volume_geometry_point::left_bottom_far],
705 test_line(f.points[volume_geometry_point::left_bottom_near],
709 test_line(f.points[volume_geometry_point::right_bottom_far],
711 test_line(f.points[volume_geometry_point::right_bottom_far],
715 test_line(f.points[volume_geometry_point::left_bottom_far],
717 test_line(f.points[volume_geometry_point::left_bottom_near],
719 test_line(f.points[volume_geometry_point::left_top_near],
721 test_line(f.points[volume_geometry_point::left_top_far],
723 test_line(f.points[volume_geometry_point::right_top_far],
725 test_line(f.points[volume_geometry_point::right_top_near],
727 // clang-format on
728
729 // Early out
730 if(bIntersect1)
731 {
732 return true;
733 }
734
735 // clang-format off
736 // B -> A
737 bool bIntersect2 =
738 f.test_line(points[volume_geometry_point::left_bottom_far],
740 f.test_line(points[volume_geometry_point::left_bottom_near],
744 f.test_line(points[volume_geometry_point::right_bottom_far],
746 f.test_line(points[volume_geometry_point::right_bottom_far],
750 f.test_line(points[volume_geometry_point::left_bottom_far],
752 f.test_line(points[volume_geometry_point::left_bottom_near],
754 f.test_line(points[volume_geometry_point::left_top_near],
756 f.test_line(points[volume_geometry_point::left_top_far],
758 f.test_line(points[volume_geometry_point::right_top_far],
760 f.test_line(points[volume_geometry_point::right_top_near],
762 // clang-format on
763
764 // Return intersection result
765 return bIntersect2;
766}
767
768auto frustum::mul(const transform& mtx) -> frustum&
769{
770 auto mtxIT = transpose(inverse(mtx.get_matrix()));
771
772 // transform planes
773 for(auto& plane : planes)
774 {
776 }
777
778 // transform points
779 for(auto& point : points)
780 {
781 point = mtx.transform_coord(point);
782 }
783
784 // transform originating position.
785 position = mtx.transform_coord(position);
786
787 // Return reference to self.
788 return *this;
789}
790
791auto frustum::operator==(const frustum& frustum) const -> bool
792{
793 // Compare planes.
794 for(size_t i = 0; i < planes.size(); ++i)
795 {
796 const plane& p1 = planes[i];
797 const plane& p2 = frustum.planes[i];
798 if(!(glm::abs<float>(p1.data.x - p2.data.x) <= glm::epsilon<float>() &&
799 glm::abs<float>(p1.data.y - p2.data.y) <= glm::epsilon<float>() &&
800 glm::abs<float>(p1.data.z - p2.data.z) <= glm::epsilon<float>() &&
801 glm::abs<float>(p1.data.w - p2.data.w) <= glm::epsilon<float>()))
802 {
803 return false;
804 }
805
806 } // Next plane
807
808 // Match
809 return true;
810}
811} // namespace math
Provides storage for common representation of spherical bounding volume, and wraps up common function...
Definition bsphere.h:18
Storage for frustum planes / values and wraps up common functionality.
Definition frustum.h:18
auto test_swept_sphere(const bsphere &sphere, const vec3 &sweepDirection, float max_distance=-1.0f) const -> bool
Determine whether or not the specified sphere, swept along the provided direction vector,...
Definition frustum.cpp:475
auto classify_aabb(const bbox &bounds) const -> volume_query
Classifies an axis-aligned bounding box (AABB) with respect to the frustum.
Definition frustum.cpp:227
auto classify_sphere(const bsphere &sphere) const -> volume_query
Classifies a sphere with respect to the frustum.
Definition frustum.cpp:390
auto test_swept_aabb(const bbox &box, const vec3 &sweepDirection, float max_distance=-1.0f) const -> bool
Determine whether or not the specified axis-aligned bounding box, swept along the provided direction ...
Definition frustum.cpp:535
vec3 position
Definition frustum.h:242
void recompute_points()
Recomputes the frustum's corner points based on its planes.
Definition frustum.cpp:153
frustum()
Default constructor.
Definition frustum.cpp:29
auto test_aabb(const bbox &bounds) const -> bool
Tests if an axis-aligned bounding box (AABB) is inside or intersecting the frustum.
Definition frustum.cpp:334
auto test_point(const vec3 &point) const -> bool
Tests if a point is inside or intersecting the frustum.
Definition frustum.cpp:602
float far_distance_
Definition frustum.h:245
auto test_sphere(const bsphere &sphere) const -> bool
Tests if a sphere is inside or intersecting the frustum.
Definition frustum.cpp:417
auto mul(const transform &t) -> frustum &
Multiplies the frustum by a transform.
Definition frustum.cpp:768
void update(const transform &view, const transform &proj, bool _oglNDC)
Updates the frustum based on the specified view and projection matrices.
Definition frustum.cpp:66
std::array< plane, 6 > planes
< The 6 planes of the frustum.
Definition frustum.h:238
auto test_vertices(const vec3 *vertices, size_t count) const -> bool
Tests if vertices are inside or intersect the frustum.
Definition frustum.cpp:357
void set_planes(const std::array< plane, 6 > &new_planes)
Sets the frustum planes.
Definition frustum.cpp:140
auto classify_plane(const plane &plane) const -> volume_query
Classifies a plane with respect to the frustum.
Definition frustum.cpp:662
auto test_line(const vec3 &v1, const vec3 &v2) const -> bool
Tests if a line intersects the frustum.
Definition frustum.cpp:607
auto classify_vertices(const vec3 *vertices, size_t count) const -> volume_query
Classifies vertices with respect to the frustum.
Definition frustum.cpp:184
auto classify_obb(const bbox &bounds, const transform &t) const -> volume_query
Classifies an oriented bounding box (OBB) with respect to the frustum.
Definition frustum.cpp:257
auto test_frustum(const frustum &frustum) const -> bool
Tests if another frustum intersects this frustum.
Definition frustum.cpp:698
auto operator==(const frustum &f) const -> bool
Equality operator.
Definition frustum.cpp:791
auto test_obb(const bbox &bounds, const transform &t) const -> bool
Tests if an oriented bounding box (OBB) is inside or intersecting the frustum.
Definition frustum.cpp:384
std::array< vec3, 8 > points
The originating position of the frustum.
Definition frustum.h:240
float near_distance_
Definition frustum.h:244
General purpose transformation class designed to maintain each component of the transformation separa...
Definition transform.hpp:27
math::vec3 position
Definition defaults.cpp:52
math::vec3 normal
Definition defaults.cpp:53
uint16_t view
Definition bbox.cpp:5
auto inverse(transform_t< T, Q > const &t) noexcept -> transform_t< T, Q >
transform_t< float > transform
volume_query
Definition math_types.h:13
auto transpose(transform_t< T, Q > const &t) noexcept -> transform_t< T, Q >
uint32_t count
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
plane get_plane(volume_plane::e side) const
Retrieves the plane for the specified side of the bounding box.
Definition bbox.cpp:59
vec3 get_extents() const
Returns a vector containing the extents of the bounding box (the half-dimensions)
Definition bbox.cpp:951
vec3 get_center() const
Returns a vector containing the exact center point of the box.
Definition bbox.cpp:946
Storage for infinite plane.
Definition plane.h:21
static auto normalize(const plane &p) -> plane
Normalizes the plane.
Definition plane.cpp:37
static auto dot_normal(const plane &p, const vec3 &v) -> float
Computes the dot product of the plane normal and a vec3.
Definition plane.cpp:15
static auto dot_coord(const plane &p, const vec3 &v) -> float
Computes the dot product of the plane and a vec3 (considering the plane's distance).
Definition plane.cpp:10
static auto mul(const plane &p, const mat4 &m) -> plane
Transforms a plane by a 4x4 matrix.
Definition plane.cpp:32
vec4 data
The components of the plane.
Definition plane.h:260