Clean up in code that clamps camera position to height map.

This commit is contained in:
Kalle Bladin
2016-06-22 13:55:02 -04:00
parent 7ff909c1fa
commit cb4b6dbdf3
7 changed files with 61 additions and 186 deletions
@@ -184,52 +184,59 @@ namespace openspace {
return _ellipsoid.geodeticSurfaceProjection(position);
}
glm::dvec3 RenderableGlobe::projectOnGlobeSurface(glm::dvec3 position) {
float RenderableGlobe::getHeight(glm::dvec3 position) {
// Get the uv coordinates to sample from
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);
glm::vec2 patchUV = glm::vec2(geoDiffPoint.lon / geoDiffPatch.lon, geoDiffPoint.lat / geoDiffPatch.lat);
// Get the tile provider for the height map
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;
const auto& tileProvider = heightMapProviders[0];
TileAndTransform tileAndTransform = TileSelector::getHighestResolutionTile(heightMapProviders[0].get(), chunkIdx);
// Transform the uv coordinates to the current tile texture
TileAndTransform tileAndTransform = TileSelector::getHighestResolutionTile(tileProvider.get(), chunkIdx);
const auto& tile = tileAndTransform.tile;
const auto& uvTransform = tileAndTransform.uvTransform;
const auto& depthTransform = tileProvider->depthTransform();
if (tile.status != Tile::Status::OK) {
return 0;
}
glm::vec2 transformedUv = uvTransform.uvOffset + uvTransform.uvScale * patchUV;
glm::vec2 transformedUv = tileAndTransform.uvTransform.uvOffset + tileAndTransform.uvTransform.uvScale * uvPatch;
double sampledHeight = tileAndTransform.tile.sampleValueAsDouble(transformedUv);
// Sample and do linear interpolation (could possibly be moved as a function in ghoul texture)
glm::uvec3 dimensions = tile.texture->dimensions();
glm::vec2 samplePos = transformedUv * glm::vec2(dimensions.xy());
glm::uvec2 samplePos00 = samplePos;
samplePos00 = glm::clamp(samplePos00, glm::uvec2(0, 0), dimensions.xy() - glm::uvec2(1));
glm::vec2 samplePosFract = samplePos - glm::vec2(samplePos00);
return sampledHeight;
glm::uvec2 samplePos10 = glm::min(samplePos00 + glm::uvec2(1, 0), dimensions.xy() - glm::uvec2(1));
glm::uvec2 samplePos01 = glm::min(samplePos00 + glm::uvec2(0, 1), dimensions.xy() - glm::uvec2(1));
glm::uvec2 samplePos11 = glm::min(samplePos00 + glm::uvec2(1, 1), dimensions.xy() - glm::uvec2(1));
float sample00 = tile.texture->texelAsFloat(samplePos00).x;
float sample10 = tile.texture->texelAsFloat(samplePos10).x;
float sample01 = tile.texture->texelAsFloat(samplePos01).x;
float sample11 = tile.texture->texelAsFloat(samplePos11).x;
float sample0 = sample00 * (1.0 - samplePosFract.x) + sample10 * samplePosFract.x;
float sample1 = sample01 * (1.0 - samplePosFract.x) + sample11 * samplePosFract.x;
float sample = sample0 * (1.0 - samplePosFract.y) + sample1 * samplePosFract.y;
// Perform depth transform to get the value in meters
float height = depthTransform.depthOffset + depthTransform.depthScale * sample;
// Return the result
return height;
}
std::shared_ptr<ChunkedLodGlobe> RenderableGlobe::chunkedLodGlobe() {
@@ -111,8 +111,7 @@ public:
void update(const UpdateData& data) override;
glm::dvec3 projectOnEllipsoid(glm::dvec3 position);
glm::dvec3 projectOnGlobeSurface(glm::dvec3 position);
double getHeight(glm::dvec3 position);
float getHeight(glm::dvec3 position);
std::shared_ptr<ChunkedLodGlobe> chunkedLodGlobe();
+9 -9
View File
@@ -460,12 +460,12 @@ namespace openspace {
format.ghoulFormat = Texture::Format::Red;
switch (gdalType) {
case GDT_Byte: format.glFormat = GL_R8; break;
case GDT_UInt16: format.glFormat = GL_R16; break;
case GDT_Int16: format.glFormat = GL_R16; break;
case GDT_UInt16: format.glFormat = GL_R16UI; break;
case GDT_Int16: format.glFormat = GL_R16_SNORM; break;
case GDT_UInt32: format.glFormat = GL_R32UI; break;
case GDT_Int32: format.glFormat = GL_R32I; break;
case GDT_Float32: format.glFormat = GL_R32F; break;
//case GDT_Float64: format.glFormat = GL_RED; break; // No representation of 64 bit float?
//case GDT_Float64: format.glFormat = GL_RED; break; // No representation of 64 bit float?
default: LERROR("GDAL data type unknown to OpenGL: " << gdalType);
}
break;
@@ -473,8 +473,8 @@ namespace openspace {
format.ghoulFormat = Texture::Format::RG;
switch (gdalType) {
case GDT_Byte: format.glFormat = GL_RG8; break;
case GDT_UInt16: format.glFormat = GL_RG16; break;
case GDT_Int16: format.glFormat = GL_RG16; break;
case GDT_UInt16: format.glFormat = GL_RG16UI; break;
case GDT_Int16: format.glFormat = GL_RG16_SNORM; break;
case GDT_UInt32: format.glFormat = GL_RG32UI; break;
case GDT_Int32: format.glFormat = GL_RG32I; break;
case GDT_Float32: format.glFormat = GL_RG32F; break;
@@ -486,8 +486,8 @@ namespace openspace {
format.ghoulFormat = Texture::Format::RGB;
switch (gdalType) {
case GDT_Byte: format.glFormat = GL_RGB8; break;
case GDT_UInt16: format.glFormat = GL_RGB16; break;
case GDT_Int16: format.glFormat = GL_RGB16; break;
case GDT_UInt16: format.glFormat = GL_RGB16UI; break;
case GDT_Int16: format.glFormat = GL_RGB16_SNORM; break;
case GDT_UInt32: format.glFormat = GL_RGB32UI; break;
case GDT_Int32: format.glFormat = GL_RGB32I; break;
case GDT_Float32: format.glFormat = GL_RGB32F; break;
@@ -499,8 +499,8 @@ namespace openspace {
format.ghoulFormat = Texture::Format::RGBA;
switch (gdalType) {
case GDT_Byte: format.glFormat = GL_RGBA8; break;
case GDT_UInt16: format.glFormat = GL_RGBA16; break;
case GDT_Int16: format.glFormat = GL_RGBA16; break;
case GDT_UInt16: format.glFormat = GL_RGBA16UI; break;
case GDT_Int16: format.glFormat = GL_RGB16_SNORM; break;
case GDT_UInt32: format.glFormat = GL_RGBA32UI; break;
case GDT_Int32: format.glFormat = GL_RGBA32I; break;
case GDT_Float32: format.glFormat = GL_RGBA32F; break;
-124
View File
@@ -51,130 +51,6 @@ 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::uvec2(1));
glm::vec2 samplePosFract = samplePos - glm::vec2(samplePos00);
glm::uvec2 samplePos10 = glm::min(samplePos00 + glm::uvec2(1, 0), dimensions.xy() - glm::uvec2(1));
glm::uvec2 samplePos01 = glm::min(samplePos00 + glm::uvec2(0, 1), dimensions.xy() - glm::uvec2(1));
glm::uvec2 samplePos11 = glm::min(samplePos00 + glm::uvec2(1, 1), dimensions.xy() - glm::uvec2(1));
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,
std::shared_ptr<TileCache> tileCache,
int framesUntilFlushRequestQueue)
@@ -59,8 +59,6 @@ namespace openspace {
enum class Status { Unavailable, OutOfRange, IOError, OK } status;
static const Tile TileUnavailable;
double sampleValueAsDouble(glm::vec2 uv, int band = 0);
};