mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-03 09:20:26 -05:00
Limit camera to not go below the ground in globebrowsing interaction mode.
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <modules/globebrowsing/other/threadpool.h>
|
||||
#include <modules/globebrowsing/tile/temporaltileprovider.h>
|
||||
#include <modules/globebrowsing/tile/tileselector.h>
|
||||
|
||||
// open space includes
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
@@ -260,10 +261,58 @@ namespace openspace {
|
||||
_tileProviderManager->prerender();
|
||||
}
|
||||
|
||||
glm::dvec3 RenderableGlobe::geodeticSurfaceProjection(glm::dvec3 position) {
|
||||
glm::dvec3 RenderableGlobe::projectOnEllipsoid(glm::dvec3 position) {
|
||||
return _ellipsoid.geodeticSurfaceProjection(position);
|
||||
}
|
||||
|
||||
glm::dvec3 RenderableGlobe::projectOnGlobeSurface(glm::dvec3 position) {
|
||||
|
||||
Geodetic2 geodeticPosition = _ellipsoid.cartesianToGeodetic2(position);
|
||||
glm::dvec3 ellipsoidNormal = _ellipsoid.geodeticSurfaceNormal(geodeticPosition);
|
||||
int chunkLevel = 20;
|
||||
ChunkIndex chunkIdx = ChunkIndex(geodeticPosition, chunkLevel);
|
||||
GeodeticPatch patch = GeodeticPatch(chunkIdx);
|
||||
Geodetic2 geoDiffPatch = patch.getCorner(Quad::NORTH_EAST) - patch.getCorner(Quad::SOUTH_WEST);
|
||||
Geodetic2 geoDiffPoint = geodeticPosition - patch.getCorner(Quad::SOUTH_WEST);
|
||||
glm::vec2 uvPatch = glm::vec2(geoDiffPoint.lon / geoDiffPatch.lon, geoDiffPoint.lat / geoDiffPatch.lat);
|
||||
|
||||
const auto& heightMapProviders = _tileProviderManager->getActivatedLayerCategory(LayeredTextures::HeightMaps);
|
||||
|
||||
if (heightMapProviders.size() == 0)
|
||||
return _ellipsoid.geodeticSurfaceProjection(position);
|
||||
|
||||
TileAndTransform tileAndTransform = TileSelector::getHighestResolutionTile(heightMapProviders[0].get(), chunkIdx);
|
||||
|
||||
glm::vec2 transformedUv = tileAndTransform.uvTransform.uvOffset + tileAndTransform.uvTransform.uvScale * uvPatch;
|
||||
double sampledHeight = tileAndTransform.tile.sampleValueAsDouble(transformedUv);
|
||||
|
||||
return _ellipsoid.geodeticSurfaceProjection(position) + ellipsoidNormal * (sampledHeight + 100);
|
||||
}
|
||||
|
||||
double RenderableGlobe::getHeight(glm::dvec3 position) {
|
||||
|
||||
Geodetic2 geodeticPosition = _ellipsoid.cartesianToGeodetic2(position);
|
||||
glm::dvec3 ellipsoidNormal = _ellipsoid.geodeticSurfaceNormal(geodeticPosition);
|
||||
int chunkLevel = 16;
|
||||
ChunkIndex chunkIdx = ChunkIndex(geodeticPosition, chunkLevel);
|
||||
GeodeticPatch patch = GeodeticPatch(chunkIdx);
|
||||
Geodetic2 geoDiffPatch = patch.getCorner(Quad::NORTH_EAST) - patch.getCorner(Quad::SOUTH_WEST);
|
||||
Geodetic2 geoDiffPoint = geodeticPosition - patch.getCorner(Quad::SOUTH_WEST);
|
||||
glm::vec2 uvPatch = glm::vec2(geoDiffPoint.lon / geoDiffPatch.lon, geoDiffPoint.lat / geoDiffPatch.lat);
|
||||
|
||||
const auto& heightMapProviders = _tileProviderManager->getActivatedLayerCategory(LayeredTextures::HeightMaps);
|
||||
|
||||
if (heightMapProviders.size() == 0)
|
||||
return 0;
|
||||
|
||||
TileAndTransform tileAndTransform = TileSelector::getHighestResolutionTile(heightMapProviders[0].get(), chunkIdx);
|
||||
|
||||
glm::vec2 transformedUv = tileAndTransform.uvTransform.uvOffset + tileAndTransform.uvTransform.uvScale * uvPatch;
|
||||
double sampledHeight = tileAndTransform.tile.sampleValueAsDouble(transformedUv);
|
||||
|
||||
return sampledHeight;
|
||||
}
|
||||
|
||||
std::shared_ptr<ChunkedLodGlobe> RenderableGlobe::chunkedLodGlobe() {
|
||||
return _chunkedLodGlobe;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,9 @@ public:
|
||||
void render(const RenderData& data) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
glm::dvec3 geodeticSurfaceProjection(glm::dvec3 position);
|
||||
glm::dvec3 projectOnEllipsoid(glm::dvec3 position);
|
||||
glm::dvec3 projectOnGlobeSurface(glm::dvec3 position);
|
||||
double getHeight(glm::dvec3 position);
|
||||
std::shared_ptr<ChunkedLodGlobe> chunkedLodGlobe();
|
||||
|
||||
properties::BoolProperty doFrustumCulling;
|
||||
|
||||
@@ -571,8 +571,6 @@ namespace openspace {
|
||||
pixelStart = glm::uvec2(pixelStart0.x >> toShift, pixelStart0.y >> toShift);
|
||||
pixelEnd = glm::uvec2(pixelEnd0.x >> toShift, pixelEnd0.y >> toShift);
|
||||
numPixels = pixelEnd - pixelStart;
|
||||
if (numPixels.x < 1000 && (pixelStart.x % 2 || pixelStart.y % 2))
|
||||
int hej = 0;
|
||||
}
|
||||
|
||||
TileDataset::DataLayout::DataLayout() {
|
||||
|
||||
@@ -51,6 +51,128 @@ namespace openspace {
|
||||
|
||||
const Tile Tile::TileUnavailable = {nullptr, nullptr, Tile::Status::Unavailable };
|
||||
|
||||
double Tile::sampleValueAsDouble(glm::vec2 uv, int band) {
|
||||
if (texture == nullptr || status != Status::OK) {
|
||||
return 0;
|
||||
}
|
||||
glm::uvec3 dimensions = texture->dimensions();
|
||||
if (band >= dimensions.z || band < 0) {
|
||||
throw ghoul::RuntimeError("Cannot sample from band " + std::to_string(band) + "in texture tile.");
|
||||
}
|
||||
glm::vec2 samplePos = uv * glm::vec2(dimensions.xy());
|
||||
glm::uvec2 samplePos00 = samplePos;
|
||||
samplePos00 = glm::clamp(samplePos00, glm::uvec2(0, 0), dimensions.xy());
|
||||
glm::vec2 samplePosFract = samplePos - glm::vec2(samplePos00);
|
||||
|
||||
glm::uvec2 samplePos10 = glm::min(samplePos00 + glm::uvec2(1, 0), dimensions.xy());
|
||||
glm::uvec2 samplePos01 = glm::min(samplePos00 + glm::uvec2(0, 1), dimensions.xy());
|
||||
glm::uvec2 samplePos11 = glm::min(samplePos00 + glm::uvec2(1, 1), dimensions.xy());
|
||||
|
||||
unsigned int linearSamplePos00 = (dimensions.x * dimensions.z) * samplePos00.y + (samplePos00.x * dimensions.z) + band;
|
||||
unsigned int linearSamplePos10 = (dimensions.x * dimensions.z) * samplePos10.y + (samplePos10.x * dimensions.z) + band;
|
||||
unsigned int linearSamplePos01 = (dimensions.x * dimensions.z) * samplePos01.y + (samplePos01.x * dimensions.z) + band;
|
||||
unsigned int linearSamplePos11 = (dimensions.x * dimensions.z) * samplePos11.y + (samplePos11.x * dimensions.z) + band;
|
||||
|
||||
GLuint dataType = texture->dataType();
|
||||
switch (dataType)
|
||||
{
|
||||
case GL_UNSIGNED_BYTE: {
|
||||
const GLubyte* pixelData = reinterpret_cast<const GLubyte*>(texture->pixelData());
|
||||
double sample00 = static_cast<double>(pixelData[linearSamplePos00]);
|
||||
double sample10 = static_cast<double>(pixelData[linearSamplePos10]);
|
||||
double sample01 = static_cast<double>(pixelData[linearSamplePos01]);
|
||||
double sample11 = static_cast<double>(pixelData[linearSamplePos11]);
|
||||
|
||||
double sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
|
||||
double sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
|
||||
|
||||
double sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
|
||||
|
||||
return sample;
|
||||
}
|
||||
case GL_UNSIGNED_SHORT: {
|
||||
const GLushort* pixelData = reinterpret_cast<const GLushort*>(texture->pixelData());
|
||||
double sample00 = static_cast<double>(pixelData[linearSamplePos00]);
|
||||
double sample10 = static_cast<double>(pixelData[linearSamplePos10]);
|
||||
double sample01 = static_cast<double>(pixelData[linearSamplePos01]);
|
||||
double sample11 = static_cast<double>(pixelData[linearSamplePos11]);
|
||||
|
||||
double sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
|
||||
double sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
|
||||
|
||||
double sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
|
||||
|
||||
return sample; }
|
||||
case GL_SHORT: {
|
||||
const GLshort* pixelData = reinterpret_cast<const GLshort*>(texture->pixelData());
|
||||
double sample00 = static_cast<double>(pixelData[linearSamplePos00]);
|
||||
double sample10 = static_cast<double>(pixelData[linearSamplePos10]);
|
||||
double sample01 = static_cast<double>(pixelData[linearSamplePos01]);
|
||||
double sample11 = static_cast<double>(pixelData[linearSamplePos11]);
|
||||
|
||||
double sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
|
||||
double sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
|
||||
|
||||
double sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
|
||||
|
||||
return sample; }
|
||||
case GL_UNSIGNED_INT: {
|
||||
const GLuint* pixelData = reinterpret_cast<const GLuint*>(texture->pixelData());
|
||||
double sample00 = static_cast<double>(pixelData[linearSamplePos00]);
|
||||
double sample10 = static_cast<double>(pixelData[linearSamplePos10]);
|
||||
double sample01 = static_cast<double>(pixelData[linearSamplePos01]);
|
||||
double sample11 = static_cast<double>(pixelData[linearSamplePos11]);
|
||||
|
||||
double sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
|
||||
double sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
|
||||
|
||||
double sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
|
||||
|
||||
return sample; }
|
||||
case GL_INT: {
|
||||
const GLint* pixelData = reinterpret_cast<const GLint*>(texture->pixelData());
|
||||
double sample00 = static_cast<double>(pixelData[linearSamplePos00]);
|
||||
double sample10 = static_cast<double>(pixelData[linearSamplePos10]);
|
||||
double sample01 = static_cast<double>(pixelData[linearSamplePos01]);
|
||||
double sample11 = static_cast<double>(pixelData[linearSamplePos11]);
|
||||
|
||||
double sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
|
||||
double sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
|
||||
|
||||
double sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
|
||||
|
||||
return sample; }
|
||||
case GL_FLOAT: {
|
||||
const GLfloat* pixelData = reinterpret_cast<const GLfloat*>(texture->pixelData());
|
||||
double sample00 = static_cast<double>(pixelData[linearSamplePos00]);
|
||||
double sample10 = static_cast<double>(pixelData[linearSamplePos10]);
|
||||
double sample01 = static_cast<double>(pixelData[linearSamplePos01]);
|
||||
double sample11 = static_cast<double>(pixelData[linearSamplePos11]);
|
||||
|
||||
double sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
|
||||
double sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
|
||||
|
||||
double sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
|
||||
|
||||
return sample; }
|
||||
case GL_DOUBLE: {
|
||||
const GLdouble* pixelData = reinterpret_cast<const GLdouble*>(texture->pixelData());
|
||||
double sample00 = static_cast<double>(pixelData[linearSamplePos00]);
|
||||
double sample10 = static_cast<double>(pixelData[linearSamplePos10]);
|
||||
double sample01 = static_cast<double>(pixelData[linearSamplePos01]);
|
||||
double sample11 = static_cast<double>(pixelData[linearSamplePos11]);
|
||||
|
||||
double sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
|
||||
double sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
|
||||
|
||||
double sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
|
||||
|
||||
return sample; }
|
||||
default:
|
||||
LWARNING("Unknown GL type in texture. Returning 0.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CachingTileProvider::CachingTileProvider(std::shared_ptr<AsyncTileDataProvider> tileReader,
|
||||
@@ -102,7 +224,6 @@ namespace openspace {
|
||||
return tile;
|
||||
}
|
||||
|
||||
|
||||
void CachingTileProvider::initTexturesFromLoadedData() {
|
||||
while (_asyncTextureDataProvider->hasLoadedTextureData()) {
|
||||
std::shared_ptr<TileIOResult> tileIOResult = _asyncTextureDataProvider->nextTileIOResult();
|
||||
|
||||
@@ -59,6 +59,8 @@ namespace openspace {
|
||||
enum class Status { Unavailable, OutOfRange, IOError, OK } status;
|
||||
|
||||
static const Tile TileUnavailable;
|
||||
|
||||
double sampleValueAsDouble(glm::vec2 uv, int band = 0);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user