mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 07:19:14 +02:00
Correctly compute conical frustum for irregular ones
This commit is contained in:
parent
67c119cd2e
commit
b4ea32bbb6
1 changed files with 11 additions and 25 deletions
|
@ -17,38 +17,24 @@ void ConicalViewFrustum::set(const ViewFrustum& viewFrustum) {
|
||||||
// The ConicalViewFrustum has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part.
|
// The ConicalViewFrustum has two parts: a central sphere (same as ViewFrustum) and a circular cone that bounds the frustum part.
|
||||||
// Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum.
|
// Why? Because approximate intersection tests are much faster to compute for a cone than for a frustum.
|
||||||
_position = viewFrustum.getPosition();
|
_position = viewFrustum.getPosition();
|
||||||
_direction = viewFrustum.getDirection();
|
|
||||||
_radius = viewFrustum.getCenterRadius();
|
_radius = viewFrustum.getCenterRadius();
|
||||||
_farClip = viewFrustum.getFarClip();
|
_farClip = viewFrustum.getFarClip();
|
||||||
|
|
||||||
// Considering the rectangle intersection the frustum and the perpendicular plane 1 unit
|
auto topLeft = viewFrustum.getNearTopLeft() - _position;
|
||||||
// away from the frustum's origin
|
auto topRight = viewFrustum.getNearTopRight() - _position;
|
||||||
// We are looking for the angle between the ray that goes through the center of the rectangle
|
auto bottomLeft = viewFrustum.getNearBottomLeft() - _position;
|
||||||
// and the ray that goes through one of the corners of the rectangle
|
auto bottomRight = viewFrustum.getNearBottomRight() - _position;
|
||||||
// (Both rays coming from the frustum's origin)
|
auto centerAxis = 0.25f * (topLeft + topRight + bottomLeft + bottomRight); // Take the average
|
||||||
// This angle will let us construct a cone in which the frustum is inscribed
|
|
||||||
// Let's define:
|
|
||||||
// A = aspect ratio = width / height
|
|
||||||
// fov = vertical field of view
|
|
||||||
// y = half height of the rectangle
|
|
||||||
// x = half width of the rectangle
|
|
||||||
// r = half diagonal of the rectangle
|
|
||||||
// then, we have:
|
|
||||||
// y / 1 = tan(fov / 2)
|
|
||||||
// x = A * y = A * tan(fov / 2)
|
|
||||||
// r^2 = x^2 + y^2 = (A^2 + 1) * tan^2(fov / 2)
|
|
||||||
// r / 1 = tan(angle) = sqrt((A^2 + 1) * tan^2(fov / 2))
|
|
||||||
// angle = atan(sqrt((A^2 + 1) * tan^2(fov / 2)))
|
|
||||||
float A = viewFrustum.getAspectRatio();
|
|
||||||
float t = tanf(0.5f * viewFrustum.getFieldOfView());
|
|
||||||
|
|
||||||
auto tan2Angle = (A * A + 1.0f) * (t * t);
|
_direction = glm::normalize(centerAxis);
|
||||||
_angle = atanf(sqrt(tan2Angle));
|
_angle = std::max(std::max(angleBetween(_direction, topLeft),
|
||||||
|
angleBetween(_direction, topRight)),
|
||||||
calculate();
|
std::max(angleBetween(_direction, bottomLeft),
|
||||||
|
angleBetween(_direction, bottomRight)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConicalViewFrustum::calculate() {
|
void ConicalViewFrustum::calculate() {
|
||||||
|
// Pre-compute cos and sin for faster checks
|
||||||
_cosAngle = cosf(_angle);
|
_cosAngle = cosf(_angle);
|
||||||
_sinAngle = sqrtf(1.0f - _cosAngle * _cosAngle);
|
_sinAngle = sqrtf(1.0f - _cosAngle * _cosAngle);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue