/* * Returns true if the given point is visible from the given viewpoint. * * A point is visible if it will be on screen, and if it is not occluded by * other objects. * * Input: * point: The point whose visibility we want to check. * viewpoint: The viewpoint to check from. * * Returns: True if the point is visible from the viewpoint. */ bool VisibilityChecker::IsVisible(const Ogre::Vector3& point, const Viewpoint& viewpoint) { float screen_x; float screen_y; auto old_position = camera_->getPosition(); auto old_direction = camera_->getDirection(); camera_->setPosition(viewpoint.position()); camera_->lookAt(viewpoint.focus()); GetScreenPosition(point, &screen_x, &screen_y); bool result = false; if (IsOnScreen(screen_x, screen_y)) { Ogre::Ray ray; camera_->getCameraToViewportRay(screen_x, screen_y, &ray); Ogre::Vector3 hit; if (RaycastAABB(ray, &hit)) { auto dist = point.distance(hit); if (dist < kOcclusionThreshold) { result = true; } else { // Hit something, but too far away from the target. result = false; } } else { // No hits. The ray should hit the target, but if it doesn't, that usually // indicates visibility. This is because if the target is occluded, the // ray is likely to have hit the occluding object. result = true; } } else { // Not on screen result= false; } camera_->setPosition(old_position); camera_->setDirection(old_direction); return result; }