final names for ViewFrustum intersection tests

This commit is contained in:
Andrew Meadows 2016-02-23 14:16:01 -08:00
parent 5d1e283508
commit f964df6c97
9 changed files with 612 additions and 621 deletions

View file

@ -188,14 +188,14 @@ void Avatar::simulate(float deltaTime) {
// simple frustum check // simple frustum check
float boundingRadius = getBoundingRadius(); float boundingRadius = getBoundingRadius();
bool inViewFrustum = (bool)(qApp->getViewFrustum()->sphereInFrustum(getPosition(), boundingRadius)); bool inView = qApp->getViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius);
{ {
PerformanceTimer perfTimer("hand"); PerformanceTimer perfTimer("hand");
getHand()->simulate(deltaTime, false); getHand()->simulate(deltaTime, false);
} }
if (_shouldAnimate && !_shouldSkipRender && inViewFrustum) { if (_shouldAnimate && !_shouldSkipRender && inView) {
{ {
PerformanceTimer perfTimer("skeleton"); PerformanceTimer perfTimer("skeleton");
_skeletonModel.getRig()->copyJointsFromJointData(_jointData); _skeletonModel.getRig()->copyJointsFromJointData(_jointData);
@ -400,7 +400,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
frustum = qApp->getDisplayViewFrustum(); frustum = qApp->getDisplayViewFrustum();
} }
if ((bool)(frustum->sphereInFrustum(getPosition(), boundingRadius))) { if (frustum->sphereIntersectsFrustum(getPosition(), boundingRadius)) {
endRender(); endRender();
return; return;
} }
@ -516,7 +516,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
auto& frustum = *renderArgs->_viewFrustum; auto& frustum = *renderArgs->_viewFrustum;
auto textPosition = getDisplayNamePosition(); auto textPosition = getDisplayNamePosition();
if ((bool)frustum.pointInFrustum(textPosition)) { if (frustum.pointIntersectsFrustum(textPosition)) {
renderDisplayName(batch, frustum, textPosition); renderDisplayName(batch, frustum, textPosition);
} }
} }
@ -669,10 +669,10 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
return namePosition; return namePosition;
} }
Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const { Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const {
Q_ASSERT_X((bool)(frustum.pointInFrustum(textPosition)), Q_ASSERT_X(view.pointIntersectsFrustum(textPosition),
"Avatar::calculateDisplayNameTransform", "Text not in viewfrustum."); "Avatar::calculateDisplayNameTransform", "Text not in viewfrustum.");
glm::vec3 toFrustum = frustum.getPosition() - textPosition; glm::vec3 toFrustum = view.getPosition() - textPosition;
// Compute orientation // Compute orientation
// If x and z are 0, atan(x, z) adais undefined, so default to 0 degrees // If x and z are 0, atan(x, z) adais undefined, so default to 0 degrees
@ -694,7 +694,7 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, cons
return result; return result;
} }
void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::vec3& textPosition) const { void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const {
PROFILE_RANGE_BATCH(batch, __FUNCTION__); PROFILE_RANGE_BATCH(batch, __FUNCTION__);
bool shouldShowReceiveStats = DependencyManager::get<AvatarManager>()->shouldShowReceiveStats() && !isMyAvatar(); bool shouldShowReceiveStats = DependencyManager::get<AvatarManager>()->shouldShowReceiveStats() && !isMyAvatar();
@ -702,7 +702,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co
// If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return // If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return
static const float CLIP_DISTANCE = 0.2f; static const float CLIP_DISTANCE = 0.2f;
if ((_displayName.isEmpty() && !shouldShowReceiveStats) || _displayNameAlpha == 0.0f if ((_displayName.isEmpty() && !shouldShowReceiveStats) || _displayNameAlpha == 0.0f
|| (glm::dot(frustum.getDirection(), getDisplayNamePosition() - frustum.getPosition()) <= CLIP_DISTANCE)) { || (glm::dot(view.getDirection(), getDisplayNamePosition() - view.getPosition()) <= CLIP_DISTANCE)) {
return; return;
} }
auto renderer = textRenderer(DISPLAYNAME); auto renderer = textRenderer(DISPLAYNAME);
@ -743,7 +743,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co
(_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA); (_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA);
// Compute display name transform // Compute display name transform
auto textTransform = calculateDisplayNameTransform(frustum, textPosition); auto textTransform = calculateDisplayNameTransform(view, textPosition);
// Test on extent above insures abs(height) > 0.0f // Test on extent above insures abs(height) > 0.0f
textTransform.postScale(1.0f / height); textTransform.postScale(1.0f / height);
batch.setModelTransform(textTransform); batch.setModelTransform(textTransform);

View file

@ -231,8 +231,8 @@ protected:
float getPelvisFloatingHeight() const; float getPelvisFloatingHeight() const;
glm::vec3 getDisplayNamePosition() const; glm::vec3 getDisplayNamePosition() const;
Transform calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const; Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const;
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::vec3& textPosition) const; void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const;
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f); virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f);
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const; virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
virtual void fixupModelsInScene(); virtual void fixupModelsInScene();

View file

@ -91,7 +91,7 @@ void OctreeHeadlessViewer::queryOctree() {
if (foundRootDetails) { if (foundRootDetails) {
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) { if ((bool)(_viewFrustum.calculateCubeKeyholeIntersection(serverBounds))) {
inViewServers++; inViewServers++;
} }
} }
@ -162,7 +162,7 @@ void OctreeHeadlessViewer::queryOctree() {
if (foundRootDetails) { if (foundRootDetails) {
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
inView = _viewFrustum.cubeInFrustum(serverBounds); inView = (bool)(_viewFrustum.calculateCubeKeyholeIntersection(serverBounds));
} }
if (inView) { if (inView) {

View file

@ -130,33 +130,7 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
return "Unknown"; return "Unknown";
} }
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const { ViewFrustum::location ViewFrustum::calculateCubeFrustumIntersection(const AACube& cube) const {
// only check against frustum
for(int i = 0; i < 6; ++i) {
float distance = _planes[i].distance(point);
if (distance < 0.0f) {
return OUTSIDE;
}
}
return INSIDE;
}
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
// only check against frustum
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
float distance = _planes[i].distance(center);
if (distance < -radius) {
// This is outside the regular frustum, so just return the value from checking the keyhole
return OUTSIDE;
} else if (distance < radius) {
result = INTERSECT;
}
}
return result;
}
ViewFrustum::location ViewFrustum::cubeInFrustum(const AACube& cube) const {
// only check against frustum // only check against frustum
ViewFrustum::location result = INSIDE; ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) { for(int i=0; i < 6; i++) {
@ -175,25 +149,6 @@ ViewFrustum::location ViewFrustum::cubeInFrustum(const AACube& cube) const {
return result; return result;
} }
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
// only check against frustum
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
const glm::vec3& normal = _planes[i].getNormal();
// check distance to farthest box point
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
return OUTSIDE;
} else {
// check distance to nearest box point
if (_planes[i].distance(box.getNearestVertex(normal)) < 0.0f) {
// box straddles the plane
result = INTERSECT;
}
}
}
return result;
}
const float HALF_SQRT_THREE = 0.8660254f; const float HALF_SQRT_THREE = 0.8660254f;
ViewFrustum::location ViewFrustum::calculateCubeKeyholeIntersection(const AACube& cube) const { ViewFrustum::location ViewFrustum::calculateCubeKeyholeIntersection(const AACube& cube) const {
@ -216,11 +171,47 @@ ViewFrustum::location ViewFrustum::calculateCubeKeyholeIntersection(const AACube
} }
// check against frustum // check against frustum
ViewFrustum::location frustumResult = cubeInFrustum(cube); ViewFrustum::location frustumResult = calculateCubeFrustumIntersection(cube);
return (frustumResult == OUTSIDE) ? sphereResult : frustumResult; return (frustumResult == OUTSIDE) ? sphereResult : frustumResult;
} }
bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const {
// only check against frustum
for(int i = 0; i < 6; ++i) {
float distance = _planes[i].distance(point);
if (distance < 0.0f) {
return false;
}
}
return true;
}
bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius) const {
// only check against frustum
for(int i=0; i < 6; i++) {
float distance = _planes[i].distance(center);
if (distance < -radius) {
// This is outside the regular frustum, so just return the value from checking the keyhole
return false;
}
}
return true;
}
bool ViewFrustum::boxIntersectsFrustum(const AABox& box) const {
// only check against frustum
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
const glm::vec3& normal = _planes[i].getNormal();
// check distance to farthest box point
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
return false;
}
}
return true;
}
bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius) const { bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius) const {
// check positive touch against central sphere // check positive touch against central sphere
if (glm::length(center - _position) <= (radius + _centerSphereRadius)) { if (glm::length(center - _position) <= (radius + _centerSphereRadius)) {

View file

@ -94,15 +94,15 @@ public:
typedef enum { OUTSIDE = 0, INTERSECT, INSIDE } location; typedef enum { OUTSIDE = 0, INTERSECT, INSIDE } location;
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
ViewFrustum::location sphereInFrustum(const glm::vec3& center, float radius) const;
ViewFrustum::location cubeInFrustum(const AACube& cube) const;
ViewFrustum::location boxInFrustum(const AABox& box) const;
/// @return INSIDE, INTERSECT, or OUTSIDE depending on how cube intersects the keyhole shape /// @return INSIDE, INTERSECT, or OUTSIDE depending on how cube intersects the keyhole shape
ViewFrustum::location calculateCubeFrustumIntersection(const AACube& cube) const;
ViewFrustum::location calculateCubeKeyholeIntersection(const AACube& cube) const; ViewFrustum::location calculateCubeKeyholeIntersection(const AACube& cube) const;
// more efficient methods when only need boolean result bool pointIntersectsFrustum(const glm::vec3& point) const;
bool sphereIntersectsFrustum(const glm::vec3& center, float radius) const;
bool cubeIntersectsFrustum(const AACube& box) const;
bool boxIntersectsFrustum(const AABox& box) const;
bool sphereIntersectsKeyhole(const glm::vec3& center, float radius) const; bool sphereIntersectsKeyhole(const glm::vec3& center, float radius) const;
bool cubeIntersectsKeyhole(const AACube& cube) const; bool cubeIntersectsKeyhole(const AACube& cube) const;
bool boxIntersectsKeyhole(const AABox& box) const; bool boxIntersectsKeyhole(const AABox& box) const;

View file

@ -478,7 +478,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
glm::vec4 cubeColor(1.0f, 1.0f, 0.0f, 1.0f); glm::vec4 cubeColor(1.0f, 1.0f, 0.0f, 1.0f);
if (isSkinned) { if (isSkinned) {
cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f); cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f);
} else if ((bool)(args->_viewFrustum->boxInFrustum(partBounds))) { } else if (args->_viewFrustum->boxIntersectsFrustum(partBounds)) {
cubeColor = glm::vec4(1.0f, 0.0f, 1.0f, 1.0f); cubeColor = glm::vec4(1.0f, 0.0f, 1.0f, 1.0f);
} }

View file

@ -39,12 +39,12 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
// TODO: some entity types (like lights) might want to be rendered even // TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum... // when they are outside of the view frustum...
bool outOfView; bool inView;
{ {
PerformanceTimer perfTimer("boxInFrustum"); PerformanceTimer perfTimer("boxIntersectsFrustum");
outOfView = frustum->boxInFrustum(item.bound) == ViewFrustum::OUTSIDE; inView = frustum->boxIntersectsFrustum(item.bound);
} }
if (!outOfView) { if (inView) {
bool bigEnoughToRender; bool bigEnoughToRender;
{ {
PerformanceTimer perfTimer("shouldRender"); PerformanceTimer perfTimer("shouldRender");
@ -238,7 +238,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
} }
bool frustumTest(const AABox& bound) { bool frustumTest(const AABox& bound) {
if (_args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE) { if (!_args->_viewFrustum->boxIntersectsFrustum(bound)) {
_renderDetails._outOfView++; _renderDetails._outOfView++;
return false; return false;
} }

File diff suppressed because it is too large Load diff

View file

@ -19,14 +19,14 @@ class ViewFrustumTests : public QObject {
private slots: private slots:
void testInit(); void testInit();
void testPointInFrustum(); void testCubeFrustumIntersection();
void testSphereInFrustum(); void testCubeKeyholeIntersection();
void testCubeInFrustum(); void testPointIntersectsFrustum();
void testBoxInFrustum(); void testSphereIntersectsFrustum();
void testCubeInKeyhole(); void testBoxIntersectsFrustum();
void testSphereTouchesKeyhole(); void testSphereIntersectsKeyhole();
void testCubeTouchesKeyhole(); void testCubeIntersectsKeyhole();
void testBoxTouchesKeyhole(); void testBoxIntersectsKeyhole();
}; };
#endif // hifi_ViewFruxtumTests_h #endif // hifi_ViewFruxtumTests_h