ChunkNode merges its children facing away from the camera as much as possible without being visible to the camera. Test by enabling front face culling.

This commit is contained in:
Erik Broberg
2016-04-21 14:07:06 -04:00
parent f35cd4bb99
commit 3432605e7b
13 changed files with 462 additions and 16 deletions
+2
View File
@@ -44,6 +44,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.h
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/latlon.h
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/angle.h
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/lrucache.h
)
@@ -65,6 +66,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/latlon.cpp
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/angle.inl
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/lrucache.inl
)
@@ -39,6 +39,7 @@ namespace {
namespace openspace {
int ChunkNode::instanceCount = 0;
int ChunkNode::renderedPatches = 0;
ChunkNode::ChunkNode(ChunkLodGlobe& owner, const LatLonPatch& patch, ChunkNode* parent)
: _owner(owner)
@@ -83,6 +84,7 @@ bool ChunkNode::internalUpdateChunkTree(const RenderData& data, ChunkIndex& trav
if (isLeaf()) {
int desiredLevel = calculateDesiredLevel(data, traverseData);
desiredLevel = glm::clamp(desiredLevel, _owner.minSplitDepth, _owner.maxSplitDepth);
if (desiredLevel > traverseData.level) {
split();
}
@@ -117,8 +119,8 @@ bool ChunkNode::internalUpdateChunkTree(const RenderData& data, ChunkIndex& trav
void ChunkNode::internalRender(const RenderData& data, ChunkIndex& traverseData) {
if (isLeaf()) {
PatchRenderer& patchRenderer = _owner.getPatchRenderer();
patchRenderer.renderPatch(_patch, data, _owner.globeRadius);
ChunkNode::renderedPatches++;
}
else {
std::vector<ChunkIndex> childIndices = traverseData.childIndices();
@@ -131,8 +133,9 @@ void ChunkNode::internalRender(const RenderData& data, ChunkIndex& traverseData)
int ChunkNode::calculateDesiredLevel(const RenderData& data, const ChunkIndex& traverseData) {
Vec3 globePosition = data.position.dvec3();
Vec3 patchNormal = _patch.center().asUnitCartesian();
Vec3 patchPosition = data.position.dvec3() + _owner.globeRadius * patchNormal;
Vec3 patchPosition = globePosition + _owner.globeRadius * patchNormal;
Vec3 cameraPosition = data.camera.position().dvec3();
Vec3 cameraDirection = Vec3(data.camera.viewDirection());
@@ -141,8 +144,21 @@ int ChunkNode::calculateDesiredLevel(const RenderData& data, const ChunkIndex& t
// if camera points at same direction as latlon patch normal,
// we see the back side and dont have to split it
Scalar cosNormalCameraDirection = glm::dot(patchNormal, cameraDirection);
if (cosNormalCameraDirection > 0.3) {
//Scalar cosNormalCameraDirection = glm::dot(patchNormal, cameraDirection);
Vec3 globeToCamera = cameraPosition - globePosition;
LatLon cameraPositionOnGlobe = LatLon::fromCartesian(globeToCamera);
LatLon closestPatchPoint = _patch.closestPoint(cameraPositionOnGlobe);
Vec3 normalOfClosestPatchPoint = closestPatchPoint.asUnitCartesian();
Scalar cosPatchNormalNormalizedGlobeToCamera = glm::dot(normalOfClosestPatchPoint, glm::normalize(globeToCamera));
//LDEBUG(cosPatchNormalCameraDirection);
double cosAngleToHorizon = _owner.globeRadius / glm::length(globeToCamera);
if (cosPatchNormalNormalizedGlobeToCamera < cosAngleToHorizon) {
return traverseData.level - 1;
}
@@ -160,8 +176,8 @@ int ChunkNode::calculateDesiredLevel(const RenderData& data, const ChunkIndex& t
Scalar scaleFactor = 100 * _owner.globeRadius;
Scalar projectedScaleFactor = scaleFactor / distance;
int desiredDepth = floor( log2(projectedScaleFactor) );
return glm::clamp(desiredDepth, _owner.minSplitDepth, _owner.maxSplitDepth);
int desiredLevel = floor( log2(projectedScaleFactor) );
return desiredLevel;
}
@@ -84,6 +84,8 @@ public:
void render(const RenderData& data, ChunkIndex);
static int instanceCount;
static int renderedPatches;
private:
+145 -3
View File
@@ -26,6 +26,10 @@
#include <modules/globebrowsing/datastructures/chunknode.h>
#include <modules/globebrowsing/datastructures/latlon.h>
#include <modules/globebrowsing/datastructures/angle.h>
#define _USE_MATH_DEFINES
#include <math.h>
namespace {
const std::string _loggerCat = "LatLon";
@@ -71,10 +75,27 @@ namespace openspace {
return Vec2(lon, lat);
}
bool LatLon::operator==(const LatLon& other) {
bool LatLon::operator==(const LatLon& other) const {
return lat == other.lat && lon == other.lon;
}
LatLon LatLon ::operator+(const LatLon& other) const {
return LatLon(lat - other.lat, lon - other.lon);
}
LatLon LatLon ::operator-(const LatLon& other) const {
return LatLon(lat - other.lat, lon - other.lon);
}
LatLon LatLon::operator*(Scalar scalar) const {
return LatLon(lat * scalar, lon * scalar);
}
LatLon LatLon::operator/(Scalar scalar) const {
return LatLon(lat / scalar, lon / scalar);
}
//////////////////////////////////////////////////////////////////////////////////////////
// LATITUDE LONGITUDE PATCH //
//////////////////////////////////////////////////////////////////////////////////////////
@@ -133,8 +154,6 @@ namespace openspace {
return LatLon(2 * _halfSize.lat, 2 * _halfSize.lon);
}
LatLon LatLonPatch::northWestCorner() const{
return LatLon(_center.lat + _halfSize.lat, _center.lon - _halfSize.lon);
}
@@ -151,4 +170,127 @@ namespace openspace {
return LatLon(_center.lat - _halfSize.lat, _center.lon + _halfSize.lon);
}
LatLon LatLonPatch::clamp(const LatLon& p) const {
using Ang = Angle<Scalar>;
// Convert to Angles for normalization
Ang centerLat = Ang::fromRadians(_center.lat);
Ang centerLon = Ang::fromRadians(_center.lon);
Ang pointLat = Ang::fromRadians(p.lat);
Ang pointLon = Ang::fromRadians(p.lon);
// Normalize w.r.t. the center in order for the clamping to done correctly
//
// Example:
// centerLat = 0 deg, halfSize.lat = 10 deg, pointLat = 330 deg
// --> Just clamping pointLat would be clamp(330, -10, 10) = 10 // WRONG!
// Instead, if we first normalize 330 deg around 0, we get -30 deg
// --> clamp(-30, -10, 10) = -10 // CORRECT!
pointLat.normalizeAround(centerLat);
pointLon.normalizeAround(centerLon);
// get clamp bounds
LatLon max = northEastCorner();
LatLon min = southWestCorner();
return LatLon(
glm::clamp(pointLat.asRadians(), min.lat, max.lat),
glm::clamp(pointLon.asRadians(), min.lon, max.lon)
);
}
LatLon LatLonPatch::closestCorner(const LatLon& p) const {
using Ang = Angle<Scalar>;
// LatLon vector from patch center to the point
LatLon centerToPoint = p - _center;
// Normalize the difference angles to be centered around 0.
Ang latDiff = Ang::fromRadians(centerToPoint.lat).normalizeAround(Ang::ZERO);
Ang lonDiff = Ang::fromRadians(centerToPoint.lon).normalizeAround(Ang::ZERO);
// If latDiff > 0
// --> point p is north of the patch center
// --> the closest corner to the point must be a northern one
// --> set the corner's latitude coordinate to center.lat + halfSize.lat
// else
// --> set corner's latidude coordinate to center.lat - halfSize.lat
Scalar cornerLat = _center.lat + _halfSize.lat * (latDiff > Ang::ZERO ? 1 : -1);
// We then assigned the corner's longitude coordinate in a similar fashion
Scalar cornerLon = _center.lon + _halfSize.lon * (lonDiff > Ang::ZERO ? 1 : -1);
return LatLon(cornerLat, cornerLon);
}
LatLon LatLonPatch::closestPoint(const LatLon& p) const {
// This method finds the closest point on the patch, to the provided
// point p. As we are deali ng with latitude-longitude patches, distance in this
// context refers to great-circle distance.
// (https://en.wikipedia.org/wiki/Great-circle_distance)
//
// This uses a simple clamping approach to find the closest point on the
// patch. A naive castesian clamp is not sufficient for this purpose,
// as illustrated with an example below.
// Example: (degrees are used for latidude, longitude)
// patchCenter = (0,0), patchHalfSize = (45,45), point = (5, 170)
// Note, the point and the patch are on opposite sides of the sphere
//
// cartesian clamp:
// --> clampedPointLat = clamp(5, -45, 45) = 5
// --> clampedPointLon = clamp(170, -45, 45) = 45
// --> result: (5, 45)
// --> closest point is actually (45, 45)
// --> The error is significant
//
// This method simply adds an extra clamp on the latitude in these cases. In the
// above example, that would be the following:
// --> clampedPointLat = clamp(180 - 5, -45, 45) = 45
//
// Just doing this actually makes points returned from this methods being the
// true closest point, great-circle distance-wise.
using Ang = Angle<Scalar>;
// Convert to Angles for normalization
Ang centerLat = Ang::fromRadians(_center.lat);
Ang centerLon = Ang::fromRadians(_center.lon);
Ang pointLat = Ang::fromRadians(p.lat);
Ang pointLon = Ang::fromRadians(p.lon);
// Normalize point with respect to center. This is done because the point
// will later be clamped. See LatLonPatch::clamp(const LatLon&) for explanation
pointLat.normalizeAround(centerLat);
pointLon.normalizeAround(centerLon);
// Calculate the longitud difference between center and point. We normalize around
// zero because we want the "shortest distance" difference, i.e the difference
// should be in the interval [-180 deg, 180 deg]
Ang centerToPointLon = (centerLon - pointLon).normalizeAround(Ang::ZERO);
// Calculate the longitudinal distance to the closest patch edge
Ang longitudeDistanceToClosestPatchEdge = centerToPointLon.abs() - Ang::fromRadians(_halfSize.lon);
// get clamp bounds
LatLon max = northEastCorner();
LatLon min = southWestCorner();
// If the longitude distance to the closest patch edge is larger than 90 deg
// the latitude will have to be clamped to its closest corner, as explained in
// the example above.
Scalar clampedLat = longitudeDistanceToClosestPatchEdge > Ang::QUARTER ?
clampedLat = glm::clamp((Ang::HALF - pointLat).normalizeAround(centerLat).asRadians(), min.lat, max.lat) :
clampedLat = glm::clamp(pointLat.asRadians(), min.lat, max.lat);
// Longitude is just clamped normally
Scalar clampedLon = glm::clamp(pointLon.asRadians(), min.lon, max.lon);
return LatLon(clampedLat, clampedLon);
}
} // namespace openspace
+28 -2
View File
@@ -38,6 +38,10 @@ typedef glm::dvec3 Vec3;
namespace openspace {
struct LatLon {
LatLon();
LatLon(Scalar latitude, Scalar longitude);
@@ -47,8 +51,13 @@ struct LatLon {
Vec3 asUnitCartesian() const;
Vec2 toLonLatVec2() const;
inline bool operator==(const LatLon& other);
inline bool operator!=(const LatLon& other) { return !(*this == (other)); }
inline bool operator==(const LatLon& other) const;
inline bool operator!=(const LatLon& other) const { return !(*this == (other)); }
inline LatLon operator+(const LatLon& other) const;
inline LatLon operator-(const LatLon& other) const;
inline LatLon operator*(Scalar scalar) const;
inline LatLon operator/(Scalar scalar) const;
Scalar lat;
Scalar lon;
@@ -81,6 +90,23 @@ public:
LatLon southWestCorner() const;
LatLon southEastCorner() const;
/**
* Clamps a point to the patch region
*/
LatLon clamp(const LatLon& p) const;
/**
* Returns the corner of the patch that is closest to the given point p
*/
LatLon closestCorner(const LatLon& p) const;
/**
* Returns a point on the patch that minimizes the great-circle distance to
* the given point p.
*/
LatLon closestPoint(const LatLon& p) const;
const LatLon& center() const;
const LatLon& halfSize() const;
LatLon size() const;
@@ -120,6 +120,8 @@ namespace openspace {
void ChunkLodGlobe::render(const RenderData& data){
minDistToCamera = INFINITY;
ChunkNode::renderedPatches = 0;
ChunkIndex leftRootTileIndex = { 0, 0, 1 };
_leftRoot->render(data, leftRootTileIndex);
@@ -129,9 +131,10 @@ namespace openspace {
//LDEBUG("min distnace to camera: " << minDistToCamera);
Vec3 cameraPos = data.camera.position().dvec3();
LDEBUG("cam pos x: " << cameraPos.x << " y: " << cameraPos.y << " z: " << cameraPos.z);
//LDEBUG("cam pos x: " << cameraPos.x << " y: " << cameraPos.y << " z: " << cameraPos.z);
//LDEBUG("ChunkNode count: " << ChunkNode::instanceCount);
//LDEBUG("RenderedPatches count: " << ChunkNode::renderedPatches);
}
void ChunkLodGlobe::update(const UpdateData& data) {
@@ -168,8 +168,11 @@ void Geometry::drawUsingActiveProgram() {
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _elementBufferID);
//glEnable(GL_CULL_FACE);
//glCullFace(GL_FRONT);
glDrawElements(GL_TRIANGLES, _elementData.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//glCullFace(GL_BACK);
}
} // namespace openspace
@@ -58,5 +58,6 @@ void main()
vec3 p = globalInterpolation();
vec4 position = modelViewProjectionTransform * vec4(p, 1);
vs_position = vec4(p, 1);
gl_Position = z_normalization(position);
}
+3 -1
View File
@@ -49,7 +49,9 @@ Fragment getFragment() {
Fragment frag;
frag.color = texture2D(textureSampler, vec2(uvTransformPatchToTile * vec3(vs_uv.s, vs_uv.t, 1)));
frag.color = frag.color * 1.0 + vec4(fract(vs_uv * 1), 0.4,1) * 0.2;
frag.color = frag.color * 0.5 + vec4(fract(vs_uv * 1), 0.4,1) * 0.5;
frag.color = 0.5*frag.color + 0.5 * vec4(1)* (abs(vs_position.y) < 10000 ? 1 : 0) ;
frag.color.a = 1;
frag.depth = pscDepth(vs_position);
return frag;
+3 -2
View File
@@ -35,10 +35,11 @@
//#include <test_scenegraphloader.inl>
//#include <test_chunknode.inl>
//#include <test_lrucache.inl>
#include <test_twmstileprovider.inl>
//#include <test_twmstileprovider.inl>
//#include <test_luaconversions.inl>
//#include <test_powerscalecoordinates.inl>
//#include <test_latlonpatch.inl>
#include <test_angle.inl>
#include <test_latlonpatch.inl>
//#include <test_texturetileset.inl>
#include <openspace/engine/openspaceengine.h>
+119
View File
@@ -0,0 +1,119 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "gtest/gtest.h"
#include <openspace/scene/scenegraphnode.h>
#include <openspace/../modules/globebrowsing/datastructures/angle.h>
#include <fstream>
#include <glm/glm.hpp>
using namespace openspace;
class AngleTest : public testing::Test {};
TEST_F(AngleTest, DoubleConversions) {
ASSERT_EQ(dAngle::fromRadians(0).asDegrees(), 0) << "from radians to degrees";
ASSERT_EQ(dAngle::HALF.asDegrees(), 180) << "from radians to degrees";
ASSERT_EQ(dAngle::fromDegrees(180).asRadians(), dAngle::PI) << "from degrees to radians";
}
TEST_F(AngleTest, FloatConversions) {
ASSERT_EQ(fAngle::ZERO.asDegrees(), 0.0) << "from radians to degrees";
ASSERT_EQ(fAngle::HALF.asDegrees(), 180.0) << "from radians to degrees";
ASSERT_EQ(fAngle::fromDegrees(180).asRadians(), fAngle::PI) << "from degrees to radians";
}
TEST_F(AngleTest, Normalize) {
ASSERT_NEAR(
dAngle::fromDegrees(390).normalize().asDegrees(),
30.0,
dAngle::EPSILON
) << "normalize to [0, 360]";
dAngle a = dAngle::fromDegrees(190);
a.normalizeAround(dAngle::ZERO);
ASSERT_NEAR(
a.asDegrees(),
-170,
dAngle::EPSILON
) << "normalize to [-180,180]";
dAngle b = dAngle::fromDegrees(190);
b.normalizeAround(dAngle::fromDegrees(90));
ASSERT_NEAR(
b.asDegrees(),
190,
dAngle::EPSILON
) << "normalize to [-90,270]";
dAngle c = dAngle::fromDegrees(360);
c.normalizeAround(dAngle::fromDegrees(1083.2));
ASSERT_NEAR(
c.asDegrees(),
1080,
dAngle::EPSILON
) << "normalize to [903.2, 1263.2]";
}
TEST_F(AngleTest, Clamp) {
ASSERT_EQ(
dAngle::fromDegrees(390).clamp(dAngle::ZERO, dAngle::HALF).asDegrees(),
180,
) << "clamp [0, 180]";
ASSERT_EQ(
dAngle::fromDegrees(390).clamp(dAngle::ZERO, dAngle::FULL).asDegrees(),
360,
) << "clamp [0, 360]";
}
TEST_F(AngleTest, ConstClamp) {
const dAngle a = dAngle::fromDegrees(390);
ASSERT_EQ(
a.getClamped(dAngle::ZERO, dAngle::HALF).asDegrees(),
180,
) << "clamp [0, 180]";
const dAngle b = dAngle::fromDegrees(390);
ASSERT_EQ(
b.getClamped(dAngle::ZERO, dAngle::FULL).asDegrees(),
360,
) << "clamp [0, 360]";
}
+128
View File
@@ -39,3 +39,131 @@ TEST_F(LatLonPatchTest, findCenterControlPoint) {
LatLonPatch patch(0, 0, M_PI / 4, M_PI / 4);
}
TEST_F(LatLonPatchTest, TestFindClosestCorner) {
Scalar piOver4 = M_PI / 4;
LatLon halfSize(piOver4, piOver4);
LatLon center(0, 0);
LatLonPatch patch(center, halfSize);
Scalar piOver3 = M_PI / 3;
LatLon point(piOver3, piOver3);
LatLon closestCorner = patch.closestCorner(point);
LatLon northEastCorner = patch.northEastCorner();
ASSERT_EQ(closestCorner.lat, northEastCorner.lat);
ASSERT_EQ(closestCorner.lon, northEastCorner.lon);
}
TEST_F(LatLonPatchTest, TestFindClosestCorner2) {
Scalar piOver6 = M_PI / 4;
Scalar piOver3 = M_PI / 3;
LatLon halfSize(1.1*piOver6, 1.1*piOver6);
LatLon center(piOver6, piOver6);
LatLonPatch patch(center, halfSize);
LatLon point(0, 0);
LatLon closestCorner = patch.closestCorner(point);
LatLon expectedCorner = patch.southWestCorner();
ASSERT_EQ(closestCorner.lat, expectedCorner.lat);
ASSERT_EQ(closestCorner.lon, expectedCorner.lon);
}
TEST_F(LatLonPatchTest, TestSphericalClamp1) {
LatLonPatch patch(0, 0, M_PI / 4, M_PI / 4);
// inside patch latitude-wise, east of patch longitude-wise
LatLon point(M_PI / 6, M_PI - 0.01);
LatLon clampedPoint = patch.closestPoint(point);
LatLon neCorner = patch.northEastCorner();
ASSERT_EQ(clampedPoint.lat, neCorner.lat);
ASSERT_EQ(clampedPoint.lon, neCorner.lon);
}
TEST_F(LatLonPatchTest, TestSphericalClamp2) {
LatLonPatch patch(0, 0, M_PI / 4, M_PI / 4);
// inside patch latitude-wise, west of patch longitude-wise
LatLon point(M_PI / 6, M_PI + 0.01);
LatLon clampedPoint = patch.closestPoint(point);
LatLon nwCorner = patch.northWestCorner();
ASSERT_EQ(clampedPoint.lat, nwCorner.lat);
ASSERT_EQ(clampedPoint.lon, nwCorner.lon);
}
TEST_F(LatLonPatchTest, TestSphericalClamp3) {
LatLonPatch patch(0, 0, M_PI / 4, M_PI / 4);
// North east of patch
LatLon point(M_PI / 3, M_PI - 0.01);
LatLon clampedPoint = patch.closestPoint(point);
LatLon neCorner = patch.northEastCorner();
ASSERT_EQ(clampedPoint.lat, neCorner.lat);
ASSERT_EQ(clampedPoint.lon, neCorner.lon);
}
TEST_F(LatLonPatchTest, TestSphericalClamp4) {
LatLonPatch patch(0, 0, M_PI / 4, M_PI / 4);
// South east of patch
LatLon point(-M_PI / 3, M_PI - 0.01);
LatLon clampedPoint = patch.closestPoint(point);
LatLon seCorner = patch.southEastCorner();
ASSERT_EQ(clampedPoint.lat, seCorner.lat);
ASSERT_EQ(clampedPoint.lon, seCorner.lon);
}
TEST_F(LatLonPatchTest, TestSphericalClamp5) {
LatLonPatch patch(0, 0, M_PI / 4, M_PI / 4);
// South west of patch
LatLon point(-M_PI / 3, 3*M_PI + 0.01);
LatLon clampedPoint = patch.closestPoint(point);
LatLon swCorner = patch.southWestCorner();
ASSERT_EQ(clampedPoint.lat, swCorner.lat);
ASSERT_EQ(clampedPoint.lon, swCorner.lon);
}
int radAsDeg(double rads) {
return floorf(Angle<Scalar>::fromRadians(rads).asDegrees());
}
TEST_F(LatLonPatchTest, PrintingSphericalClamp) {
LatLonPatch patch(0, 0, M_PI / 4, M_PI / 4);
using Ang = Angle<Scalar>;
Ang delta = Ang::fromDegrees(30);
std::cout << "point lat, lon --> clamped lat, lon" << std::endl;
for (Ang lat = Ang::fromDegrees(90); lat > -Ang::QUARTER; lat -= delta) {
for (Ang lon = Ang::fromDegrees(180); lon > -Ang::HALF; lon -= delta) {
LatLon point(lat.asRadians(), lon.asRadians());
LatLon clamped = patch.closestPoint(point);
std::cout
<< radAsDeg(point.lat) << ", "
<< radAsDeg(point.lon) << " --> "
<< radAsDeg(clamped.lat) << ", "
<< radAsDeg(clamped.lon) << std::endl;
}
std::cout << std::endl;
}
}
+2 -1
View File
@@ -37,6 +37,7 @@ using namespace openspace;
TEST_F(TWMSTileProviderTest, Simple) {
/*
TwmsTileProvider tileProvider;
TileIndex tileIndex = { 0, 0, 0 };
@@ -46,5 +47,5 @@ TEST_F(TWMSTileProviderTest, Simple) {
std::this_thread::sleep_for(2s);
std::cout << "exiting" << std::endl;
*/
}