mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-25 05:48:59 -05:00
Commented code to test tile loading with concurrent job manager. Texture Loader does not allow multithreading
This commit is contained in:
@@ -28,135 +28,140 @@
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "Ellipsoid";
|
||||
const std::string _loggerCat = "Ellipsoid";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Ellipsoid::Ellipsoid(Vec3 radii)
|
||||
: _radii(radii)
|
||||
, _cachedValues({
|
||||
Vec3( // _radiiSquared
|
||||
(_radii.x * _radii.x),
|
||||
(_radii.y * _radii.y),
|
||||
(_radii.z * _radii.z)),
|
||||
Vec3( // _oneOverRadiiSquared
|
||||
1.0 / (_radii.x * _radii.x),
|
||||
1.0 / (_radii.y * _radii.y),
|
||||
1.0 / (_radii.z * _radii.z)),
|
||||
Vec3( // _radiiToTheFourth
|
||||
_radii.x * _radii.x * _radii.x * _radii.x,
|
||||
_radii.y * _radii.y * _radii.y * _radii.y,
|
||||
_radii.z * _radii.z * _radii.z * _radii.z),
|
||||
glm::min(_radii.x, glm::min(_radii.y, _radii.z))})
|
||||
{
|
||||
const Ellipsoid Ellipsoid::UnitSphere = Ellipsoid(1, 1, 1);
|
||||
|
||||
}
|
||||
const Ellipsoid Ellipsoid::WGS84 = Ellipsoid(6378137.0, 6378137.0, 6356752.314245);
|
||||
|
||||
Ellipsoid::Ellipsoid(Scalar x, Scalar y, Scalar z)
|
||||
: Ellipsoid(Vec3(x, y, z))
|
||||
{
|
||||
|
||||
}
|
||||
Ellipsoid::Ellipsoid(Vec3 radii)
|
||||
: _radii(radii)
|
||||
, _cachedValues({
|
||||
Vec3( // _radiiSquared
|
||||
(_radii.x * _radii.x),
|
||||
(_radii.y * _radii.y),
|
||||
(_radii.z * _radii.z)),
|
||||
Vec3( // _oneOverRadiiSquared
|
||||
1.0 / (_radii.x * _radii.x),
|
||||
1.0 / (_radii.y * _radii.y),
|
||||
1.0 / (_radii.z * _radii.z)),
|
||||
Vec3( // _radiiToTheFourth
|
||||
_radii.x * _radii.x * _radii.x * _radii.x,
|
||||
_radii.y * _radii.y * _radii.y * _radii.y,
|
||||
_radii.z * _radii.z * _radii.z * _radii.z),
|
||||
glm::min(_radii.x, glm::min(_radii.y, _radii.z))})
|
||||
{
|
||||
|
||||
Ellipsoid::~Ellipsoid()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
Ellipsoid::Ellipsoid(Scalar x, Scalar y, Scalar z)
|
||||
: Ellipsoid(Vec3(x, y, z))
|
||||
{
|
||||
|
||||
Vec3 Ellipsoid::scaleToGeocentricSurface(const Vec3& p) const
|
||||
{
|
||||
Scalar beta = 1.0 / sqrt(dot(p * p, _cachedValues._oneOverRadiiSquared));
|
||||
return beta * p;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::scaleToGeodeticSurface(const Vec3& p) const
|
||||
{
|
||||
Scalar beta = 1.0 / sqrt(dot(p * p, _cachedValues._oneOverRadiiSquared));
|
||||
Scalar n = glm::length(beta * p * _cachedValues._oneOverRadiiSquared);
|
||||
Scalar alpha = (1.0 - beta) * (glm::length(p) / n);
|
||||
|
||||
Vec3 p2 = p * p;
|
||||
Vec3 d, d2, d3;
|
||||
Ellipsoid::~Ellipsoid()
|
||||
{
|
||||
|
||||
Scalar s = 0.0;
|
||||
Scalar dSdA = 1.0;
|
||||
}
|
||||
|
||||
Scalar epsilon = 1e-10;
|
||||
do {
|
||||
alpha -= (s / dSdA);
|
||||
Vec3 Ellipsoid::scaleToGeocentricSurface(const Vec3& p) const
|
||||
{
|
||||
Scalar beta = 1.0 / sqrt(dot(p * p, _cachedValues._oneOverRadiiSquared));
|
||||
return beta * p;
|
||||
}
|
||||
|
||||
d = Vec3(1.0) + alpha * _cachedValues._oneOverRadiiSquared;
|
||||
d2 = d * d;
|
||||
d3 = d * d2;
|
||||
|
||||
s = glm::dot(p2 / (_cachedValues._radiiSquared * d2), Vec3(1.0)) - 1.0;
|
||||
Vec3 Ellipsoid::scaleToGeodeticSurface(const Vec3& p) const
|
||||
{
|
||||
Scalar beta = 1.0 / sqrt(dot(p * p, _cachedValues._oneOverRadiiSquared));
|
||||
Scalar n = glm::length(beta * p * _cachedValues._oneOverRadiiSquared);
|
||||
Scalar alpha = (1.0 - beta) * (glm::length(p) / n);
|
||||
|
||||
Vec3 p2 = p * p;
|
||||
Vec3 d, d2, d3;
|
||||
|
||||
dSdA = -2.0 * glm::dot(p2 / (_cachedValues._radiiToTheFourth * d3), Vec3(1.0));
|
||||
}
|
||||
while (abs(s) > epsilon);
|
||||
return p / d;
|
||||
}
|
||||
Scalar s = 0.0;
|
||||
Scalar dSdA = 1.0;
|
||||
|
||||
Vec3 Ellipsoid::geodeticSurfaceNormal(const Vec3& p) const
|
||||
{
|
||||
Vec3 normal = p * _cachedValues._oneOverRadiiSquared;
|
||||
return glm::normalize(normal);
|
||||
}
|
||||
Scalar epsilon = 1e-10;
|
||||
do {
|
||||
alpha -= (s / dSdA);
|
||||
|
||||
Vec3 Ellipsoid::geodeticSurfaceNormal(Geodetic2 geodetic2) const
|
||||
{
|
||||
Scalar cosLat = glm::cos(geodetic2.lat);
|
||||
//geodetic2.lon = geodetic2.lon > M_PI ? geodetic2.lon - M_PI * 2 : geodetic2.lon;
|
||||
return Vec3(
|
||||
cosLat * cos(geodetic2.lon),
|
||||
cosLat * sin(geodetic2.lon),
|
||||
sin(geodetic2.lat));
|
||||
}
|
||||
d = Vec3(1.0) + alpha * _cachedValues._oneOverRadiiSquared;
|
||||
d2 = d * d;
|
||||
d3 = d * d2;
|
||||
|
||||
s = glm::dot(p2 / (_cachedValues._radiiSquared * d2), Vec3(1.0)) - 1.0;
|
||||
|
||||
// TODO: IMPLEMENT THESE FUNCTIONS AND SEND RADIISQUARED TO THE SHADER PROGRAM
|
||||
dSdA = -2.0 * glm::dot(p2 / (_cachedValues._radiiToTheFourth * d3), Vec3(1.0));
|
||||
}
|
||||
while (abs(s) > epsilon);
|
||||
return p / d;
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::radiiSquared() const
|
||||
{
|
||||
return _cachedValues._radiiSquared;
|
||||
}
|
||||
Vec3 Ellipsoid::geodeticSurfaceNormal(const Vec3& p) const
|
||||
{
|
||||
Vec3 normal = p * _cachedValues._oneOverRadiiSquared;
|
||||
return glm::normalize(normal);
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::oneOverRadiiSquared() const
|
||||
{
|
||||
return _cachedValues._oneOverRadiiSquared;
|
||||
}
|
||||
Vec3 Ellipsoid::geodeticSurfaceNormal(Geodetic2 geodetic2) const
|
||||
{
|
||||
Scalar cosLat = glm::cos(geodetic2.lat);
|
||||
//geodetic2.lon = geodetic2.lon > M_PI ? geodetic2.lon - M_PI * 2 : geodetic2.lon;
|
||||
return Vec3(
|
||||
cosLat * cos(geodetic2.lon),
|
||||
cosLat * sin(geodetic2.lon),
|
||||
sin(geodetic2.lat));
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::radiiToTheFourth() const
|
||||
{
|
||||
return _cachedValues._radiiToTheFourth;
|
||||
}
|
||||
// TODO: IMPLEMENT THESE FUNCTIONS AND SEND RADIISQUARED TO THE SHADER PROGRAM
|
||||
|
||||
Scalar Ellipsoid::minimumRadius() const
|
||||
{
|
||||
return _cachedValues._minimumRadius;
|
||||
}
|
||||
Vec3 Ellipsoid::radiiSquared() const
|
||||
{
|
||||
return _cachedValues._radiiSquared;
|
||||
}
|
||||
|
||||
Geodetic2 Ellipsoid::cartesianToGeodetic2(const Vec3& p) const
|
||||
{
|
||||
Vec3 normal = geodeticSurfaceNormal(p);
|
||||
return Geodetic2(
|
||||
asin(normal.z / length(normal)), // Latitude
|
||||
atan2(normal.y, normal.x)); // Longitude
|
||||
}
|
||||
Vec3 Ellipsoid::oneOverRadiiSquared() const
|
||||
{
|
||||
return _cachedValues._oneOverRadiiSquared;
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::geodetic2ToCartesian(const Geodetic2& geodetic2) const
|
||||
{
|
||||
// Position on surface : height = 0
|
||||
return geodetic3ToCartesian(Geodetic3({ geodetic2, 0 }));
|
||||
}
|
||||
Vec3 Ellipsoid::radiiToTheFourth() const
|
||||
{
|
||||
return _cachedValues._radiiToTheFourth;
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::geodetic3ToCartesian(const Geodetic3& geodetic3) const
|
||||
{
|
||||
Vec3 normal = geodeticSurfaceNormal(geodetic3.geodetic2);
|
||||
Vec3 k = _cachedValues._radiiSquared * normal;
|
||||
Scalar gamma = sqrt(dot(k, normal));
|
||||
Vec3 rSurface = k / gamma;
|
||||
return rSurface + geodetic3.height * normal;
|
||||
}
|
||||
Scalar Ellipsoid::minimumRadius() const
|
||||
{
|
||||
return _cachedValues._minimumRadius;
|
||||
}
|
||||
|
||||
Geodetic2 Ellipsoid::cartesianToGeodetic2(const Vec3& p) const
|
||||
{
|
||||
Vec3 normal = geodeticSurfaceNormal(p);
|
||||
return Geodetic2(
|
||||
asin(normal.z / length(normal)), // Latitude
|
||||
atan2(normal.y, normal.x)); // Longitude
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::geodetic2ToCartesian(const Geodetic2& geodetic2) const
|
||||
{
|
||||
// Position on surface : height = 0
|
||||
return geodetic3ToCartesian(Geodetic3({ geodetic2, 0 }));
|
||||
}
|
||||
|
||||
Vec3 Ellipsoid::geodetic3ToCartesian(const Geodetic3& geodetic3) const
|
||||
{
|
||||
Vec3 normal = geodeticSurfaceNormal(geodetic3.geodetic2);
|
||||
Vec3 k = _cachedValues._radiiSquared * normal;
|
||||
Scalar gamma = sqrt(dot(k, normal));
|
||||
Vec3 rSurface = k / gamma;
|
||||
return rSurface + geodetic3.height * normal;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -29,67 +29,80 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
/**
|
||||
This class is based largely on the Ellipsoid class defined in the book
|
||||
"3D Engine Design for Virtual Globes". Most planets or planetary objects are better
|
||||
described using ellipsoids than spheres. All inputs and outputs to this class is
|
||||
in the WGS84 standard coordinate system where the x-axis points towards geographic
|
||||
(lat = 0, lon = 0), the y-axis points towards (lat = 0, lon = 90deg) and the
|
||||
z-axis points towards the north pole.
|
||||
*/
|
||||
/**
|
||||
This class is based largely on the Ellipsoid class defined in the book
|
||||
"3D Engine Design for Virtual Globes". Most planets or planetary objects are better
|
||||
described using ellipsoids than spheres. All inputs and outputs to this class is
|
||||
in the WGS84 standard coordinate system where the x-axis points towards geographic
|
||||
(lat = 0, lon = 0), the y-axis points towards (lat = 0, lon = 90deg) and the
|
||||
z-axis points towards the north pole.
|
||||
*/
|
||||
class Ellipsoid {
|
||||
public:
|
||||
/**
|
||||
\param radii defines three radii for the Ellipsoid
|
||||
*/
|
||||
Ellipsoid(Vec3 radii);
|
||||
|
||||
/**
|
||||
\param x defines the radius in x direction.
|
||||
\param y defines the radius in y direction.
|
||||
\param z defines the radius in z direction.
|
||||
*/
|
||||
Ellipsoid(Scalar x, Scalar y, Scalar z);
|
||||
~Ellipsoid();
|
||||
|
||||
/**
|
||||
Scales a point along the geocentric normal and places it on the surface of the
|
||||
Ellipsoid.
|
||||
\param p is a point in the cartesian coordinate system to be placed on the surface
|
||||
of the Ellipsoid
|
||||
*/
|
||||
Vec3 scaleToGeocentricSurface(const Vec3& p) const;
|
||||
/**
|
||||
Scales a point along the geodetic normal and places it on the surface of the
|
||||
Ellipsoid.
|
||||
\param p is a point in the cartesian coordinate system to be placed on the surface
|
||||
of the Ellipsoid
|
||||
*/
|
||||
Vec3 scaleToGeodeticSurface(const Vec3& p) const;
|
||||
/**
|
||||
World Geodetic System 1984 coordinate system
|
||||
*/
|
||||
static const Ellipsoid WGS84;
|
||||
|
||||
Vec3 geodeticSurfaceNormal(const Vec3& p) const;
|
||||
Vec3 geodeticSurfaceNormal(Geodetic2 geodetic2) const;
|
||||
|
||||
Vec3 radiiSquared() const;
|
||||
Vec3 oneOverRadiiSquared() const;
|
||||
Vec3 radiiToTheFourth() const;
|
||||
Scalar minimumRadius() const;
|
||||
static const Ellipsoid UnitSphere;
|
||||
|
||||
Geodetic2 cartesianToGeodetic2(const Vec3& p) const;
|
||||
Vec3 geodetic2ToCartesian(const Geodetic2& geodetic2) const;
|
||||
Vec3 geodetic3ToCartesian(const Geodetic3& geodetic3) const;
|
||||
|
||||
/**
|
||||
\param radii defines three radii for the Ellipsoid
|
||||
*/
|
||||
Ellipsoid(Vec3 radii);
|
||||
|
||||
|
||||
/**
|
||||
\param x defines the radius in x direction.
|
||||
\param y defines the radius in y direction.
|
||||
\param z defines the radius in z direction.
|
||||
*/
|
||||
Ellipsoid(Scalar x, Scalar y, Scalar z);
|
||||
~Ellipsoid();
|
||||
|
||||
|
||||
/**
|
||||
Scales a point along the geocentric normal and places it on the surface of the
|
||||
Ellipsoid.
|
||||
\param p is a point in the cartesian coordinate system to be placed on the surface
|
||||
of the Ellipsoid
|
||||
*/
|
||||
Vec3 scaleToGeocentricSurface(const Vec3& p) const;
|
||||
|
||||
|
||||
/**
|
||||
Scales a point along the geodetic normal and places it on the surface of the
|
||||
Ellipsoid.
|
||||
\param p is a point in the cartesian coordinate system to be placed on the surface
|
||||
of the Ellipsoid
|
||||
*/
|
||||
Vec3 scaleToGeodeticSurface(const Vec3& p) const;
|
||||
|
||||
Vec3 geodeticSurfaceNormal(const Vec3& p) const;
|
||||
Vec3 geodeticSurfaceNormal(Geodetic2 geodetic2) const;
|
||||
|
||||
Vec3 radiiSquared() const;
|
||||
Vec3 oneOverRadiiSquared() const;
|
||||
Vec3 radiiToTheFourth() const;
|
||||
Scalar minimumRadius() const;
|
||||
|
||||
Geodetic2 cartesianToGeodetic2(const Vec3& p) const;
|
||||
Vec3 geodetic2ToCartesian(const Geodetic2& geodetic2) const;
|
||||
Vec3 geodetic3ToCartesian(const Geodetic3& geodetic3) const;
|
||||
|
||||
private:
|
||||
struct EllipsoidCache
|
||||
{
|
||||
const Vec3 _radiiSquared;
|
||||
const Vec3 _oneOverRadiiSquared;
|
||||
const Vec3 _radiiToTheFourth;
|
||||
const Scalar _minimumRadius;
|
||||
};
|
||||
struct EllipsoidCache
|
||||
{
|
||||
const Vec3 _radiiSquared;
|
||||
const Vec3 _oneOverRadiiSquared;
|
||||
const Vec3 _radiiToTheFourth;
|
||||
const Scalar _minimumRadius;
|
||||
};
|
||||
|
||||
const Vec3 _radii;
|
||||
const EllipsoidCache _cachedValues;
|
||||
const Vec3 _radii;
|
||||
const EllipsoidCache _cachedValues;
|
||||
};
|
||||
} // namespace openspace
|
||||
|
||||
|
||||
@@ -39,120 +39,124 @@
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "ChunkLodGlobe";
|
||||
const std::string _loggerCat = "ChunkLodGlobe";
|
||||
|
||||
const std::string keyFrame = "Frame";
|
||||
const std::string keyGeometry = "Geometry";
|
||||
const std::string keyShading = "PerformShading";
|
||||
const std::string keyFrame = "Frame";
|
||||
const std::string keyGeometry = "Geometry";
|
||||
const std::string keyShading = "PerformShading";
|
||||
|
||||
const std::string keyBody = "Body";
|
||||
const std::string keyBody = "Body";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
const GeodeticPatch ChunkLodGlobe::LEFT_HEMISPHERE = GeodeticPatch(0, -M_PI/2, M_PI/2, M_PI/2);
|
||||
const GeodeticPatch ChunkLodGlobe::RIGHT_HEMISPHERE = GeodeticPatch(0, M_PI/2, M_PI/2, M_PI/2);
|
||||
const GeodeticPatch ChunkLodGlobe::LEFT_HEMISPHERE = GeodeticPatch(0, -M_PI/2, M_PI/2, M_PI/2);
|
||||
const GeodeticPatch ChunkLodGlobe::RIGHT_HEMISPHERE = GeodeticPatch(0, M_PI/2, M_PI/2, M_PI/2);
|
||||
|
||||
|
||||
ChunkLodGlobe::ChunkLodGlobe(
|
||||
const ghoul::Dictionary& dictionary,
|
||||
const Ellipsoid& ellipsoid)
|
||||
: _ellipsoid(ellipsoid)
|
||||
, _leftRoot(new ChunkNode(*this, LEFT_HEMISPHERE))
|
||||
, _rightRoot(new ChunkNode(*this, RIGHT_HEMISPHERE))
|
||||
, minSplitDepth(2)
|
||||
, maxSplitDepth(22)
|
||||
, _rotation("rotation", "Rotation", 0, 0, 360)
|
||||
|
||||
{
|
||||
std::string name;
|
||||
bool success = dictionary.getValue(SceneGraphNode::KeyName, name);
|
||||
//ghoul_assert(success, "ChunkLodGlobe need the '" << SceneGraphNode::KeyName << "' be specified");
|
||||
setName(name);
|
||||
ChunkLodGlobe::ChunkLodGlobe(
|
||||
const ghoul::Dictionary& dictionary,
|
||||
const Ellipsoid& ellipsoid)
|
||||
: _ellipsoid(ellipsoid)
|
||||
, _leftRoot(new ChunkNode(*this, LEFT_HEMISPHERE))
|
||||
, _rightRoot(new ChunkNode(*this, RIGHT_HEMISPHERE))
|
||||
, minSplitDepth(2)
|
||||
, maxSplitDepth(22)
|
||||
, _rotation("rotation", "Rotation", 0, 0, 360)
|
||||
|
||||
{
|
||||
std::string name;
|
||||
bool success = dictionary.getValue(SceneGraphNode::KeyName, name);
|
||||
//ghoul_assert(success, "ChunkLodGlobe need the '" << SceneGraphNode::KeyName << "' be specified");
|
||||
setName(name);
|
||||
|
||||
dictionary.getValue(keyFrame, _frame);
|
||||
dictionary.getValue(keyBody, _target);
|
||||
if (_target != "")
|
||||
setBody(_target);
|
||||
dictionary.getValue(keyFrame, _frame);
|
||||
dictionary.getValue(keyBody, _target);
|
||||
if (_target != "")
|
||||
setBody(_target);
|
||||
|
||||
// Mainly for debugging purposes @AA
|
||||
addProperty(_rotation);
|
||||
// Mainly for debugging purposes @AA
|
||||
addProperty(_rotation);
|
||||
|
||||
|
||||
//globeRadius = dictionary.value<double>("Radius");
|
||||
|
||||
//globeRadius = dictionary.value<double>("Radius");
|
||||
|
||||
|
||||
// ---------
|
||||
// init Renderer
|
||||
auto geometry = std::shared_ptr<BasicGrid>(new BasicGrid(
|
||||
10,
|
||||
10,
|
||||
TriangleSoup::Positions::No,
|
||||
TriangleSoup::TextureCoordinates::Yes,
|
||||
TriangleSoup::Normals::No));
|
||||
// ---------
|
||||
// init Renderer
|
||||
auto geometry = std::shared_ptr<BasicGrid>(new BasicGrid(
|
||||
10,
|
||||
10,
|
||||
TriangleSoup::Positions::No,
|
||||
TriangleSoup::TextureCoordinates::Yes,
|
||||
TriangleSoup::Normals::No));
|
||||
|
||||
|
||||
_patchRenderer.reset(new LatLonPatchRenderer(geometry));
|
||||
_patchRenderer.reset(new LatLonPatchRenderer(geometry));
|
||||
|
||||
_frustumCuller = std::shared_ptr<FrustumCuller>(new FrustumCuller());
|
||||
_frustumCuller = std::shared_ptr<FrustumCuller>(new FrustumCuller());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ChunkLodGlobe::~ChunkLodGlobe() {
|
||||
ChunkLodGlobe::~ChunkLodGlobe() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool ChunkLodGlobe::initialize() {
|
||||
return isReady();
|
||||
}
|
||||
bool ChunkLodGlobe::initialize() {
|
||||
return isReady();
|
||||
}
|
||||
|
||||
bool ChunkLodGlobe::deinitialize() {
|
||||
return true;
|
||||
}
|
||||
bool ChunkLodGlobe::deinitialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChunkLodGlobe::isReady() const {
|
||||
bool ready = true;
|
||||
return ready;
|
||||
}
|
||||
bool ChunkLodGlobe::isReady() const {
|
||||
bool ready = true;
|
||||
return ready;
|
||||
}
|
||||
|
||||
LatLonPatchRenderer& ChunkLodGlobe::getPatchRenderer() {
|
||||
return *_patchRenderer;
|
||||
}
|
||||
LatLonPatchRenderer& ChunkLodGlobe::getPatchRenderer() {
|
||||
return *_patchRenderer;
|
||||
}
|
||||
|
||||
FrustumCuller& ChunkLodGlobe::getFrustumCuller() {
|
||||
return *_frustumCuller;
|
||||
}
|
||||
FrustumCuller& ChunkLodGlobe::getFrustumCuller() {
|
||||
return *_frustumCuller;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ChunkLodGlobe::render(const RenderData& data){
|
||||
minDistToCamera = INFINITY;
|
||||
ChunkNode::renderedPatches = 0;
|
||||
void ChunkLodGlobe::render(const RenderData& data){
|
||||
minDistToCamera = INFINITY;
|
||||
ChunkNode::renderedPatches = 0;
|
||||
|
||||
ChunkIndex leftRootTileIndex = { 0, 0, 1 };
|
||||
_leftRoot->render(data, leftRootTileIndex);
|
||||
|
||||
ChunkIndex rightRootTileIndex = { 1, 0, 1 };
|
||||
_rightRoot->render(data, rightRootTileIndex);
|
||||
ChunkIndex leftRootTileIndex = { 0, 0, 1 };
|
||||
_leftRoot->render(data, leftRootTileIndex);
|
||||
|
||||
//LDEBUG("min distnace to camera: " << minDistToCamera);
|
||||
ChunkIndex rightRootTileIndex = { 1, 0, 1 };
|
||||
_rightRoot->render(data, rightRootTileIndex);
|
||||
|
||||
Vec3 cameraPos = data.camera.position().dvec3();
|
||||
//LDEBUG("cam pos x: " << cameraPos.x << " y: " << cameraPos.y << " z: " << cameraPos.z);
|
||||
//LDEBUG("min distnace to camera: " << minDistToCamera);
|
||||
|
||||
//LDEBUG("ChunkNode count: " << ChunkNode::instanceCount);
|
||||
//LDEBUG("RenderedPatches count: " << ChunkNode::renderedPatches);
|
||||
}
|
||||
Vec3 cameraPos = data.camera.position().dvec3();
|
||||
//LDEBUG("cam pos x: " << cameraPos.x << " y: " << cameraPos.y << " z: " << cameraPos.z);
|
||||
|
||||
void ChunkLodGlobe::update(const UpdateData& data) {
|
||||
// set spice-orientation in accordance to timestamp
|
||||
_stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time);
|
||||
_time = data.time;
|
||||
}
|
||||
//LDEBUG("ChunkNode count: " << ChunkNode::instanceCount);
|
||||
//LDEBUG("RenderedPatches count: " << ChunkNode::renderedPatches);
|
||||
}
|
||||
|
||||
const Ellipsoid& ChunkLodGlobe::ellipsoid() const
|
||||
{
|
||||
return _ellipsoid;
|
||||
}
|
||||
void ChunkLodGlobe::update(const UpdateData& data) {
|
||||
|
||||
// set spice-orientation in accordance to timestamp
|
||||
_stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time);
|
||||
_time = data.time;
|
||||
|
||||
_patchRenderer->update();
|
||||
}
|
||||
|
||||
const Ellipsoid& ChunkLodGlobe::ellipsoid() const
|
||||
{
|
||||
return _ellipsoid;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -137,13 +137,13 @@ void ChunkNode::internalRender(const RenderData& data, ChunkIndex& traverseData)
|
||||
}
|
||||
|
||||
int ChunkNode::calculateDesiredLevelAndUpdateIsVisible(
|
||||
const RenderData& data,
|
||||
const ChunkIndex& traverseData) {
|
||||
const RenderData& data,
|
||||
const ChunkIndex& traverseData) {
|
||||
_isVisible = true;
|
||||
Vec3 globePosition = data.position.dvec3();
|
||||
Vec3 patchPosition =
|
||||
globePosition +
|
||||
_owner.ellipsoid().geodetic2ToCartesian(_patch.center());
|
||||
Vec3 patchPosition =
|
||||
globePosition +
|
||||
_owner.ellipsoid().geodetic2ToCartesian(_patch.center());
|
||||
|
||||
Vec3 cameraPosition = data.camera.position().dvec3();
|
||||
Vec3 cameraDirection = Vec3(data.camera.viewDirection());
|
||||
@@ -156,23 +156,23 @@ int ChunkNode::calculateDesiredLevelAndUpdateIsVisible(
|
||||
|
||||
Vec3 globeToCamera = cameraPosition - globePosition;
|
||||
|
||||
Geodetic2 cameraPositionOnGlobe =
|
||||
_owner.ellipsoid().cartesianToGeodetic2(globeToCamera);
|
||||
Geodetic2 closestPatchPoint = _patch.closestPoint(cameraPositionOnGlobe);
|
||||
Geodetic2 cameraPositionOnGlobe =
|
||||
_owner.ellipsoid().cartesianToGeodetic2(globeToCamera);
|
||||
Geodetic2 closestPatchPoint = _patch.closestPoint(cameraPositionOnGlobe);
|
||||
|
||||
Vec3 normalOfClosestPatchPoint =
|
||||
_owner.ellipsoid().geodeticSurfaceNormal(closestPatchPoint);
|
||||
Scalar cosPatchNormalNormalizedGlobeToCamera =
|
||||
glm::dot(normalOfClosestPatchPoint, glm::normalize(globeToCamera));
|
||||
Vec3 normalOfClosestPatchPoint =
|
||||
_owner.ellipsoid().geodeticSurfaceNormal(closestPatchPoint);
|
||||
Scalar cosPatchNormalNormalizedGlobeToCamera =
|
||||
glm::dot(normalOfClosestPatchPoint, glm::normalize(globeToCamera));
|
||||
|
||||
//LDEBUG(cosPatchNormalCameraDirection);
|
||||
|
||||
// Get the minimum radius from the ellipsoid. The closer the ellipsoid is to a
|
||||
// sphere, the better this will make the splitting. Using the minimum radius to
|
||||
// be safe. This means that if the ellipsoid has high difference between radii,
|
||||
// splitting might accur even though it is not needed.
|
||||
Scalar minimumGlobeRadius = _owner.ellipsoid().minimumRadius();
|
||||
double cosAngleToHorizon = minimumGlobeRadius / glm::length(globeToCamera);
|
||||
// Get the minimum radius from the ellipsoid. The closer the ellipsoid is to a
|
||||
// sphere, the better this will make the splitting. Using the minimum radius to
|
||||
// be safe. This means that if the ellipsoid has high difference between radii,
|
||||
// splitting might accur even though it is not needed.
|
||||
Scalar minimumGlobeRadius = _owner.ellipsoid().minimumRadius();
|
||||
double cosAngleToHorizon = minimumGlobeRadius / glm::length(globeToCamera);
|
||||
if (cosPatchNormalNormalizedGlobeToCamera < cosAngleToHorizon) {
|
||||
_isVisible = false;
|
||||
return traverseData.level - 1;
|
||||
@@ -181,20 +181,20 @@ int ChunkNode::calculateDesiredLevelAndUpdateIsVisible(
|
||||
// Do frustrum culling
|
||||
FrustumCuller& culler = _owner.getFrustumCuller();
|
||||
|
||||
if (!culler.isVisible(data, _patch, _owner.ellipsoid())) {
|
||||
_isVisible = false;
|
||||
return traverseData.level - 1;
|
||||
}
|
||||
if (!culler.isVisible(data, _patch, _owner.ellipsoid())) {
|
||||
_isVisible = false;
|
||||
return traverseData.level - 1;
|
||||
}
|
||||
|
||||
|
||||
// Calculate desired level based on distance
|
||||
Scalar distance = glm::length(cameraToChunk);
|
||||
_owner.minDistToCamera = fmin(_owner.minDistToCamera, distance);
|
||||
|
||||
Scalar scaleFactor = 100 * minimumGlobeRadius;
|
||||
Scalar projectedScaleFactor = scaleFactor / distance;
|
||||
int desiredLevel = floor( log2(projectedScaleFactor) );
|
||||
return desiredLevel;
|
||||
Scalar scaleFactor = 100 * minimumGlobeRadius;
|
||||
Scalar projectedScaleFactor = scaleFactor / distance;
|
||||
int desiredLevel = floor( log2(projectedScaleFactor) );
|
||||
return desiredLevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ namespace openspace {
|
||||
virtual ~Job() { }
|
||||
|
||||
virtual void execute() = 0;
|
||||
virtual P product() = 0;
|
||||
|
||||
virtual std::shared_ptr<P> product() = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -35,31 +35,32 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
// Templated class implementing a Least-Recently-Used Cache
|
||||
template<typename KeyType, typename ValueType>
|
||||
class LRUCache {
|
||||
public:
|
||||
LRUCache(size_t size);
|
||||
~LRUCache();
|
||||
// Templated class implementing a Least-Recently-Used Cache
|
||||
template<typename KeyType, typename ValueType>
|
||||
class LRUCache {
|
||||
public:
|
||||
LRUCache(size_t size);
|
||||
~LRUCache();
|
||||
|
||||
|
||||
void put(const KeyType& key, const ValueType& value);
|
||||
bool exist(const KeyType& key) const;
|
||||
ValueType get(const KeyType& key);
|
||||
void put(const KeyType& key, const ValueType& value);
|
||||
bool exist(const KeyType& key) const;
|
||||
ValueType get(const KeyType& key);
|
||||
size_t size() const;
|
||||
|
||||
|
||||
private:
|
||||
void clean();
|
||||
private:
|
||||
void clean();
|
||||
|
||||
|
||||
// Member varialbes
|
||||
private:
|
||||
|
||||
std::list<std::pair<KeyType, ValueType>> _itemList;
|
||||
std::unordered_map<KeyType, decltype(_itemList.begin())> _itemMap;
|
||||
size_t _cacheSize;
|
||||
// Member varialbes
|
||||
private:
|
||||
|
||||
std::list<std::pair<KeyType, ValueType>> _itemList;
|
||||
std::unordered_map<KeyType, decltype(_itemList.begin())> _itemMap;
|
||||
size_t _cacheSize;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -32,66 +32,72 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
LRUCache<KeyType, ValueType>::LRUCache(size_t size)
|
||||
: _cacheSize(size) { }
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
LRUCache<KeyType, ValueType>::LRUCache(size_t size)
|
||||
: _cacheSize(size) { }
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
LRUCache<KeyType, ValueType>::~LRUCache() {
|
||||
// Clean up list and map!
|
||||
}
|
||||
template<typename KeyType, typename ValueType>
|
||||
LRUCache<KeyType, ValueType>::~LRUCache() {
|
||||
// Clean up list and map!
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
// PUBLIC INTERFACE //
|
||||
//////////////////////////////
|
||||
//////////////////////////////
|
||||
// PUBLIC INTERFACE //
|
||||
//////////////////////////////
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
void LRUCache<KeyType, ValueType>::put(const KeyType& key, const ValueType& value)
|
||||
{
|
||||
auto it = _itemMap.find(key);
|
||||
if (it != _itemMap.end()) {
|
||||
_itemList.erase(it->second);
|
||||
_itemMap.erase(it);
|
||||
}
|
||||
_itemList.push_front(std::make_pair(key, value));
|
||||
_itemMap.insert(std::make_pair(key, _itemList.begin()));
|
||||
clean();
|
||||
}
|
||||
template<typename KeyType, typename ValueType>
|
||||
void LRUCache<KeyType, ValueType>::put(const KeyType& key, const ValueType& value)
|
||||
{
|
||||
auto it = _itemMap.find(key);
|
||||
if (it != _itemMap.end()) {
|
||||
_itemList.erase(it->second);
|
||||
_itemMap.erase(it);
|
||||
}
|
||||
_itemList.push_front(std::make_pair(key, value));
|
||||
_itemMap.insert(std::make_pair(key, _itemList.begin()));
|
||||
clean();
|
||||
}
|
||||
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
bool LRUCache<KeyType, ValueType>::exist(const KeyType& key) const
|
||||
{
|
||||
return _itemMap.count(key) > 0;
|
||||
}
|
||||
template<typename KeyType, typename ValueType>
|
||||
bool LRUCache<KeyType, ValueType>::exist(const KeyType& key) const
|
||||
{
|
||||
return _itemMap.count(key) > 0;
|
||||
}
|
||||
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
ValueType LRUCache<KeyType, ValueType>::get(const KeyType& key)
|
||||
{
|
||||
ghoul_assert(exist(key), "Key " << key << " must exist");
|
||||
auto it = _itemMap.find(key);
|
||||
// Move list iterator pointing to value
|
||||
_itemList.splice(_itemList.begin(), _itemList, it->second);
|
||||
return it->second->second;
|
||||
}
|
||||
template<typename KeyType, typename ValueType>
|
||||
ValueType LRUCache<KeyType, ValueType>::get(const KeyType& key)
|
||||
{
|
||||
ghoul_assert(exist(key), "Key " << key << " must exist");
|
||||
auto it = _itemMap.find(key);
|
||||
// Move list iterator pointing to value
|
||||
_itemList.splice(_itemList.begin(), _itemList, it->second);
|
||||
return it->second->second;
|
||||
}
|
||||
|
||||
template<typename KeyType, typename ValueType>
|
||||
size_t LRUCache<KeyType, ValueType>::size() const
|
||||
{
|
||||
return _itemMap.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
// PRIVATE HELPERS //
|
||||
//////////////////////////////
|
||||
template<typename KeyType, typename ValueType>
|
||||
void LRUCache<KeyType, ValueType>::clean()
|
||||
{
|
||||
while (_itemMap.size() > _cacheSize) {
|
||||
auto last_it = _itemList.end(); last_it--;
|
||||
_itemMap.erase(last_it->first);
|
||||
_itemList.pop_back();
|
||||
}
|
||||
}
|
||||
//////////////////////////////
|
||||
// PRIVATE HELPERS //
|
||||
//////////////////////////////
|
||||
template<typename KeyType, typename ValueType>
|
||||
void LRUCache<KeyType, ValueType>::clean()
|
||||
{
|
||||
while (_itemMap.size() > _cacheSize) {
|
||||
auto last_it = _itemList.end(); last_it--;
|
||||
_itemMap.erase(last_it->first);
|
||||
_itemList.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -37,124 +37,149 @@
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TwmsTileProvider";
|
||||
const std::string _loggerCat = "TwmsTileProvider";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
TwmsTileProvider::TwmsTileProvider()
|
||||
: _tileCache(5000) // setting cache size
|
||||
, _fileFutureCache(5000) // setting cache size
|
||||
{
|
||||
int downloadApplicationVersion = 1;
|
||||
if (!DownloadManager::isInitialized()) {
|
||||
DownloadManager::initialize("../tmp_openspace_downloads/", downloadApplicationVersion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TwmsTileProvider::~TwmsTileProvider(){
|
||||
TwmsTileProvider::TwmsTileProvider()
|
||||
: _tileCache(5000) // setting cache size
|
||||
//, _fileFutureCache(5000) // setting cache size
|
||||
{
|
||||
int downloadApplicationVersion = 1;
|
||||
if (!DownloadManager::isInitialized()) {
|
||||
DownloadManager::initialize("../tmp_openspace_downloads/", downloadApplicationVersion);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
TwmsTileProvider::~TwmsTileProvider(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Texture> TwmsTileProvider::getTile(const TileIndex& tileIndex) {
|
||||
HashKey hashkey = tileIndex.hashKey();
|
||||
if (_tileCache.exist(hashkey)) {
|
||||
return _tileCache.get(hashkey);
|
||||
}
|
||||
else if (_fileFutureCache.exist(hashkey)) {
|
||||
if (_fileFutureCache.get(hashkey)->isFinished) {
|
||||
std::string fileName = _fileFutureCache.get(hashkey)->filePath;
|
||||
std::string filePath = "tiles/" + fileName;
|
||||
std::shared_ptr<Texture> texture = loadAndInitTextureDisk(filePath);
|
||||
//LDEBUG("Downloaded " << fileName);
|
||||
_tileCache.put(hashkey, texture);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::shared_ptr<DownloadManager::FileFuture> fileFuture = requestTile(tileIndex);
|
||||
_fileFutureCache.put(hashkey, fileFuture);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void TwmsTileProvider::prerender() {
|
||||
|
||||
std::shared_ptr<Texture> TwmsTileProvider::loadAndInitTextureDisk(std::string filePath) {
|
||||
auto textureReader = ghoul::io::TextureReader::ref();
|
||||
std::shared_ptr<Texture> texture = std::move(textureReader.loadTexture(absPath(filePath)));
|
||||
// Remove filefutures that are inactive
|
||||
auto it = _fileFutureMap.begin();
|
||||
auto end = _fileFutureMap.end();
|
||||
for (; it != end;){
|
||||
|
||||
if (it->second->isAborted ||
|
||||
it->second->secondsRemaining > 20 ||
|
||||
it->second->errorMessage.compare("") != 0 ||
|
||||
it->second->isFinished)
|
||||
{
|
||||
it = _fileFutureMap.erase(it);
|
||||
//LDEBUG("removnig filefuture");
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// upload to gpu
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
texture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToEdge);
|
||||
return texture;
|
||||
}
|
||||
|
||||
// Move finished texture tiles to cache
|
||||
while (_concurrentJobManager.numFinishedJobs() > 0) {
|
||||
auto finishedJob = _concurrentJobManager.popFinishedJob();
|
||||
|
||||
TextureLoadJob* finishedTextureLoadJob = reinterpret_cast<TextureLoadJob*>(finishedJob.get());
|
||||
|
||||
ghoul_assert(finishedTextureLoadJob != nullptr, "unable to reinterpret cast to TextureLoadJob*");
|
||||
|
||||
auto texture = finishedTextureLoadJob->product();
|
||||
// upload to gpu
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
texture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToEdge);
|
||||
|
||||
//LDEBUG("uploaded texture " << finishedTextureLoadJob->hashKey());
|
||||
HashKey hashkey = finishedTextureLoadJob->hashKey();
|
||||
_tileCache.put(hashkey, texture);
|
||||
_fileFutureMap.erase(hashkey);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Texture> TwmsTileProvider::getTile(const TileIndex& tileIndex) {
|
||||
HashKey hashkey = tileIndex.hashKey();
|
||||
|
||||
if (_tileCache.exist(hashkey)) {
|
||||
return _tileCache.get(hashkey);
|
||||
}
|
||||
else if (_fileFutureMap.find(hashkey) != _fileFutureMap.end()) {
|
||||
if (_fileFutureMap.find(hashkey)->second->isFinished) {
|
||||
|
||||
std::string fileName = _fileFutureMap.find(hashkey)->second->filePath;
|
||||
std::string filePath = "tiles/" + fileName;
|
||||
|
||||
std::shared_ptr<Texture> texture = loadAndInitTextureDisk(filePath);
|
||||
_tileCache.put(hashkey, texture);
|
||||
_fileFutureMap.erase(hashkey);
|
||||
|
||||
//LDEBUG("Downloaded " << fileName);
|
||||
|
||||
|
||||
//auto job = std::shared_ptr<TextureLoadJob>(new TextureLoadJob(filePath, hashkey));
|
||||
//_concurrentJobManager.enqueueJob(job);
|
||||
}
|
||||
}
|
||||
else if(_fileFutureMap.size() < 50){
|
||||
|
||||
std::shared_ptr<DownloadManager::FileFuture> fileFuture = requestTile(tileIndex);
|
||||
_fileFutureMap.insert_or_assign(hashkey, fileFuture);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> TwmsTileProvider::loadAndInitTextureDisk(std::string filePath) {
|
||||
auto textureReader = ghoul::io::TextureReader::ref();
|
||||
std::shared_ptr<Texture> texture = std::move(textureReader.loadTexture(absPath(filePath)));
|
||||
|
||||
// upload to gpu
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
texture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToEdge);
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<DownloadManager::FileFuture> TwmsTileProvider::requestTile(const TileIndex& tileIndex) {
|
||||
// download tile
|
||||
std::stringstream ss;
|
||||
//std::string baseUrl = "https://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi?TIME=2016-04-17&layer=MODIS_Terra_CorrectedReflectance_TrueColor&tilematrixset=EPSG4326_250m&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fjpeg";
|
||||
//ss << baseUrl;
|
||||
//ss << "&TileMatrix=" << tileIndex.level;
|
||||
//ss << "&TileCol=" << tileIndex.x;
|
||||
//ss << "&TileRow=" << tileIndex.y;
|
||||
// https://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi?TIME=2016-04-17&layer=MODIS_Terra_CorrectedReflectance_TrueColor&tilematrixset=EPSG4326_250m&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fjpeg&TileMatrix=0&TileCol=0&TileRow=0
|
||||
std::shared_ptr<DownloadManager::FileFuture> TwmsTileProvider::requestTile(const TileIndex& tileIndex) {
|
||||
// download tile
|
||||
std::stringstream ss;
|
||||
//std::string baseUrl = "https://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi?TIME=2016-04-17&layer=MODIS_Terra_CorrectedReflectance_TrueColor&tilematrixset=EPSG4326_250m&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fjpeg";
|
||||
//ss << baseUrl;
|
||||
//ss << "&TileMatrix=" << tileIndex.level;
|
||||
//ss << "&TileCol=" << tileIndex.x;
|
||||
//ss << "&TileRow=" << tileIndex.y;
|
||||
// https://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi?TIME=2016-04-17&layer=MODIS_Terra_CorrectedReflectance_TrueColor&tilematrixset=EPSG4326_250m&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fjpeg&TileMatrix=0&TileCol=0&TileRow=0
|
||||
|
||||
std::string baseUrl = "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913";
|
||||
ss << baseUrl;
|
||||
ss << "/" << tileIndex.level;
|
||||
ss << "/" << tileIndex.x;
|
||||
ss << "/" << tileIndex.y;
|
||||
ss << ".png?1461277159335";
|
||||
// http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/5/8/12.png?
|
||||
std::string twmsRequestUrl = ss.str();
|
||||
|
||||
ss = std::stringstream();
|
||||
ss << tileIndex.level;
|
||||
ss << "_" << tileIndex.x;
|
||||
ss << "_" << tileIndex.y;
|
||||
std::string filePath = "tiles/tile" + ss.str() + ".png";
|
||||
std::string baseUrl = "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913";
|
||||
ss << baseUrl;
|
||||
ss << "/" << tileIndex.level;
|
||||
ss << "/" << tileIndex.x;
|
||||
ss << "/" << tileIndex.y;
|
||||
ss << ".png?1461277159335";
|
||||
// http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/5/8/12.png?
|
||||
std::string twmsRequestUrl = ss.str();
|
||||
|
||||
ss = std::stringstream();
|
||||
ss << tileIndex.level;
|
||||
ss << "_" << tileIndex.x;
|
||||
ss << "_" << tileIndex.y;
|
||||
std::string filePath = "tiles/tile" + ss.str() + ".png";
|
||||
|
||||
using ghoul::filesystem::File;
|
||||
File localTileFile(filePath);
|
||||
bool overrideFile = true;
|
||||
using ghoul::filesystem::File;
|
||||
File localTileFile(filePath);
|
||||
bool overrideFile = true;
|
||||
|
||||
std::shared_ptr<DownloadManager::FileFuture> fileFuture = DownloadManager::ref().downloadFile(twmsRequestUrl, localTileFile, overrideFile);
|
||||
return fileFuture;
|
||||
|
||||
/*
|
||||
struct OnTileDownloaded {
|
||||
HashKey key;
|
||||
LRUCache<HashKey, std::shared_ptr<Texture>> * tileCache;
|
||||
|
||||
OnTileDownloaded(HashKey key, LRUCache<HashKey, std::shared_ptr<Texture>> * tileCache)
|
||||
: key(key)
|
||||
, tileCache(tileCache)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void operator()(const DownloadManager::FileFuture& ff) const {
|
||||
//LDEBUG("Download of tile with hashkey " << key << " done!");
|
||||
auto textureReader = ghoul::io::TextureReader::ref();
|
||||
std::string relFilePath = "tiles/" + ff.filePath;
|
||||
std::shared_ptr<Texture> texture = std::move(textureReader.loadTexture(absPath(relFilePath)));
|
||||
|
||||
// upload to gpu
|
||||
texture->uploadTexture();
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
|
||||
tileCache->put(key, texture);
|
||||
LDEBUG("Cache updated");
|
||||
}
|
||||
};
|
||||
OnTileDownloaded onTileDownloaded(tileIndex.hashKey(), &_tileCache);
|
||||
*/
|
||||
|
||||
std::shared_ptr<DownloadManager::FileFuture> fileFuture = DownloadManager::ref().downloadFile(twmsRequestUrl, localTileFile, overrideFile);
|
||||
return fileFuture;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -26,9 +26,13 @@
|
||||
#define __TWMS_TILE_PROVIDER_H__
|
||||
|
||||
#include <modules/globebrowsing/other/lrucache.h>
|
||||
#include <modules/globebrowsing/other/concurrentjobmanager.h>
|
||||
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h> // absPath
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
|
||||
#include <openspace/engine/downloadmanager.h>
|
||||
|
||||
@@ -39,15 +43,52 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace openspace {
|
||||
using HashKey = unsigned long;
|
||||
using HashKey = unsigned long;
|
||||
|
||||
struct TileIndex {
|
||||
int x, y, level;
|
||||
struct TileIndex {
|
||||
int x, y, level;
|
||||
|
||||
HashKey hashKey() const {
|
||||
return x ^ (y << 16) ^ (level << 21);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
struct TextureLoadJob : public Job<Texture> {
|
||||
TextureLoadJob(const std::string& filePath, HashKey hashkey)
|
||||
: _filePath(filePath)
|
||||
, _hashkey(hashkey){
|
||||
|
||||
}
|
||||
|
||||
virtual ~TextureLoadJob() { }
|
||||
|
||||
virtual void execute() {
|
||||
|
||||
auto textureReader = ghoul::io::TextureReader::ref();
|
||||
_texture = std::move(textureReader.loadTexture(absPath(_filePath)));
|
||||
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<Texture> product() {
|
||||
return _texture;
|
||||
}
|
||||
|
||||
HashKey hashKey() { return _hashkey; }
|
||||
|
||||
|
||||
private:
|
||||
std::string _filePath;
|
||||
HashKey _hashkey;
|
||||
std::shared_ptr<Texture> _texture;
|
||||
};
|
||||
|
||||
|
||||
HashKey hashKey() const {
|
||||
return x ^ (y << 16) ^ (level << 21);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -57,24 +98,29 @@ namespace openspace {
|
||||
|
||||
|
||||
namespace openspace {
|
||||
using namespace ghoul::opengl;
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
class TwmsTileProvider
|
||||
{
|
||||
public:
|
||||
TwmsTileProvider();
|
||||
~TwmsTileProvider();
|
||||
class TwmsTileProvider
|
||||
{
|
||||
public:
|
||||
TwmsTileProvider();
|
||||
~TwmsTileProvider();
|
||||
|
||||
std::shared_ptr<Texture> getTile(const TileIndex& tileIndex);
|
||||
std::shared_ptr<Texture> getTile(const TileIndex& tileIndex);
|
||||
|
||||
void prerender();
|
||||
|
||||
|
||||
private:
|
||||
std::shared_ptr<DownloadManager::FileFuture> requestTile(const TileIndex&);
|
||||
std::shared_ptr<Texture> loadAndInitTextureDisk(std::string filePath);
|
||||
private:
|
||||
std::shared_ptr<DownloadManager::FileFuture> requestTile(const TileIndex&);
|
||||
std::shared_ptr<Texture> loadAndInitTextureDisk(std::string filePath);
|
||||
|
||||
LRUCache<HashKey, std::shared_ptr<Texture>> _tileCache;
|
||||
LRUCache<HashKey, std::shared_ptr<DownloadManager::FileFuture>> _fileFutureCache;
|
||||
};
|
||||
LRUCache<HashKey, std::shared_ptr<Texture>> _tileCache;
|
||||
std::unordered_map<HashKey, std::shared_ptr<DownloadManager::FileFuture>> _fileFutureMap;
|
||||
//LRUCache<HashKey, std::shared_ptr<DownloadManager::FileFuture>> _fileFutureCache;
|
||||
|
||||
ConcurrentJobManager<Texture> _concurrentJobManager;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
|
||||
@@ -41,217 +41,221 @@
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "PatchRenderer";
|
||||
const std::string _loggerCat = "PatchRenderer";
|
||||
|
||||
const std::string keyFrame = "Frame";
|
||||
const std::string keyGeometry = "Geometry";
|
||||
const std::string keyShading = "PerformShading";
|
||||
const std::string keyFrame = "Frame";
|
||||
const std::string keyGeometry = "Geometry";
|
||||
const std::string keyShading = "PerformShading";
|
||||
|
||||
const std::string keyBody = "Body";
|
||||
const std::string keyBody = "Body";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
PatchRenderer::PatchRenderer()
|
||||
: _tileSet(Geodetic2(M_PI, M_PI * 2), Geodetic2(M_PI / 2, -M_PI), 0)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
PatchRenderer::PatchRenderer()
|
||||
: _tileSet(Geodetic2(M_PI, M_PI * 2), Geodetic2(M_PI / 2, -M_PI), 0)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PatchRenderer::~PatchRenderer() {
|
||||
if (_programObject) {
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
renderEngine.removeRenderProgram(_programObject);
|
||||
_programObject = nullptr;
|
||||
}
|
||||
}
|
||||
PatchRenderer::~PatchRenderer() {
|
||||
if (_programObject) {
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
renderEngine.removeRenderProgram(_programObject);
|
||||
_programObject = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// LATLON PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
LatLonPatchRenderer::LatLonPatchRenderer(shared_ptr<Grid> grid)
|
||||
: PatchRenderer()
|
||||
, _grid(grid)
|
||||
{
|
||||
_programObject = OsEng.renderEngine().buildRenderProgram(
|
||||
"LatLonSphereMappingProgram",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/latlonpatch_spheremapping_vs.glsl",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/simple_fs.glsl");
|
||||
ghoul_assert(_programObject != nullptr, "Failed to initialize programObject!");
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// LATLON PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
LatLonPatchRenderer::LatLonPatchRenderer(shared_ptr<Grid> grid)
|
||||
: PatchRenderer()
|
||||
, _grid(grid)
|
||||
{
|
||||
_programObject = OsEng.renderEngine().buildRenderProgram(
|
||||
"LatLonSphereMappingProgram",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/latlonpatch_spheremapping_vs.glsl",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/simple_fs.glsl");
|
||||
ghoul_assert(_programObject != nullptr, "Failed to initialize programObject!");
|
||||
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
void LatLonPatchRenderer::renderPatch(
|
||||
const GeodeticPatch& patch, const RenderData& data, const Ellipsoid& ellipsoid)
|
||||
{
|
||||
|
||||
// Get the textures that should be used for rendering
|
||||
TileIndex ti = _tileSet.getTileIndex(patch);
|
||||
void LatLonPatchRenderer::update() {
|
||||
tileProvider.prerender();
|
||||
}
|
||||
|
||||
renderPatch(patch, data, ellipsoid, ti);
|
||||
}
|
||||
void LatLonPatchRenderer::renderPatch(
|
||||
const GeodeticPatch& patch, const RenderData& data, const Ellipsoid& ellipsoid)
|
||||
{
|
||||
|
||||
// Get the textures that should be used for rendering
|
||||
TileIndex ti = _tileSet.getTileIndex(patch);
|
||||
|
||||
void LatLonPatchRenderer::renderPatch(
|
||||
const GeodeticPatch& patch,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid,
|
||||
const TileIndex& tileIndex)
|
||||
{
|
||||
renderPatch(patch, data, ellipsoid, ti);
|
||||
}
|
||||
|
||||
using namespace glm;
|
||||
void LatLonPatchRenderer::renderPatch(
|
||||
const GeodeticPatch& patch,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid,
|
||||
const TileIndex& tileIndex)
|
||||
{
|
||||
|
||||
using namespace glm;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO : Model transform should be fetched as a matrix directly.
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
mat4 viewTransform = data.camera.combinedViewMatrix();
|
||||
mat4 modelViewProjectionTransform = data.camera.projectionMatrix()
|
||||
* viewTransform * modelTransform;
|
||||
// TODO : Model transform should be fetched as a matrix directly.
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
mat4 viewTransform = data.camera.combinedViewMatrix();
|
||||
mat4 modelViewProjectionTransform = data.camera.projectionMatrix()
|
||||
* viewTransform * modelTransform;
|
||||
|
||||
|
||||
// activate shader
|
||||
_programObject->activate();
|
||||
// activate shader
|
||||
_programObject->activate();
|
||||
|
||||
// Get the textures that should be used for rendering
|
||||
std::shared_ptr<ghoul::opengl::Texture> tile00;
|
||||
bool usingTile = true;
|
||||
TileIndex ti;
|
||||
ti.level =tileIndex.level;
|
||||
ti.x = tileIndex.y;
|
||||
ti.y = tileIndex.x;
|
||||
tile00 = tileProvider.getTile(ti);
|
||||
// Get the textures that should be used for rendering
|
||||
std::shared_ptr<ghoul::opengl::Texture> tile00;
|
||||
bool usingTile = true;
|
||||
TileIndex ti;
|
||||
ti.level =tileIndex.level;
|
||||
ti.x = tileIndex.y;
|
||||
ti.y = tileIndex.x;
|
||||
tile00 = tileProvider.getTile(ti);
|
||||
|
||||
if (tile00 == nullptr) {
|
||||
tile00 = _tileSet.getTile(tileIndex);
|
||||
usingTile = false;
|
||||
}
|
||||
if (tile00 == nullptr) {
|
||||
tile00 = _tileSet.getTile(tileIndex);
|
||||
usingTile = false;
|
||||
}
|
||||
|
||||
glm::mat3 uvTransform = usingTile ? glm::mat3(1) : _tileSet.getUvTransformationPatchToTile(patch, tileIndex);
|
||||
glm::mat3 uvTransform = usingTile ? glm::mat3(1) : _tileSet.getUvTransformationPatchToTile(patch, tileIndex);
|
||||
|
||||
// Bind and use the texture
|
||||
ghoul::opengl::TextureUnit texUnit;
|
||||
texUnit.activate();
|
||||
tile00->bind();
|
||||
_programObject->setUniform("textureSampler", texUnit);
|
||||
_programObject->setUniform("uvTransformPatchToTile", uvTransform);
|
||||
// Bind and use the texture
|
||||
ghoul::opengl::TextureUnit texUnit;
|
||||
texUnit.activate();
|
||||
tile00->bind();
|
||||
_programObject->setUniform("textureSampler", texUnit);
|
||||
_programObject->setUniform("uvTransformPatchToTile", uvTransform);
|
||||
|
||||
Geodetic2 swCorner = patch.southWestCorner();
|
||||
_programObject->setUniform("segmentsPerPatch", _grid->xSegments());
|
||||
_programObject->setUniform("modelViewProjectionTransform", modelViewProjectionTransform);
|
||||
_programObject->setUniform("minLatLon", vec2(swCorner.toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", vec2(patch.size().toLonLatVec2()));
|
||||
_programObject->setUniform("radiiSquared", vec3(ellipsoid.radiiSquared()));
|
||||
Geodetic2 swCorner = patch.southWestCorner();
|
||||
_programObject->setUniform("segmentsPerPatch", _grid->xSegments());
|
||||
_programObject->setUniform("modelViewProjectionTransform", modelViewProjectionTransform);
|
||||
_programObject->setUniform("minLatLon", vec2(swCorner.toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", vec2(patch.size().toLonLatVec2()));
|
||||
_programObject->setUniform("radiiSquared", vec3(ellipsoid.radiiSquared()));
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// render
|
||||
_grid->geometry().drawUsingActiveProgram();
|
||||
// render
|
||||
_grid->geometry().drawUsingActiveProgram();
|
||||
|
||||
// disable shader
|
||||
_programObject->deactivate();
|
||||
}
|
||||
|
||||
// disable shader
|
||||
_programObject->deactivate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// CLIPMAP PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
ClipMapPatchRenderer::ClipMapPatchRenderer(shared_ptr<ClipMapGrid> grid)
|
||||
: PatchRenderer()
|
||||
, _grid(grid)
|
||||
{
|
||||
_programObject = OsEng.renderEngine().buildRenderProgram(
|
||||
"LatLonSphereMappingProgram",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/clipmappatch_spheremapping_vs.glsl",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/simple_fs.glsl");
|
||||
ghoul_assert(_programObject != nullptr, "Failed to initialize programObject!");
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// CLIPMAP PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
ClipMapPatchRenderer::ClipMapPatchRenderer(shared_ptr<ClipMapGrid> grid)
|
||||
: PatchRenderer()
|
||||
, _grid(grid)
|
||||
{
|
||||
_programObject = OsEng.renderEngine().buildRenderProgram(
|
||||
"LatLonSphereMappingProgram",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/clipmappatch_spheremapping_vs.glsl",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/simple_fs.glsl");
|
||||
ghoul_assert(_programObject != nullptr, "Failed to initialize programObject!");
|
||||
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
void ClipMapPatchRenderer::renderPatch(
|
||||
const Geodetic2& patchSize,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid)
|
||||
{
|
||||
// activate shader
|
||||
_programObject->activate();
|
||||
using namespace glm;
|
||||
void ClipMapPatchRenderer::renderPatch(
|
||||
const Geodetic2& patchSize,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid)
|
||||
{
|
||||
// activate shader
|
||||
_programObject->activate();
|
||||
using namespace glm;
|
||||
|
||||
mat4 viewTransform = data.camera.combinedViewMatrix();
|
||||
mat4 viewTransform = data.camera.combinedViewMatrix();
|
||||
|
||||
// TODO : Model transform should be fetched as a matrix directly.
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
// TODO : Model transform should be fetched as a matrix directly.
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
|
||||
// Snap patch position
|
||||
int segmentsPerPatch = _grid->segments();
|
||||
Geodetic2 stepSize = Geodetic2(
|
||||
patchSize.lat / segmentsPerPatch,
|
||||
patchSize.lon / segmentsPerPatch);
|
||||
ivec2 patchesToCoverGlobe = ivec2(
|
||||
M_PI / patchSize.lat + 0.5,
|
||||
M_PI * 2 / patchSize.lon + 0.5);
|
||||
Geodetic2 cameraPosLatLon = ellipsoid.cartesianToGeodetic2(data.camera.position().dvec3());
|
||||
ivec2 intSnapCoord = ivec2(
|
||||
cameraPosLatLon.lat / (M_PI * 2) * segmentsPerPatch * patchesToCoverGlobe.y,
|
||||
cameraPosLatLon.lon / (M_PI) * segmentsPerPatch * patchesToCoverGlobe.x);
|
||||
Geodetic2 newPatchCenter = Geodetic2(
|
||||
stepSize.lat * intSnapCoord.x,
|
||||
stepSize.lon * intSnapCoord.y);
|
||||
GeodeticPatch newPatch(
|
||||
newPatchCenter,
|
||||
Geodetic2(patchSize.lat / 2, patchSize.lon / 2));
|
||||
// Snap patch position
|
||||
int segmentsPerPatch = _grid->segments();
|
||||
Geodetic2 stepSize = Geodetic2(
|
||||
patchSize.lat / segmentsPerPatch,
|
||||
patchSize.lon / segmentsPerPatch);
|
||||
ivec2 patchesToCoverGlobe = ivec2(
|
||||
M_PI / patchSize.lat + 0.5,
|
||||
M_PI * 2 / patchSize.lon + 0.5);
|
||||
Geodetic2 cameraPosLatLon = ellipsoid.cartesianToGeodetic2(data.camera.position().dvec3());
|
||||
ivec2 intSnapCoord = ivec2(
|
||||
cameraPosLatLon.lat / (M_PI * 2) * segmentsPerPatch * patchesToCoverGlobe.y,
|
||||
cameraPosLatLon.lon / (M_PI) * segmentsPerPatch * patchesToCoverGlobe.x);
|
||||
Geodetic2 newPatchCenter = Geodetic2(
|
||||
stepSize.lat * intSnapCoord.x,
|
||||
stepSize.lon * intSnapCoord.y);
|
||||
GeodeticPatch newPatch(
|
||||
newPatchCenter,
|
||||
Geodetic2(patchSize.lat / 2, patchSize.lon / 2));
|
||||
|
||||
ivec2 contraction = ivec2(intSnapCoord.y % 2, intSnapCoord.x % 2);
|
||||
ivec2 contraction = ivec2(intSnapCoord.y % 2, intSnapCoord.x % 2);
|
||||
|
||||
//LDEBUG("patch.center = [ " << patch.center.lat << " , " << patch.center.lon << " ]");
|
||||
//LDEBUG("intSnapCoord = [ " << intSnapCoord.x << " , " << intSnapCoord.y << " ]");
|
||||
//LDEBUG("contraction = [ " << contraction.x << " , " << contraction.y << " ]");
|
||||
//LDEBUG("patch.center = [ " << patch.center.lat << " , " << patch.center.lon << " ]");
|
||||
//LDEBUG("intSnapCoord = [ " << intSnapCoord.x << " , " << intSnapCoord.y << " ]");
|
||||
//LDEBUG("contraction = [ " << contraction.x << " , " << contraction.y << " ]");
|
||||
|
||||
|
||||
// Get the textures that should be used for rendering
|
||||
TileIndex tileIndex = _tileSet.getTileIndex(newPatch);
|
||||
GeodeticPatch tilePatch = _tileSet.getTilePositionAndScale(tileIndex);
|
||||
std::shared_ptr<ghoul::opengl::Texture> tile00 = _tileSet.getTile(tileIndex);
|
||||
glm::mat3 uvTransform = _tileSet.getUvTransformationPatchToTile(newPatch, tileIndex);
|
||||
// Get the textures that should be used for rendering
|
||||
TileIndex tileIndex = _tileSet.getTileIndex(newPatch);
|
||||
GeodeticPatch tilePatch = _tileSet.getTilePositionAndScale(tileIndex);
|
||||
std::shared_ptr<ghoul::opengl::Texture> tile00 = _tileSet.getTile(tileIndex);
|
||||
glm::mat3 uvTransform = _tileSet.getUvTransformationPatchToTile(newPatch, tileIndex);
|
||||
|
||||
// Bind and use the texture
|
||||
ghoul::opengl::TextureUnit texUnit;
|
||||
texUnit.activate();
|
||||
tile00->bind();
|
||||
_programObject->setUniform("textureSampler", texUnit);
|
||||
_programObject->setUniform("uvTransformPatchToTile", mat3(uvTransform));
|
||||
// Bind and use the texture
|
||||
ghoul::opengl::TextureUnit texUnit;
|
||||
texUnit.activate();
|
||||
tile00->bind();
|
||||
_programObject->setUniform("textureSampler", texUnit);
|
||||
_programObject->setUniform("uvTransformPatchToTile", mat3(uvTransform));
|
||||
|
||||
_programObject->setUniform(
|
||||
"modelViewProjectionTransform",
|
||||
data.camera.projectionMatrix() * viewTransform * modelTransform);
|
||||
_programObject->setUniform("segmentsPerPatch", segmentsPerPatch);
|
||||
_programObject->setUniform("minLatLon", vec2(newPatch.southWestCorner().toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", vec2(patchSize.toLonLatVec2()));
|
||||
_programObject->setUniform("radiiSquared", vec3(ellipsoid.radiiSquared()));
|
||||
_programObject->setUniform("contraction", contraction);
|
||||
_programObject->setUniform(
|
||||
"modelViewProjectionTransform",
|
||||
data.camera.projectionMatrix() * viewTransform * modelTransform);
|
||||
_programObject->setUniform("segmentsPerPatch", segmentsPerPatch);
|
||||
_programObject->setUniform("minLatLon", vec2(newPatch.southWestCorner().toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", vec2(patchSize.toLonLatVec2()));
|
||||
_programObject->setUniform("radiiSquared", vec3(ellipsoid.radiiSquared()));
|
||||
_programObject->setUniform("contraction", contraction);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// render
|
||||
_grid->geometry().drawUsingActiveProgram();
|
||||
// render
|
||||
_grid->geometry().drawUsingActiveProgram();
|
||||
|
||||
// disable shader
|
||||
_programObject->deactivate();
|
||||
}
|
||||
// disable shader
|
||||
_programObject->deactivate();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -75,6 +75,8 @@ namespace openspace {
|
||||
public:
|
||||
LatLonPatchRenderer(shared_ptr<Grid> grid);
|
||||
|
||||
void update();
|
||||
|
||||
void renderPatch(
|
||||
const GeodeticPatch& patch,
|
||||
const RenderData& data,
|
||||
@@ -85,9 +87,13 @@ namespace openspace {
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid,
|
||||
const TileIndex& ti);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
shared_ptr<Grid> _grid;
|
||||
|
||||
TwmsTileProvider tileProvider;
|
||||
shared_ptr<Grid> _grid;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ struct TestJob : public Job<int> {
|
||||
std::cout << "Finished job" << std::endl;
|
||||
}
|
||||
|
||||
virtual int product() {
|
||||
return prod;
|
||||
virtual std::shared_ptr<int> product() {
|
||||
return std::make_shared<int>(prod);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -88,27 +88,68 @@ TEST_F(ConcurrentJobManagerTest, Basic) {
|
||||
|
||||
auto finishedJob = jobManager.popFinishedJob();
|
||||
|
||||
int product = finishedJob->product();
|
||||
int product = *finishedJob->product();
|
||||
EXPECT_EQ(product, 1337) << "Expecting product to be 1337";
|
||||
}
|
||||
|
||||
|
||||
struct VerboseTestJob : public TestJob {
|
||||
VerboseTestJob(int jobExecutingTime)
|
||||
: TestJob(jobExecutingTime) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct VerboseProduct {
|
||||
VerboseProduct(int v)
|
||||
: val(v){
|
||||
std::cout << "VerboseProduct constructor" << std::endl;
|
||||
}
|
||||
|
||||
~VerboseProduct() {
|
||||
std::cout << "VerboseProduct destructor" << std::endl;
|
||||
}
|
||||
|
||||
int val;
|
||||
};
|
||||
|
||||
|
||||
struct VerboseJob : public Job<VerboseProduct>{
|
||||
VerboseJob(int jobExecutingTime)
|
||||
: _jobExecutingTime(jobExecutingTime) {
|
||||
std::cout << "VerboseTestJob constructor" << std::endl;
|
||||
}
|
||||
|
||||
~VerboseTestJob() {
|
||||
~VerboseJob() {
|
||||
std::cout << "VerboseTestJob destructor" << std::endl;
|
||||
}
|
||||
|
||||
virtual void execute() {
|
||||
std::cout << " ** Executing job ... " << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(_jobExecutingTime));
|
||||
_product = std::shared_ptr<VerboseProduct>(new VerboseProduct(1337));
|
||||
std::cout << " ** Finished job" << std::endl;
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<VerboseProduct> product() {
|
||||
return _product;
|
||||
}
|
||||
|
||||
int _jobExecutingTime;
|
||||
std::shared_ptr<VerboseProduct> _product;
|
||||
|
||||
};
|
||||
|
||||
TEST_F(ConcurrentJobManagerTest, JobCreation) {
|
||||
ConcurrentJobManager<int> jobManager;
|
||||
|
||||
auto testJob1 = std::shared_ptr<TestJob>(new VerboseTestJob(20));
|
||||
|
||||
|
||||
|
||||
|
||||
TEST_F(ConcurrentJobManagerTest, JobCreation) {
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
|
||||
ConcurrentJobManager<VerboseProduct> jobManager;
|
||||
|
||||
auto testJob1 = std::shared_ptr<VerboseJob>(new VerboseJob(20));
|
||||
|
||||
jobManager.enqueueJob(testJob1);
|
||||
|
||||
@@ -121,8 +162,12 @@ TEST_F(ConcurrentJobManagerTest, JobCreation) {
|
||||
|
||||
|
||||
auto finishedJob = jobManager.popFinishedJob();
|
||||
{
|
||||
auto product = finishedJob->product();
|
||||
}
|
||||
|
||||
|
||||
int product = finishedJob->product();
|
||||
EXPECT_EQ(product, 1337) << "Expecting product to be 1337";
|
||||
int a;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user