mirror of
https://github.com/lubosz/overte.git
synced 2025-04-14 06:46:19 +02:00
add ViewFrustum::cubeInKeyhole()
This commit is contained in:
parent
706cf66240
commit
9409339230
4 changed files with 234 additions and 5 deletions
|
@ -198,6 +198,33 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
const float HALF_SQRT_THREE = 0.8660254f;
|
||||
|
||||
ViewFrustum::location ViewFrustum::cubeInKeyhole(const AACube& cube) const {
|
||||
// check against centeral sphere
|
||||
ViewFrustum::location sphereResult = INTERSECT;
|
||||
glm::vec3 cubeOffset = cube.calcCenter() - _position;
|
||||
float distance = glm::length(cubeOffset);
|
||||
if (distance > EPSILON) {
|
||||
glm::vec3 vertex = cube.getFarthestVertex(cubeOffset) - _position;
|
||||
if (glm::dot(vertex, cubeOffset) < _keyholeRadius * distance) {
|
||||
// the most outward cube vertex is inside central sphere
|
||||
return INSIDE;
|
||||
}
|
||||
if (!cube.touchesSphere(_position, _keyholeRadius)) {
|
||||
sphereResult = OUTSIDE;
|
||||
}
|
||||
} else if (_keyholeRadius > HALF_SQRT_THREE * cube.getScale()) {
|
||||
// the cube is in center of sphere and its bounding radius is inside
|
||||
return INSIDE;
|
||||
}
|
||||
|
||||
// check against frustum
|
||||
ViewFrustum::location frustumResult = cubeInFrustum(cube);
|
||||
|
||||
return (frustumResult == OUTSIDE) ? sphereResult : frustumResult;
|
||||
}
|
||||
|
||||
bool ViewFrustum::sphereTouchesKeyhole(const glm::vec3& center, float radius) const {
|
||||
// check positive touch against central sphere
|
||||
if (glm::length(center - _position) <= (radius + _keyholeRadius)) {
|
||||
|
|
|
@ -96,6 +96,9 @@ public:
|
|||
ViewFrustum::location cubeInFrustum(const AACube& cube) const;
|
||||
ViewFrustum::location boxInFrustum(const AABox& box) const;
|
||||
|
||||
ViewFrustum::location cubeInKeyhole(const AACube& cube) const;
|
||||
|
||||
// more efficient methods when only need boolean result
|
||||
bool sphereTouchesKeyhole(const glm::vec3& center, float radius) const;
|
||||
bool cubeTouchesKeyhole(const AACube& cube) const;
|
||||
bool boxTouchesKeyhole(const AABox& box) const;
|
||||
|
|
|
@ -198,7 +198,7 @@ void ViewFrustumTests::testSphereInFrustum() {
|
|||
glm::quat elevation, swing;
|
||||
glm::vec3 sphereCenter, localOffset;
|
||||
|
||||
float sphereRadius = 2.68f; // must be much smaller than sphereDistance
|
||||
float sphereRadius = 2.68f; // must be much smaller than sphereDistance for small angle approx below
|
||||
float sphereDistance = farClip;
|
||||
float sphereAngle = sphereRadius / sphereDistance; // sine of small angles approximation
|
||||
|
||||
|
@ -327,7 +327,7 @@ void ViewFrustumTests::testCubeInFrustum() {
|
|||
glm::quat elevation, swing;
|
||||
glm::vec3 cubeCenter, localOffset;
|
||||
|
||||
float cubeScale = 2.68f; // must be much smaller than cubeDistance
|
||||
float cubeScale = 2.68f; // must be much smaller than cubeDistance for small angle approx below
|
||||
glm::vec3 halfScaleOffset = 0.5f * glm::vec3(cubeScale);
|
||||
float cubeDistance = farClip;
|
||||
float cubeBoundingRadius = 0.5f * sqrtf(3.0f) * cubeScale;
|
||||
|
@ -473,7 +473,7 @@ void ViewFrustumTests::testBoxInFrustum() {
|
|||
glm::quat elevation, swing;
|
||||
glm::vec3 boxCenter, localOffset;
|
||||
|
||||
glm::vec3 boxScale = glm::vec3(2.68f, 1.78f, 0.431f); // sides must be much smaller than boxDistance
|
||||
glm::vec3 boxScale = glm::vec3(2.68f, 1.78f, 0.431f);
|
||||
float boxDistance = farClip;
|
||||
float boxBoundingRadius = 0.5f * glm::length(boxScale);
|
||||
float boxAngle = boxBoundingRadius / boxDistance; // sine of small angles approximation
|
||||
|
@ -592,6 +592,204 @@ void ViewFrustumTests::testBoxInFrustum() {
|
|||
QCOMPARE(view.boxInFrustum(box), ViewFrustum::OUTSIDE);
|
||||
}
|
||||
|
||||
void ViewFrustumTests::testCubeInKeyhole() {
|
||||
float aspect = 1.0f;
|
||||
float fovX = PI / 2.0f;
|
||||
float fovY = 2.0f * asinf(sinf(0.5f * fovX) / aspect);
|
||||
float nearClip = 1.0f;
|
||||
float farClip = 100.0f;
|
||||
float holeRadius = 10.0f;
|
||||
|
||||
glm::vec3 center = glm::vec3(12.3f, 4.56f, 89.7f);
|
||||
|
||||
float angle = PI / 7.0f;
|
||||
glm::vec3 axis = Vectors::UNIT_Y;
|
||||
glm::quat rotation = glm::angleAxis(angle, axis);
|
||||
|
||||
ViewFrustum view;
|
||||
view.setProjection(glm::perspective(fovX, aspect, nearClip, farClip));
|
||||
view.setPosition(center);
|
||||
view.setOrientation(rotation);
|
||||
view.setKeyholeRadius(holeRadius);
|
||||
view.calculate();
|
||||
|
||||
float delta = 0.1f;
|
||||
float deltaAngle = 0.01f;
|
||||
glm::quat elevation, swing;
|
||||
glm::vec3 cubeCenter, localOffset;
|
||||
|
||||
float cubeScale = 2.68f; // must be much smaller than cubeDistance for small angle approx below
|
||||
glm::vec3 halfScaleOffset = 0.5f * glm::vec3(cubeScale);
|
||||
float cubeDistance = farClip;
|
||||
float cubeBoundingRadius = 0.5f * sqrtf(3.0f) * cubeScale;
|
||||
float cubeAngle = cubeBoundingRadius / cubeDistance; // sine of small angles approximation
|
||||
AACube cube(center, cubeScale);
|
||||
|
||||
// farPlane
|
||||
localOffset = (cubeDistance - cubeBoundingRadius - delta) * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
localOffset = cubeDistance * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
localOffset = (cubeDistance + cubeBoundingRadius + delta) * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// nearPlane
|
||||
localOffset = (nearClip + 2.0f * cubeBoundingRadius + delta) * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
localOffset = (nearClip + delta) * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
// topPlane
|
||||
angle = 0.5f * fovY;
|
||||
elevation = glm::angleAxis(angle - cubeAngle - deltaAngle, localRight);
|
||||
localOffset = elevation * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
elevation = glm::angleAxis(angle, localRight);
|
||||
localOffset = elevation * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
elevation = glm::angleAxis(angle + cubeAngle + deltaAngle, localRight);
|
||||
localOffset = elevation * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// bottom plane
|
||||
angle = -0.5f * fovY;
|
||||
elevation = glm::angleAxis(angle + cubeAngle + deltaAngle, localRight);
|
||||
localOffset = elevation * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
elevation = glm::angleAxis(angle, localRight);
|
||||
localOffset = elevation * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
elevation = glm::angleAxis(angle - cubeAngle - deltaAngle, localRight);
|
||||
localOffset = elevation * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// right plane
|
||||
angle = 0.5f * fovX;
|
||||
swing = glm::angleAxis(angle - cubeAngle - deltaAngle, localUp);
|
||||
localOffset = swing * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
swing = glm::angleAxis(angle, localUp);
|
||||
localOffset = swing * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
swing = glm::angleAxis(angle + cubeAngle + deltaAngle, localUp);
|
||||
localOffset = swing * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// left plane
|
||||
angle = -0.5f * fovX;
|
||||
swing = glm::angleAxis(angle + cubeAngle + deltaAngle, localUp);
|
||||
localOffset = swing * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
swing = glm::angleAxis(angle, localUp);
|
||||
localOffset = swing * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
swing = glm::angleAxis(angle - cubeAngle - deltaAngle, localUp);
|
||||
localOffset = swing * (cubeDistance * localForward);
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// central sphere right
|
||||
localOffset = (holeRadius - cubeBoundingRadius - delta) * localRight;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
localOffset = holeRadius * localRight;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
localOffset = (holeRadius + cubeBoundingRadius + delta) * localRight;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// central sphere up
|
||||
localOffset = (holeRadius - cubeBoundingRadius - delta) * localUp;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
localOffset = holeRadius * localUp;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
localOffset = (holeRadius + cubeBoundingRadius + delta) * localUp;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// central sphere back
|
||||
localOffset = (-holeRadius + cubeBoundingRadius + delta) * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE);
|
||||
|
||||
localOffset = - holeRadius * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT);
|
||||
|
||||
localOffset = (-holeRadius - cubeBoundingRadius - delta) * localForward;
|
||||
cubeCenter = center + rotation * localOffset;
|
||||
cube.setBox(cubeCenter - halfScaleOffset, cubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::OUTSIDE);
|
||||
|
||||
// central sphere center
|
||||
float bigCubeScale = 2.0f * holeRadius / sqrtf(3.0f) - delta;
|
||||
cube.setBox(center - glm::vec3(0.5f * bigCubeScale), bigCubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INSIDE); // smaller than sphere
|
||||
|
||||
bigCubeScale = 2.0f * holeRadius / sqrtf(3.0f) + delta;
|
||||
cube.setBox(center - glm::vec3(0.5f * bigCubeScale), bigCubeScale);
|
||||
QCOMPARE(view.cubeInKeyhole(cube), ViewFrustum::INTERSECT); // larger than sphere
|
||||
}
|
||||
|
||||
void ViewFrustumTests::testSphereTouchesKeyhole() {
|
||||
float aspect = 1.0f;
|
||||
float fovX = PI / 2.0f;
|
||||
|
@ -618,7 +816,7 @@ void ViewFrustumTests::testSphereTouchesKeyhole() {
|
|||
glm::quat elevation, swing;
|
||||
glm::vec3 sphereCenter, localOffset;
|
||||
|
||||
float sphereRadius = 2.68f; // must be much smaller than sphereDistance
|
||||
float sphereRadius = 2.68f; // must be much smaller than sphereDistance for small angle approx below
|
||||
float sphereDistance = farClip;
|
||||
float sphereAngle = sphereRadius / sphereDistance; // sine of small angles approximation
|
||||
|
||||
|
@ -786,7 +984,7 @@ void ViewFrustumTests::testCubeTouchesKeyhole() {
|
|||
glm::quat elevation, swing;
|
||||
glm::vec3 cubeCenter, localOffset;
|
||||
|
||||
float cubeScale = 2.68f; // must be much smaller than cubeDistance
|
||||
float cubeScale = 2.68f; // must be much smaller than cubeDistance for small angle approx below
|
||||
glm::vec3 halfScaleOffset = 0.5f * glm::vec3(cubeScale);
|
||||
float cubeDistance = farClip;
|
||||
float cubeBoundingRadius = 0.5f * sqrtf(3.0f) * cubeScale;
|
||||
|
|
|
@ -23,6 +23,7 @@ private slots:
|
|||
void testSphereInFrustum();
|
||||
void testCubeInFrustum();
|
||||
void testBoxInFrustum();
|
||||
void testCubeInKeyhole();
|
||||
void testSphereTouchesKeyhole();
|
||||
void testCubeTouchesKeyhole();
|
||||
void testBoxTouchesKeyhole();
|
||||
|
|
Loading…
Reference in a new issue