mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-22 19:29:04 -05:00
Solve merge conflict.
This commit is contained in:
@@ -33,6 +33,7 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunklodglobe.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunknode.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkindex.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunk.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/trianglesoup.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/grid.h
|
||||
@@ -66,6 +67,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunklodglobe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunknode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunkindex.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/globes/chunk.cpp
|
||||
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/meshes/trianglesoup.cpp
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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 <ghoul/misc/assert.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
|
||||
#include <modules/globebrowsing/globes/chunk.h>
|
||||
#include <modules/globebrowsing/globes/chunklodglobe.h>
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "Chunk";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Chunk::Chunk(ChunkLodGlobe* owner, const ChunkIndex& chunkIndex)
|
||||
: _owner(owner)
|
||||
, _surfacePatch(chunkIndex)
|
||||
, _index(chunkIndex)
|
||||
, _isVisible(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const GeodeticPatch& Chunk::surfacePatch() const {
|
||||
return _surfacePatch;
|
||||
}
|
||||
|
||||
ChunkLodGlobe* const Chunk::owner() const {
|
||||
return _owner;
|
||||
}
|
||||
|
||||
const ChunkIndex Chunk::index() const {
|
||||
return _index;
|
||||
}
|
||||
|
||||
bool Chunk::isVisible() const {
|
||||
return _isVisible;
|
||||
}
|
||||
|
||||
void Chunk::setIndex(const ChunkIndex& index) {
|
||||
_index = index;
|
||||
_surfacePatch = GeodeticPatch(index);
|
||||
}
|
||||
|
||||
void Chunk::setOwner(ChunkLodGlobe* newOwner) {
|
||||
_owner = newOwner;
|
||||
}
|
||||
|
||||
Chunk::Status Chunk::update(const RenderData& data) {
|
||||
//In the current implementation of the horizon culling and the distance to the
|
||||
//camera, 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.
|
||||
|
||||
_isVisible = true;
|
||||
|
||||
const Ellipsoid& ellipsoid = _owner->ellipsoid();
|
||||
|
||||
// Do horizon culling
|
||||
const int maxHeight = 8700; // should be read from gdal dataset or mod file
|
||||
_isVisible = HorizonCuller::isVisible(data, _surfacePatch, ellipsoid, maxHeight);
|
||||
if (!_isVisible) {
|
||||
return WANT_MERGE;
|
||||
}
|
||||
|
||||
|
||||
// Do frustum culling
|
||||
_isVisible = FrustumCuller::isVisible(data, _surfacePatch, ellipsoid);
|
||||
if (!_isVisible) {
|
||||
return WANT_MERGE;
|
||||
}
|
||||
|
||||
auto center = _surfacePatch.center();
|
||||
Vec3 globePosition = data.position.dvec3();
|
||||
Vec3 patchPosition = globePosition + ellipsoid.geodetic2ToCartesian(center);
|
||||
Vec3 cameraPosition = data.camera.position().dvec3();
|
||||
Vec3 cameraToChunk = patchPosition - cameraPosition;
|
||||
Scalar minimumGlobeRadius = ellipsoid.minimumRadius();
|
||||
|
||||
// Calculate desired level based on distance
|
||||
Scalar distance = glm::length(cameraToChunk);
|
||||
_owner->minDistToCamera = fmin(_owner->minDistToCamera, distance);
|
||||
|
||||
Scalar scaleFactor = 10 * minimumGlobeRadius;
|
||||
Scalar projectedScaleFactor = scaleFactor / distance;
|
||||
int desiredLevel = floor(log2(projectedScaleFactor));
|
||||
|
||||
// clamp level
|
||||
desiredLevel = glm::clamp(desiredLevel, _owner->minSplitDepth, _owner->maxSplitDepth);
|
||||
|
||||
if (desiredLevel < _index.level) return WANT_MERGE;
|
||||
else if (_index.level < desiredLevel) return WANT_SPLIT;
|
||||
else return DO_NOTHING;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
@@ -0,0 +1,79 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __CHUNK_H__
|
||||
#define __CHUNK_H__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
#include <modules/globebrowsing/rendering/culling.h>
|
||||
|
||||
#include <modules/globebrowsing/globes/chunkindex.h>
|
||||
#include <modules/globebrowsing/geodetics/geodetic2.h>
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class ChunkLodGlobe;
|
||||
|
||||
|
||||
class Chunk {
|
||||
public:
|
||||
|
||||
enum Status{
|
||||
DO_NOTHING,
|
||||
WANT_MERGE,
|
||||
WANT_SPLIT,
|
||||
};
|
||||
|
||||
Chunk(ChunkLodGlobe* owner, const ChunkIndex& chunkIndex);
|
||||
|
||||
/// Updates chunk internally and returns a desired level
|
||||
Status update(const RenderData& data);
|
||||
|
||||
const GeodeticPatch& surfacePatch() const;
|
||||
ChunkLodGlobe* const owner() const;
|
||||
const ChunkIndex index() const;
|
||||
bool isVisible() const;
|
||||
|
||||
void setIndex(const ChunkIndex& index);
|
||||
void setOwner(ChunkLodGlobe* newOwner);
|
||||
|
||||
|
||||
private:
|
||||
ChunkLodGlobe* _owner;
|
||||
ChunkIndex _index;
|
||||
bool _isVisible;
|
||||
GeodeticPatch _surfacePatch;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // __CHUNK_H__
|
||||
@@ -48,14 +48,8 @@ namespace openspace {
|
||||
y = floor(yIndexSpace);
|
||||
}
|
||||
|
||||
|
||||
std::vector<ChunkIndex> ChunkIndex::childIndices() const {
|
||||
return{
|
||||
{ 2 * x + 0, 2 * y + 0, level + 1 },
|
||||
{ 2 * x + 1, 2 * y + 0, level + 1 },
|
||||
{ 2 * x + 0, 2 * y + 1, level + 1 },
|
||||
{ 2 * x + 1, 2 * y + 1, level + 1 },
|
||||
};
|
||||
ChunkIndex ChunkIndex::child(Quad q) const {
|
||||
return ChunkIndex(2 * x + q % 2, 2 * y + q / 2, level + 1);
|
||||
}
|
||||
|
||||
ChunkIndex ChunkIndex::parent() const {
|
||||
|
||||
@@ -30,14 +30,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
namespace openspace {
|
||||
|
||||
|
||||
class Geodetic2;
|
||||
|
||||
enum Quad {
|
||||
NORTH_WEST,
|
||||
NORTH_WEST = 0,
|
||||
NORTH_EAST,
|
||||
SOUTH_WEST,
|
||||
SOUTH_EAST
|
||||
@@ -59,7 +58,6 @@ struct ChunkIndex {
|
||||
ChunkIndex(const ChunkIndex& other) : x(other.x), y(other.y), level(other.level) { }
|
||||
ChunkIndex(const Geodetic2& point, int level);
|
||||
|
||||
std::vector<ChunkIndex> childIndices() const;
|
||||
|
||||
bool hasParent() const {
|
||||
return level > 0;
|
||||
@@ -83,6 +81,7 @@ struct ChunkIndex {
|
||||
return y % 2 == 1;
|
||||
}
|
||||
|
||||
ChunkIndex child(Quad q) const;
|
||||
|
||||
/**
|
||||
Gets the tile at a specified offset from this tile.
|
||||
|
||||
@@ -47,24 +47,27 @@ 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 ChunkIndex ChunkLodGlobe::LEFT_HEMISPHERE_INDEX = ChunkIndex(0, 0, 1);
|
||||
const ChunkIndex ChunkLodGlobe::RIGHT_HEMISPHERE_INDEX = ChunkIndex(1, 0, 1);
|
||||
|
||||
|
||||
ChunkLodGlobe::ChunkLodGlobe(
|
||||
const Ellipsoid& ellipsoid,
|
||||
std::shared_ptr<TileProviderManager> tileProviderManager)
|
||||
: _ellipsoid(ellipsoid)
|
||||
, _leftRoot(new ChunkNode(*this, LEFT_HEMISPHERE))
|
||||
, _rightRoot(new ChunkNode(*this, RIGHT_HEMISPHERE))
|
||||
, _leftRoot(new ChunkNode(Chunk(this, LEFT_HEMISPHERE_INDEX)))
|
||||
, _rightRoot(new ChunkNode(Chunk(this, RIGHT_HEMISPHERE_INDEX)))
|
||||
, minSplitDepth(2)
|
||||
, maxSplitDepth(22)
|
||||
{
|
||||
auto geometry = std::shared_ptr<BasicGrid>(new BasicGrid(
|
||||
256,
|
||||
256,
|
||||
100,
|
||||
100,
|
||||
TriangleSoup::Positions::No,
|
||||
TriangleSoup::TextureCoordinates::Yes,
|
||||
TriangleSoup::Normals::No));
|
||||
|
||||
_patchRenderer.reset(new LatLonPatchRenderer(geometry, tileProviderManager));
|
||||
_patchRenderer.reset(new ChunkRenderer(geometry, tileProviderManager));
|
||||
}
|
||||
|
||||
ChunkLodGlobe::~ChunkLodGlobe() {
|
||||
@@ -84,7 +87,7 @@ namespace openspace {
|
||||
return ready;
|
||||
}
|
||||
|
||||
LatLonPatchRenderer& ChunkLodGlobe::getPatchRenderer() {
|
||||
ChunkRenderer& ChunkLodGlobe::getPatchRenderer() const{
|
||||
return *_patchRenderer;
|
||||
}
|
||||
|
||||
@@ -93,11 +96,9 @@ namespace openspace {
|
||||
ChunkNode::renderedPatches = 0;
|
||||
|
||||
|
||||
ChunkIndex leftRootChunkIndex = { 0, 0, 1 };
|
||||
_leftRoot->render(data, leftRootChunkIndex);
|
||||
|
||||
ChunkIndex rightRootChunkIndex = { 1, 0, 1 };
|
||||
_rightRoot->render(data, rightRootChunkIndex);
|
||||
_leftRoot->render(data);
|
||||
_rightRoot->render(data);
|
||||
|
||||
//LDEBUG("min distnace to camera: " << minDistToCamera);
|
||||
|
||||
@@ -106,6 +107,7 @@ namespace openspace {
|
||||
|
||||
//LDEBUG("ChunkNode count: " << ChunkNode::instanceCount);
|
||||
//LDEBUG("RenderedPatches count: " << ChunkNode::renderedPatches);
|
||||
//LDEBUG(ChunkNode::renderedPatches << " / " << ChunkNode::instanceCount << " chunks rendered");
|
||||
}
|
||||
|
||||
void ChunkLodGlobe::update(const UpdateData& data) {
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace openspace {
|
||||
std::shared_ptr<TileProviderManager> tileProviderManager);
|
||||
~ChunkLodGlobe();
|
||||
|
||||
LatLonPatchRenderer& getPatchRenderer();
|
||||
ChunkRenderer& getPatchRenderer() const;
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
@@ -85,11 +85,14 @@ namespace openspace {
|
||||
std::unique_ptr<ChunkNode> _rightRoot;
|
||||
|
||||
// the patch used for actual rendering
|
||||
std::unique_ptr<LatLonPatchRenderer> _patchRenderer;
|
||||
std::unique_ptr<ChunkRenderer> _patchRenderer;
|
||||
|
||||
static const GeodeticPatch LEFT_HEMISPHERE;
|
||||
static const GeodeticPatch RIGHT_HEMISPHERE;
|
||||
|
||||
static const ChunkIndex LEFT_HEMISPHERE_INDEX;
|
||||
static const ChunkIndex RIGHT_HEMISPHERE_INDEX;
|
||||
|
||||
const Ellipsoid& _ellipsoid;
|
||||
};
|
||||
|
||||
|
||||
@@ -42,11 +42,9 @@ namespace openspace {
|
||||
int ChunkNode::instanceCount = 0;
|
||||
int ChunkNode::renderedPatches = 0;
|
||||
|
||||
ChunkNode::ChunkNode(ChunkLodGlobe& owner, const GeodeticPatch& patch, ChunkNode* parent)
|
||||
: _owner(owner)
|
||||
, _patch(patch)
|
||||
ChunkNode::ChunkNode(const Chunk& chunk, ChunkNode* parent)
|
||||
: _chunk(chunk)
|
||||
, _parent(parent)
|
||||
, _isVisible(true)
|
||||
{
|
||||
_children[0] = nullptr;
|
||||
_children[1] = nullptr;
|
||||
@@ -68,38 +66,31 @@ bool ChunkNode::isLeaf() const {
|
||||
}
|
||||
|
||||
|
||||
void ChunkNode::render(const RenderData& data, ChunkIndex traverseData) {
|
||||
void ChunkNode::render(const RenderData& data) {
|
||||
ghoul_assert(isRoot(), "this method should only be invoked on root");
|
||||
//LDEBUG("-------------");
|
||||
internalUpdateChunkTree(data, traverseData);
|
||||
internalRender(data, traverseData);
|
||||
internalUpdateChunkTree(data);
|
||||
internalRender(data);
|
||||
}
|
||||
|
||||
|
||||
// Returns true or false wether this node can be merge or not
|
||||
bool ChunkNode::internalUpdateChunkTree(const RenderData& data, ChunkIndex& traverseData) {
|
||||
using namespace glm;
|
||||
Geodetic2 center = _patch.center();
|
||||
|
||||
bool ChunkNode::internalUpdateChunkTree(const RenderData& data) {
|
||||
//Geodetic2 center = _chunk.surfacePatch.center();
|
||||
//LDEBUG("x: " << patch.x << " y: " << patch.y << " level: " << patch.level << " lat: " << center.lat << " lon: " << center.lon);
|
||||
|
||||
if (isLeaf()) {
|
||||
|
||||
int desiredLevel = calculateDesiredLevelAndUpdateIsVisible(data, traverseData);
|
||||
desiredLevel = glm::clamp(desiredLevel, _owner.minSplitDepth, _owner.maxSplitDepth);
|
||||
if (desiredLevel > traverseData.level) {
|
||||
Chunk::Status status = _chunk.update(data);
|
||||
if (status == Chunk::WANT_SPLIT) {
|
||||
split();
|
||||
}
|
||||
else if(desiredLevel < traverseData.level){
|
||||
return true; // request a merge from parent
|
||||
}
|
||||
return false;
|
||||
return status == Chunk::WANT_MERGE;
|
||||
}
|
||||
else {
|
||||
int requestedMergeMask = 0;
|
||||
std::vector<ChunkIndex> childIndices = traverseData.childIndices();
|
||||
|
||||
char requestedMergeMask = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (_children[i]->internalUpdateChunkTree(data, childIndices[i])) {
|
||||
if (_children[i]->internalUpdateChunkTree(data)) {
|
||||
requestedMergeMask |= (1 << i);
|
||||
}
|
||||
}
|
||||
@@ -109,135 +100,35 @@ bool ChunkNode::internalUpdateChunkTree(const RenderData& data, ChunkIndex& trav
|
||||
merge();
|
||||
|
||||
// re-run this method on this, now that this is a leaf node
|
||||
return internalUpdateChunkTree(data, traverseData);
|
||||
return internalUpdateChunkTree(data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ChunkNode::internalRender(const RenderData& data, ChunkIndex& traverseData) {
|
||||
void ChunkNode::internalRender(const RenderData& data) {
|
||||
if (isLeaf()) {
|
||||
if (_isVisible) {
|
||||
|
||||
LatLonPatchRenderer& patchRenderer = _owner.getPatchRenderer();
|
||||
|
||||
patchRenderer.renderPatch(_patch, data, _owner.ellipsoid(), traverseData);
|
||||
if (_chunk.isVisible()) {
|
||||
ChunkRenderer& patchRenderer = _chunk.owner()->getPatchRenderer();
|
||||
patchRenderer.renderChunk(_chunk, _chunk.owner()->ellipsoid(), data);
|
||||
//patchRenderer.renderPatch(_chunk.surfacePatch, data, _chunk.owner->ellipsoid(), _chunk.index);
|
||||
ChunkNode::renderedPatches++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::vector<ChunkIndex> childIndices = traverseData.childIndices();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
_children[i]->internalRender(data, childIndices[i]);
|
||||
_children[i]->internalRender(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ChunkNode::calculateDesiredLevelAndUpdateIsVisible(
|
||||
const RenderData& data,
|
||||
const ChunkIndex& traverseData) {
|
||||
_isVisible = true;
|
||||
Vec3 globePosition = data.position.dvec3();
|
||||
|
||||
Vec3 patchPosition =
|
||||
globePosition +
|
||||
_owner.ellipsoid().geodetic2ToCartesian(_patch.center());
|
||||
|
||||
Vec3 cameraPosition = data.camera.position().dvec3();
|
||||
//Vec3 cameraDirection = Vec3(data.camera.viewDirection());
|
||||
Vec3 cameraToChunk = patchPosition - cameraPosition;
|
||||
|
||||
Scalar minimumGlobeRadius = _owner.ellipsoid().minimumRadius();
|
||||
|
||||
/*
|
||||
// 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);
|
||||
|
||||
Vec3 globeToCamera = cameraPosition - globePosition;
|
||||
|
||||
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));
|
||||
|
||||
//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);
|
||||
if (cosPatchNormalNormalizedGlobeToCamera < cosAngleToHorizon) {
|
||||
_isVisible = false;
|
||||
return traverseData.level - 1;
|
||||
}
|
||||
*/
|
||||
|
||||
if (traverseData == ChunkIndex(0, 0, 1))
|
||||
int hej = 0;
|
||||
|
||||
LDEBUG("traverseData = " << traverseData);
|
||||
|
||||
if (!HorizonCuller::isVisible(
|
||||
data,
|
||||
_patch,
|
||||
_owner.ellipsoid(),
|
||||
8700))
|
||||
{
|
||||
_isVisible = false;
|
||||
return traverseData.level - 1;
|
||||
}
|
||||
|
||||
|
||||
// Do frustrum culling
|
||||
//FrustumCuller& culler = _owner.getFrustumCuller();
|
||||
|
||||
if (!FrustumCuller::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 = 10 * minimumGlobeRadius;
|
||||
Scalar projectedScaleFactor = scaleFactor / distance;
|
||||
int desiredLevel = floor( log2(projectedScaleFactor) );
|
||||
return desiredLevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ChunkNode::split(int depth) {
|
||||
if (depth > 0 && isLeaf()) {
|
||||
|
||||
// Defining short handles for center, halfSize and quarterSize
|
||||
const Geodetic2& c = _patch.center();
|
||||
const Geodetic2& hs = _patch.halfSize();
|
||||
Geodetic2 qs = Geodetic2(0.5 * hs.lat, 0.5 * hs.lon);
|
||||
|
||||
// Subdivide bounds
|
||||
|
||||
GeodeticPatch nwBounds = GeodeticPatch(Geodetic2(c.lat + qs.lat, c.lon - qs.lon), qs);
|
||||
GeodeticPatch neBounds = GeodeticPatch(Geodetic2(c.lat + qs.lat, c.lon + qs.lon), qs);
|
||||
GeodeticPatch swBounds = GeodeticPatch(Geodetic2(c.lat - qs.lat, c.lon - qs.lon), qs);
|
||||
GeodeticPatch seBounds = GeodeticPatch(Geodetic2(c.lat - qs.lat, c.lon + qs.lon), qs);
|
||||
|
||||
// Create new chunk nodes
|
||||
|
||||
_children[Quad::NORTH_WEST] = std::unique_ptr<ChunkNode>(new ChunkNode(_owner, nwBounds, this));
|
||||
_children[Quad::NORTH_EAST] = std::unique_ptr<ChunkNode>(new ChunkNode(_owner, neBounds, this));
|
||||
_children[Quad::SOUTH_WEST] = std::unique_ptr<ChunkNode>(new ChunkNode(_owner, swBounds, this));
|
||||
_children[Quad::SOUTH_EAST] = std::unique_ptr<ChunkNode>(new ChunkNode(_owner, seBounds, this));
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
Chunk chunk(_chunk.owner(), _chunk.index().child((Quad)i));
|
||||
_children[i] = std::unique_ptr<ChunkNode>(new ChunkNode(chunk, this));
|
||||
}
|
||||
}
|
||||
|
||||
if (depth - 1 > 0) {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <ostream>
|
||||
|
||||
#include <modules/globebrowsing/globes/chunkindex.h>
|
||||
#include <modules/globebrowsing/globes/chunk.h>
|
||||
#include <modules/globebrowsing/geodetics/geodetic2.h>
|
||||
#include <modules/globebrowsing/rendering/patchrenderer.h>
|
||||
|
||||
@@ -46,9 +47,11 @@ namespace openspace {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ChunkNode {
|
||||
public:
|
||||
ChunkNode(ChunkLodGlobe&, const GeodeticPatch&, ChunkNode* parent = nullptr);
|
||||
ChunkNode(const Chunk& chunk, ChunkNode* parent = nullptr);
|
||||
~ChunkNode();
|
||||
|
||||
|
||||
@@ -61,7 +64,7 @@ public:
|
||||
|
||||
const ChunkNode& getChild(Quad quad) const;
|
||||
|
||||
void render(const RenderData& data, ChunkIndex);
|
||||
void render(const RenderData& data);
|
||||
|
||||
static int instanceCount;
|
||||
static int renderedPatches;
|
||||
@@ -69,28 +72,16 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void internalRender(const RenderData& data, ChunkIndex&);
|
||||
bool internalUpdateChunkTree(const RenderData& data, ChunkIndex& traverseData);
|
||||
void internalRender(const RenderData& data);
|
||||
bool internalUpdateChunkTree(const RenderData& data);
|
||||
|
||||
/**
|
||||
Uses horizon culling, frustum culling and distance to camera to determine a
|
||||
desired level.
|
||||
In the current implementation of the horizon culling and the distance to the
|
||||
camera, 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.
|
||||
*/
|
||||
int calculateDesiredLevelAndUpdateIsVisible(
|
||||
const RenderData& data,
|
||||
const ChunkIndex& traverseData);
|
||||
|
||||
|
||||
|
||||
ChunkNode* _parent;
|
||||
std::unique_ptr<ChunkNode> _children[4];
|
||||
ChunkLodGlobe& _owner;
|
||||
GeodeticPatch _patch;
|
||||
bool _isVisible;
|
||||
|
||||
Chunk _chunk;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace openspace {
|
||||
GDALDataset* dataSet,
|
||||
ChunkIndex chunkIndex,
|
||||
int tileLevelDifference)
|
||||
|
||||
{
|
||||
int nRasters = dataSet->GetRasterCount();
|
||||
|
||||
@@ -61,8 +60,7 @@ namespace openspace {
|
||||
|
||||
// Level = overviewCount - overview (default, levels may be overridden)
|
||||
int numOverviews = firstBand->GetOverviewCount();
|
||||
//int xSize0 = firstBand->GetOverview(0)->GetXSize();
|
||||
//int ySize0 = firstBand->GetOverview(0)->GetYSize();
|
||||
|
||||
|
||||
// Generate a patch from the chunkIndex, extract the bounds which
|
||||
// are used to calculated where in the GDAL data set to read data.
|
||||
|
||||
@@ -97,6 +97,7 @@ namespace openspace {
|
||||
delete _gdalDataSet;
|
||||
}
|
||||
|
||||
|
||||
void TileProvider::prerender() {
|
||||
while (_tileLoadManager.numFinishedJobs() > 0) {
|
||||
auto finishedJob = _tileLoadManager.popFinishedJob();
|
||||
@@ -108,6 +109,7 @@ namespace openspace {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Tile TileProvider::getMostHiResTile(ChunkIndex chunkIndex) {
|
||||
std::shared_ptr<Texture> tex = nullptr;
|
||||
glm::vec2 uvOffset(0, 0);
|
||||
|
||||
@@ -129,6 +129,7 @@ namespace openspace {
|
||||
|
||||
virtual void execute() {
|
||||
_uninitedTexture = _tileProvider->getUninitializedTextureTile(_chunkIndex);
|
||||
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<UninitializedTextureTile> product() {
|
||||
|
||||
@@ -115,6 +115,7 @@ namespace openspace {
|
||||
return pointScreenSpace;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// HORIZON CULLER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/rendering/patchrenderer.h>
|
||||
|
||||
#include <modules/globebrowsing/rendering/patchrenderer.h>
|
||||
#include <modules/globebrowsing/meshes/clipmapgrid.h>
|
||||
|
||||
// open space includes
|
||||
@@ -85,7 +85,7 @@ namespace openspace {
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// LATLON PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
LatLonPatchRenderer::LatLonPatchRenderer(
|
||||
ChunkRenderer::ChunkRenderer(
|
||||
shared_ptr<Grid> grid,
|
||||
shared_ptr<TileProviderManager> tileProviderManager)
|
||||
: PatchRenderer(tileProviderManager)
|
||||
@@ -101,14 +101,13 @@ namespace openspace {
|
||||
_programObjectGlobalRendering->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
void LatLonPatchRenderer::renderPatch(
|
||||
const GeodeticPatch& patch,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid,
|
||||
const ChunkIndex& chunkIndex)
|
||||
|
||||
|
||||
void ChunkRenderer::renderChunk(const Chunk& chunk, const Ellipsoid& ellipsoid,
|
||||
const RenderData& data)
|
||||
|
||||
{
|
||||
using namespace glm;
|
||||
|
||||
|
||||
// TODO : Model transform should be fetched as a matrix directly.
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
@@ -118,32 +117,31 @@ namespace openspace {
|
||||
|
||||
// activate shader
|
||||
_programObjectGlobalRendering->activate();
|
||||
|
||||
|
||||
|
||||
// For now just pick the first one from height maps
|
||||
auto heightMapProviders = _tileProviderManager->heightMapProviders();
|
||||
auto tileProviderHeight = heightMapProviders.begin()->second;
|
||||
|
||||
// Get the textures that should be used for rendering
|
||||
Tile heightTile = tileProviderHeight->getMostHiResTile(chunkIndex);
|
||||
Tile heightTile = tileProviderHeight->getMostHiResTile(chunk.index());
|
||||
|
||||
|
||||
|
||||
// Bind and use the texture
|
||||
ghoul::opengl::TextureUnit texUnitHeight;
|
||||
texUnitHeight.activate();
|
||||
heightTile.texture->bind();
|
||||
_programObjectGlobalRendering->setUniform("textureSamplerHeight", texUnitHeight);
|
||||
|
||||
_programObjectGlobalRendering->setUniform("heightSamplingScale", heightTile.transform.uvScale);
|
||||
_programObjectGlobalRendering->setUniform("heightSamplingOffset", heightTile.transform.uvOffset);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Pick the first color texture
|
||||
auto colorTextureProviders = _tileProviderManager->colorTextureProviders();
|
||||
auto tileProviderColor = colorTextureProviders.begin()->second;
|
||||
Tile colorTile = tileProviderColor->getMostHiResTile(chunkIndex);
|
||||
Tile colorTile = tileProviderColor->getMostHiResTile(chunk.index());
|
||||
|
||||
|
||||
// Bind and use the texture
|
||||
@@ -155,8 +153,8 @@ namespace openspace {
|
||||
_programObjectGlobalRendering->setUniform("colorSamplingOffset", colorTile.transform.uvOffset);
|
||||
|
||||
|
||||
Geodetic2 swCorner = patch.southWestCorner();
|
||||
auto patchSize = patch.size();
|
||||
Geodetic2 swCorner = chunk.surfacePatch().southWestCorner();
|
||||
auto patchSize = chunk.surfacePatch().size();
|
||||
_programObjectGlobalRendering->setUniform("modelViewProjectionTransform", modelViewProjectionTransform);
|
||||
_programObjectGlobalRendering->setUniform("minLatLon", vec2(swCorner.toLonLatVec2()));
|
||||
_programObjectGlobalRendering->setUniform("lonLatScalingFactor", vec2(patchSize.toLonLatVec2()));
|
||||
@@ -172,6 +170,8 @@ namespace openspace {
|
||||
// disable shader
|
||||
_programObjectGlobalRendering->deactivate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// CLIPMAP PATCH RENDERER //
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
#include <modules/globebrowsing/other/texturetileset.h>
|
||||
#include <modules/globebrowsing/other/patchcoverageprovider.h>
|
||||
#include <modules/globebrowsing/other/tileprovidermanager.h>
|
||||
#include <modules/globebrowsing/globes/chunkindex.h>
|
||||
#include <modules/globebrowsing/globes/chunknode.h>
|
||||
|
||||
|
||||
|
||||
namespace ghoul {
|
||||
@@ -77,23 +78,22 @@ namespace openspace {
|
||||
// PATCH RENDERER SUBCLASSES //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LatLonPatchRenderer : public PatchRenderer {
|
||||
class ChunkRenderer : public PatchRenderer {
|
||||
public:
|
||||
LatLonPatchRenderer(
|
||||
shared_ptr<Grid> grid,
|
||||
shared_ptr<TileProviderManager> tileProviderManager);
|
||||
ChunkRenderer(shared_ptr<Grid> grid,
|
||||
shared_ptr<TileProviderManager> tileProviderManager);
|
||||
|
||||
|
||||
void ChunkRenderer::renderChunk(const Chunk& chunk, const Ellipsoid& ellipsoid, const RenderData& data);
|
||||
|
||||
void renderPatch(
|
||||
const GeodeticPatch& patch,
|
||||
const RenderData& data,
|
||||
const Ellipsoid& ellipsoid,
|
||||
const ChunkIndex& chunkIndex);
|
||||
private:
|
||||
shared_ptr<Grid> _grid;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ClipMapPatchRenderer : public PatchRenderer {
|
||||
public:
|
||||
ClipMapPatchRenderer(
|
||||
|
||||
Reference in New Issue
Block a user