Add BoundingRegionWithLooseFittingHeights, better use of std::variant
This commit is contained in:
parent
d18aad7ca2
commit
f50aaae886
|
|
@ -5,9 +5,16 @@
|
|||
#include "CesiumGeometry/OrientedBoundingBox.h"
|
||||
#include "CesiumGeospatial/BoundingRegion.h"
|
||||
#include "CesiumGeometry/BoundingSphere.h"
|
||||
#include "CesiumGeospatial/BoundingRegionWithLooseFittingHeights.h"
|
||||
|
||||
namespace Cesium3DTiles {
|
||||
typedef std::variant<CesiumGeometry::OrientedBoundingBox, CesiumGeospatial::BoundingRegion, CesiumGeometry::BoundingSphere> BoundingVolume;
|
||||
|
||||
typedef std::variant<
|
||||
CesiumGeometry::BoundingSphere,
|
||||
CesiumGeometry::OrientedBoundingBox,
|
||||
CesiumGeospatial::BoundingRegion,
|
||||
CesiumGeospatial::BoundingRegionWithLooseFittingHeights
|
||||
> BoundingVolume;
|
||||
|
||||
CESIUM3DTILES_API BoundingVolume transformBoundingVolume(const glm::dmat4x4& transform, const BoundingVolume& boundingVolume);
|
||||
CESIUM3DTILES_API glm::dvec3 getBoundingVolumeCenter(const BoundingVolume& boundingVolume);
|
||||
|
|
|
|||
|
|
@ -7,59 +7,63 @@ using namespace CesiumGeospatial;
|
|||
namespace Cesium3DTiles {
|
||||
|
||||
BoundingVolume transformBoundingVolume(const glm::dmat4x4& transform, const BoundingVolume& boundingVolume) {
|
||||
switch (boundingVolume.index()) {
|
||||
case 0:
|
||||
{
|
||||
const OrientedBoundingBox& boundingBox = std::get<OrientedBoundingBox>(boundingVolume);
|
||||
glm::dvec3 center = transform * glm::dvec4(boundingBox.getCenter(), 1.0);
|
||||
glm::dmat3 halfAxes = glm::dmat3(transform) * boundingBox.getHalfAxes();
|
||||
return OrientedBoundingBox(center, halfAxes);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// Regions are not transformed.
|
||||
return boundingVolume;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
const BoundingSphere& boundingSphere = std::get<BoundingSphere>(boundingVolume);
|
||||
glm::dvec3 center = transform * glm::dvec4(boundingSphere.getCenter(), 1.0);
|
||||
struct Operation {
|
||||
const glm::dmat4x4& transform;
|
||||
|
||||
double uniformScale = std::max(
|
||||
std::max(
|
||||
glm::length(glm::dvec3(transform[0])),
|
||||
glm::length(glm::dvec3(transform[1]))
|
||||
),
|
||||
glm::length(glm::dvec3(transform[2]))
|
||||
);
|
||||
BoundingVolume operator()(const OrientedBoundingBox& boundingBox) {
|
||||
glm::dvec3 center = transform * glm::dvec4(boundingBox.getCenter(), 1.0);
|
||||
glm::dmat3 halfAxes = glm::dmat3(transform) * boundingBox.getHalfAxes();
|
||||
return OrientedBoundingBox(center, halfAxes);
|
||||
}
|
||||
|
||||
return BoundingSphere(center, boundingSphere.getRadius() * uniformScale);
|
||||
}
|
||||
default:
|
||||
return boundingVolume;
|
||||
}
|
||||
BoundingVolume operator()(const BoundingRegion& boundingRegion) {
|
||||
// Regions are not transformed.
|
||||
return boundingRegion;
|
||||
}
|
||||
|
||||
BoundingVolume operator()(const BoundingSphere& boundingSphere) {
|
||||
glm::dvec3 center = transform * glm::dvec4(boundingSphere.getCenter(), 1.0);
|
||||
|
||||
double uniformScale = std::max(
|
||||
std::max(
|
||||
glm::length(glm::dvec3(transform[0])),
|
||||
glm::length(glm::dvec3(transform[1]))
|
||||
),
|
||||
glm::length(glm::dvec3(transform[2]))
|
||||
);
|
||||
|
||||
return BoundingSphere(center, boundingSphere.getRadius() * uniformScale);
|
||||
}
|
||||
|
||||
BoundingVolume operator()(const BoundingRegionWithLooseFittingHeights& boundingRegion) {
|
||||
// Regions are not transformed.
|
||||
return boundingRegion;
|
||||
}
|
||||
};
|
||||
|
||||
return std::visit(Operation { transform }, boundingVolume);
|
||||
}
|
||||
|
||||
glm::dvec3 getBoundingVolumeCenter(const BoundingVolume& boundingVolume) {
|
||||
switch (boundingVolume.index()) {
|
||||
case 0:
|
||||
{
|
||||
const OrientedBoundingBox& boundingBox = std::get<OrientedBoundingBox>(boundingVolume);
|
||||
return boundingBox.getCenter();
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
const BoundingRegion& region = std::get<BoundingRegion>(boundingVolume);
|
||||
return region.getBoundingBox().getCenter();
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
const BoundingSphere& boundingSphere = std::get<BoundingSphere>(boundingVolume);
|
||||
return boundingSphere.getCenter();
|
||||
}
|
||||
default:
|
||||
return glm::dvec3(0.0);
|
||||
}
|
||||
struct Operation {
|
||||
glm::dvec3 operator()(const OrientedBoundingBox& boundingBox) {
|
||||
return boundingBox.getCenter();
|
||||
}
|
||||
|
||||
glm::dvec3 operator()(const BoundingRegion& boundingRegion) {
|
||||
return boundingRegion.getBoundingBox().getCenter();
|
||||
}
|
||||
|
||||
glm::dvec3 operator()(const BoundingSphere& boundingSphere) {
|
||||
return boundingSphere.getCenter();
|
||||
}
|
||||
|
||||
glm::dvec3 operator()(const BoundingRegionWithLooseFittingHeights& boundingRegion) {
|
||||
return boundingRegion.getBoundingRegion().getBoundingBox().getCenter();
|
||||
}
|
||||
};
|
||||
|
||||
return std::visit(Operation {}, boundingVolume);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,47 +149,51 @@ namespace Cesium3DTiles {
|
|||
|
||||
bool Camera::isBoundingVolumeVisible(const BoundingVolume& boundingVolume) const {
|
||||
// TODO: use plane masks
|
||||
switch (boundingVolume.index()) {
|
||||
case 0:
|
||||
{
|
||||
const OrientedBoundingBox& boundingBox = std::get<OrientedBoundingBox>(boundingVolume);
|
||||
return Cesium3DTiles::isBoundingVolumeVisible(boundingBox, this->_leftPlane, this->_rightPlane, this->_bottomPlane, this->_topPlane);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
const BoundingRegion& boundingRegion = std::get<BoundingRegion>(boundingVolume);
|
||||
return Cesium3DTiles::isBoundingVolumeVisible(boundingRegion, this->_leftPlane, this->_rightPlane, this->_bottomPlane, this->_topPlane);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
const BoundingSphere& boundingSphere = std::get<BoundingSphere>(boundingVolume);
|
||||
return Cesium3DTiles::isBoundingVolumeVisible(boundingSphere, this->_leftPlane, this->_rightPlane, this->_bottomPlane, this->_topPlane);
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
struct Operation {
|
||||
const Camera& camera;
|
||||
|
||||
bool operator()(const OrientedBoundingBox& boundingBox) {
|
||||
return Cesium3DTiles::isBoundingVolumeVisible(boundingBox, camera._leftPlane, camera._rightPlane, camera._bottomPlane, camera._topPlane);
|
||||
}
|
||||
|
||||
bool operator()(const BoundingRegion& boundingRegion) {
|
||||
return Cesium3DTiles::isBoundingVolumeVisible(boundingRegion, camera._leftPlane, camera._rightPlane, camera._bottomPlane, camera._topPlane);
|
||||
}
|
||||
|
||||
bool operator()(const BoundingSphere& boundingSphere) {
|
||||
return Cesium3DTiles::isBoundingVolumeVisible(boundingSphere, camera._leftPlane, camera._rightPlane, camera._bottomPlane, camera._topPlane);
|
||||
}
|
||||
|
||||
bool operator()(const BoundingRegionWithLooseFittingHeights& boundingRegion) {
|
||||
return Cesium3DTiles::isBoundingVolumeVisible(boundingRegion.getBoundingRegion(), camera._leftPlane, camera._rightPlane, camera._bottomPlane, camera._topPlane);
|
||||
}
|
||||
};
|
||||
|
||||
return std::visit(Operation { *this }, boundingVolume);
|
||||
}
|
||||
|
||||
double Camera::computeDistanceSquaredToBoundingVolume(const BoundingVolume& boundingVolume) const {
|
||||
switch (boundingVolume.index()) {
|
||||
case 0:
|
||||
{
|
||||
const OrientedBoundingBox& boundingBox = std::get<OrientedBoundingBox>(boundingVolume);
|
||||
return boundingBox.computeDistanceSquaredToPosition(this->_position);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
const BoundingRegion& boundingRegion = std::get<BoundingRegion>(boundingVolume);
|
||||
return boundingRegion.computeDistanceSquaredToPosition(this->_position);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
const BoundingSphere& boundingSphere = std::get<BoundingSphere>(boundingVolume);
|
||||
return boundingSphere.computeDistanceSquaredToPosition(this->_position);
|
||||
}
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
struct Operation {
|
||||
const Camera& camera;
|
||||
|
||||
double operator()(const OrientedBoundingBox& boundingBox) {
|
||||
return boundingBox.computeDistanceSquaredToPosition(camera._position);
|
||||
}
|
||||
|
||||
double operator()(const BoundingRegion& boundingRegion) {
|
||||
return boundingRegion.computeDistanceSquaredToPosition(camera._position);
|
||||
}
|
||||
|
||||
double operator()(const BoundingSphere& boundingSphere) {
|
||||
return boundingSphere.computeDistanceSquaredToPosition(camera._position);
|
||||
}
|
||||
|
||||
double operator()(const BoundingRegionWithLooseFittingHeights& boundingRegion) {
|
||||
return boundingRegion.computeConservativeDistanceSquaredToPosition(camera._position);
|
||||
}
|
||||
};
|
||||
|
||||
return std::visit(Operation { *this }, boundingVolume);
|
||||
}
|
||||
|
||||
double Camera::computeScreenSpaceError(double geometricError, double distance) const {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
|
||||
#include "CesiumGeospatial/Library.h"
|
||||
#include "CesiumGeospatial/BoundingRegion.h"
|
||||
|
||||
namespace CesiumGeospatial {
|
||||
|
||||
/**
|
||||
* @brief A {@see BoundingRegion} whose heights might be very inaccurate and so distances should be estimated conservatively
|
||||
* for level-of-detail computations.
|
||||
*
|
||||
* An instance of this class serves as a marker of the imprecision of the heights in a {@see BoundingRegion}, and also
|
||||
* has a {@see BoundingRegionWithLooseFittingHeights::computeConservativeDistanceSquaredToPosition} method to compute
|
||||
* the conservative distance metric.
|
||||
*/
|
||||
class CESIUMGEOSPATIAL_API BoundingRegionWithLooseFittingHeights {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new bounding region.
|
||||
*
|
||||
* @param boundingRegion The bounding region that has imprecise heights.
|
||||
*/
|
||||
BoundingRegionWithLooseFittingHeights(const BoundingRegion& boundingRegion);
|
||||
|
||||
/**
|
||||
* @brief Gets the bounding region that has imprecise heights.
|
||||
*/
|
||||
const BoundingRegion& getBoundingRegion() const { return this->_region; }
|
||||
|
||||
/**
|
||||
* @brief Computes the conservative distance-squared from a position in ellipsoid-centered Cartesian coordinates
|
||||
* to the closest point in this bounding region.
|
||||
*
|
||||
* It is conservative in that the distance is computed using whichever
|
||||
* is _farther away_ of this bounding region's imprecise minimum and maximum heights, so the returned distance
|
||||
* may be greater than what the distance to the bounding region would be if the heights were precise. When used for level-of-detail
|
||||
* selection, this ensures that imprecise selection caused by the imprecise heights will cause _too little_ detail to
|
||||
* be loaded rather than too much detail. This is important because overestimating the required level-of-detail can require
|
||||
* an excessive number of tiles to be loaded.
|
||||
*
|
||||
* @param position The position.
|
||||
* @param ellipsoid The ellipsoid on which this region is defined.
|
||||
* @return The distance-squared from the position to the closest point in the bounding region.
|
||||
*/
|
||||
double computeConservativeDistanceSquaredToPosition(const glm::dvec3& position, const Ellipsoid& ellipsoid = Ellipsoid::WGS84) const { return this->_region.computeDistanceSquaredToPosition(position, ellipsoid); }
|
||||
|
||||
/**
|
||||
* @brief Computes the conservative distance-squared from a longitude-latitude-height position
|
||||
* to the closest point in this bounding region.
|
||||
*
|
||||
* It is conservative in that the distance is computed using whichever
|
||||
* is _farther away_ of this bounding region's imprecise minimum and maximum heights, so the returned distance
|
||||
* may be greater than what the distance to the bounding region would be if the heights were precise. When used for level-of-detail
|
||||
* selection, this ensures that imprecise selection caused by the imprecise heights will cause _too little_ detail to
|
||||
* be loaded rather than too much detail. This is important because overestimating the required level-of-detail can require
|
||||
* an excessive number of tiles to be loaded.
|
||||
*
|
||||
* @param position The position.
|
||||
* @param ellipsoid The ellipsoid on which this region is defined.
|
||||
* @return The distance-squared from the position to the closest point in the bounding region.
|
||||
*/
|
||||
double computeConservativeDistanceSquaredToPosition(const Cartographic& position, const Ellipsoid& ellipsoid = Ellipsoid::WGS84) const { return this->_region.computeDistanceSquaredToPosition(position, ellipsoid); }
|
||||
|
||||
/**
|
||||
* @brief Computes the conservative distance-squared from a position to the closest point in this bounding region, when the longitude-latitude-height
|
||||
* and ellipsoid-centered Cartesian coordinates of the position are both already known.
|
||||
*
|
||||
* It is conservative in that the distance is computed using whichever
|
||||
* is _farther away_ of this bounding region's imprecise minimum and maximum heights, so the returned distance
|
||||
* may be greater than what the distance to the bounding region would be if the heights were precise. When used for level-of-detail
|
||||
* selection, this ensures that imprecise selection caused by the imprecise heights will cause _too little_ detail to
|
||||
* be loaded rather than too much detail. This is important because overestimating the required level-of-detail can require
|
||||
* an excessive number of tiles to be loaded.
|
||||
*
|
||||
* @param cartographicPosition The position as a longitude-latitude-height.
|
||||
* @param cartesianPosition The position as ellipsoid-centered Cartesian coordinates.
|
||||
* @return The distance-squared from the position to the closest point in the bounding region.
|
||||
*/
|
||||
double computeConservativeDistanceSquaredToPosition(const Cartographic& cartographicPosition, const glm::dvec3& cartesianPosition) const { return this->_region.computeDistanceSquaredToPosition(cartographicPosition, cartesianPosition); }
|
||||
|
||||
private:
|
||||
BoundingRegion _region;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#include "CesiumGeospatial/BoundingRegionWithLooseFittingHeights.h"
|
||||
|
||||
Loading…
Reference in New Issue