mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-13 06:49:05 -05:00
Solve merge conflict.
This commit is contained in:
@@ -65,86 +65,100 @@ bool ChunkNode::isLeaf() const {
|
||||
}
|
||||
|
||||
|
||||
void ChunkNode::render(const RenderData& data) {
|
||||
void ChunkNode::render(const RenderData& data, ChunkIndex traverseData) {
|
||||
ghoul_assert(isRoot(), "this method should only be invoked on root");
|
||||
//LDEBUG("-------------");
|
||||
internalUpdateChunkTree(data, 0);
|
||||
internalRender(data, 0);
|
||||
internalUpdateChunkTree(data, traverseData);
|
||||
internalRender(data, traverseData);
|
||||
}
|
||||
|
||||
|
||||
// Returns true or false wether this node can be merge or not
|
||||
bool ChunkNode::internalUpdateChunkTree(const RenderData& data, int depth) {
|
||||
bool ChunkNode::internalUpdateChunkTree(const RenderData& data, ChunkIndex& traverseData) {
|
||||
using namespace glm;
|
||||
LatLon center = _patch.center;
|
||||
LatLon center = _patch.center();
|
||||
|
||||
|
||||
//LDEBUG("x: " << patch.x << " y: " << patch.y << " level: " << patch.level << " lat: " << center.lat << " lon: " << center.lon);
|
||||
|
||||
if (isLeaf()) {
|
||||
int desiredDepth = desiredSplitDepth(data);
|
||||
if (desiredDepth > depth) {
|
||||
int desiredLevel = calculateDesiredLevel(data, traverseData);
|
||||
if (desiredLevel > traverseData.level) {
|
||||
split();
|
||||
}
|
||||
else if(desiredDepth < depth){
|
||||
else if(desiredLevel < traverseData.level){
|
||||
return true; // request a merge from parent
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
|
||||
int requestedMergeMask = 0;
|
||||
std::vector<ChunkIndex> childIndices = traverseData.childIndices();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (_children[i]->internalUpdateChunkTree(data, depth + 1)) {
|
||||
if (_children[i]->internalUpdateChunkTree(data, childIndices[i])) {
|
||||
requestedMergeMask |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check if all children requested merge
|
||||
if (requestedMergeMask == 0xf) {
|
||||
merge();
|
||||
|
||||
// re-run this method on this, now that this is a leaf node
|
||||
return internalUpdateChunkTree(data, depth);
|
||||
return internalUpdateChunkTree(data, traverseData);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ChunkNode::internalRender(const RenderData& data, int currLevel) {
|
||||
void ChunkNode::internalRender(const RenderData& data, ChunkIndex& traverseData) {
|
||||
if (isLeaf()) {
|
||||
PatchRenderer& patchRenderer = _owner.getPatchRenderer();
|
||||
|
||||
patchRenderer.renderPatch(_patch, data, _owner.globeRadius);
|
||||
}
|
||||
else {
|
||||
std::vector<ChunkIndex> childIndices = traverseData.childIndices();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
_children[i]->internalRender(data, currLevel+1);
|
||||
_children[i]->internalRender(data, childIndices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ChunkNode::desiredSplitDepth(const RenderData& data) {
|
||||
Vec3 normal = _patch.center.asUnitCartesian();
|
||||
Vec3 pos = data.position.dvec3() + _owner.globeRadius * normal;
|
||||
int ChunkNode::calculateDesiredLevel(const RenderData& data, const ChunkIndex& traverseData) {
|
||||
|
||||
// Temporay ugly fix for Camera::position() is broken.
|
||||
Vec3 buggedCameraPos = data.camera.position().dvec3();
|
||||
|
||||
Vec3 patchNormal = _patch.center().asUnitCartesian();
|
||||
Vec3 patchPosition = data.position.dvec3() + _owner.globeRadius * patchNormal;
|
||||
|
||||
Vec3 cameraPosition = data.camera.position().dvec3();
|
||||
Vec3 cameraDirection = Vec3(data.camera.viewDirection());
|
||||
Vec3 cameraPos = buggedCameraPos;// -_owner.globeRadius * cameraDirection;
|
||||
|
||||
Vec3 cameraToChunk = pos - cameraPos;
|
||||
Vec3 cameraToChunk = patchPosition - cameraPosition;
|
||||
|
||||
|
||||
// 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(normal, cameraDirection);
|
||||
Scalar cosNormalCameraDirection = glm::dot(patchNormal, cameraDirection);
|
||||
if (cosNormalCameraDirection > 0.3) {
|
||||
return _owner.minSplitDepth;
|
||||
return traverseData.level - 1;
|
||||
}
|
||||
|
||||
|
||||
// Do frustrum culling
|
||||
FrustrumCuller& culler = _owner.getFrustrumCuller();
|
||||
|
||||
if (!culler.isVisible(data, _patch, _owner.globeRadius)) {
|
||||
return traverseData.level - 1;
|
||||
}
|
||||
|
||||
// Calculate desired level based on distance
|
||||
Scalar distance = glm::length(cameraToChunk);
|
||||
_owner.minDistToCamera = fmin(_owner.minDistToCamera, distance);
|
||||
|
||||
Scalar scaleFactor = 40 * _owner.globeRadius;// *150 * _patch.unitArea();
|
||||
Scalar scaleFactor = 100 * _owner.globeRadius;
|
||||
Scalar projectedScaleFactor = scaleFactor / distance;
|
||||
int desiredDepth = floor( log2(projectedScaleFactor) );
|
||||
return glm::clamp(desiredDepth, _owner.minSplitDepth, _owner.maxSplitDepth);
|
||||
@@ -156,8 +170,8 @@ void ChunkNode::split(int depth) {
|
||||
if (depth > 0 && isLeaf()) {
|
||||
|
||||
// Defining short handles for center, halfSize and quarterSize
|
||||
const LatLon& c = _patch.center;
|
||||
const LatLon& hs = _patch.halfSize;
|
||||
const LatLon& c = _patch.center();
|
||||
const LatLon& hs = _patch.halfSize();
|
||||
LatLon qs = LatLon(0.5 * hs.lat, 0.5 * hs.lon);
|
||||
|
||||
// Subdivide bounds
|
||||
@@ -189,7 +203,7 @@ void ChunkNode::merge() {
|
||||
}
|
||||
}
|
||||
|
||||
const ChunkNode& ChunkNode::getChild(Quad quad) const {
|
||||
const ChunkNode& ChunkNode::getChild(Quad quad) const {
|
||||
return *_children[quad];
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,20 @@ enum Quad {
|
||||
};
|
||||
|
||||
|
||||
struct ChunkIndex {
|
||||
int x, y, level;
|
||||
|
||||
std::vector<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 },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ChunkNode {
|
||||
@@ -67,15 +81,15 @@ public:
|
||||
|
||||
const ChunkNode& getChild(Quad quad) const;
|
||||
|
||||
void render(const RenderData& data);
|
||||
void render(const RenderData& data, ChunkIndex);
|
||||
|
||||
static int instanceCount;
|
||||
|
||||
private:
|
||||
|
||||
void internalRender(const RenderData& data, int currLevel);
|
||||
bool internalUpdateChunkTree(const RenderData& data, int currLevel);
|
||||
int desiredSplitDepth(const RenderData& data);
|
||||
void internalRender(const RenderData& data, ChunkIndex&);
|
||||
bool internalUpdateChunkTree(const RenderData& data, ChunkIndex&);
|
||||
int calculateDesiredLevel(const RenderData& data, const ChunkIndex&);
|
||||
|
||||
|
||||
ChunkNode* _parent;
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace openspace {
|
||||
}
|
||||
|
||||
|
||||
Vec3 LatLon::asUnitCartesian() {
|
||||
Vec3 LatLon::asUnitCartesian() const{
|
||||
return Vec3(
|
||||
glm::cos(lat) * glm::cos(lon),
|
||||
glm::cos(lat) * glm::sin(lon),
|
||||
@@ -80,47 +80,70 @@ namespace openspace {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LatLonPatch::LatLonPatch(Scalar centerLat, Scalar centerLon, Scalar halfSizeLat, Scalar halfSizeLon)
|
||||
: center(LatLon(centerLat, centerLon))
|
||||
, halfSize(LatLon(halfSizeLat, halfSizeLon))
|
||||
: _center(LatLon(centerLat, centerLon))
|
||||
, _halfSize(LatLon(halfSizeLat, halfSizeLon))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LatLonPatch::LatLonPatch(const LatLon& center, const LatLon& halfSize)
|
||||
: center(center)
|
||||
, halfSize(halfSize)
|
||||
: _center(center)
|
||||
, _halfSize(halfSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LatLonPatch::LatLonPatch(const LatLonPatch& patch)
|
||||
: center(patch.center)
|
||||
, halfSize(patch.halfSize)
|
||||
: _center(patch._center)
|
||||
, _halfSize(patch._halfSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LatLonPatch::setCenter(const LatLon& center) {
|
||||
_center = center;
|
||||
}
|
||||
|
||||
void LatLonPatch::setHalfSize(const LatLon& halfSize) {
|
||||
_halfSize = halfSize;
|
||||
}
|
||||
|
||||
Scalar LatLonPatch::minimalBoundingRadius() const {
|
||||
const LatLon& cornerNearEquator = _center.lat > 0 ? southWestCorner() : northWestCorner();
|
||||
return glm::length(_center.asUnitCartesian() - cornerNearEquator.asUnitCartesian());
|
||||
}
|
||||
|
||||
Scalar LatLonPatch::unitArea() const {
|
||||
Scalar deltaTheta = 2 * halfSize.lon;
|
||||
Scalar phiMin = center.lat - halfSize.lat;
|
||||
Scalar phiMax = center.lat + halfSize.lat;
|
||||
Scalar deltaTheta = 2 * _halfSize.lon;
|
||||
Scalar phiMin = _center.lat - _halfSize.lat;
|
||||
Scalar phiMax = _center.lat + _halfSize.lat;
|
||||
return deltaTheta * (sin(phiMax) - sin(phiMin));
|
||||
}
|
||||
|
||||
const LatLon& LatLonPatch::center() const {
|
||||
return _center;
|
||||
}
|
||||
|
||||
const LatLon& LatLonPatch::halfSize() const {
|
||||
return _halfSize;
|
||||
}
|
||||
|
||||
|
||||
LatLon LatLonPatch::northWestCorner() const{
|
||||
return LatLon(center.lat + halfSize.lat, center.lon - halfSize.lon);
|
||||
return LatLon(_center.lat + _halfSize.lat, _center.lon - _halfSize.lon);
|
||||
}
|
||||
|
||||
LatLon LatLonPatch::northEastCorner() const{
|
||||
return LatLon(center.lat + halfSize.lat, center.lon + halfSize.lon);
|
||||
return LatLon(_center.lat + _halfSize.lat, _center.lon + _halfSize.lon);
|
||||
}
|
||||
|
||||
LatLon LatLonPatch::southWestCorner() const{
|
||||
return LatLon(center.lat - halfSize.lat, center.lon - halfSize.lon);
|
||||
return LatLon(_center.lat - _halfSize.lat, _center.lon - _halfSize.lon);
|
||||
}
|
||||
|
||||
LatLon LatLonPatch::southEastCorner() const{
|
||||
return LatLon(center.lat - halfSize.lat, center.lon + halfSize.lon);
|
||||
return LatLon(_center.lat - _halfSize.lat, _center.lon + _halfSize.lon);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -44,7 +44,7 @@ struct LatLon {
|
||||
LatLon(const LatLon& src);
|
||||
|
||||
static LatLon fromCartesian(const Vec3& v);
|
||||
Vec3 asUnitCartesian();
|
||||
Vec3 asUnitCartesian() const;
|
||||
Vec2 toLonLatVec2() const;
|
||||
|
||||
inline bool operator==(const LatLon& other);
|
||||
@@ -54,21 +54,39 @@ struct LatLon {
|
||||
Scalar lon;
|
||||
};
|
||||
|
||||
struct LatLonPatch {
|
||||
|
||||
|
||||
|
||||
class LatLonPatch {
|
||||
public:
|
||||
LatLonPatch(Scalar, Scalar, Scalar, Scalar);
|
||||
LatLonPatch(const LatLon& center, const LatLon& halfSize);
|
||||
LatLonPatch(const LatLonPatch& patch);
|
||||
|
||||
|
||||
void setCenter(const LatLon&);
|
||||
void setHalfSize(const LatLon&);
|
||||
|
||||
|
||||
// Returns the minimal bounding radius that together with the LatLonPatch's
|
||||
// center point represents a sphere in which the patch is completely contained
|
||||
Scalar minimalBoundingRadius() const;
|
||||
|
||||
// Returns the area of the patch with unit radius
|
||||
Scalar unitArea() const;
|
||||
|
||||
|
||||
LatLon northWestCorner() const;
|
||||
LatLon northEastCorner() const;
|
||||
LatLon southWestCorner() const;
|
||||
LatLon southEastCorner() const;
|
||||
|
||||
LatLon center;
|
||||
LatLon halfSize;
|
||||
const LatLon& center() const;
|
||||
const LatLon& halfSize() const;
|
||||
|
||||
private:
|
||||
LatLon _center;
|
||||
LatLon _halfSize;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace openspace {
|
||||
: _leftRoot(new ChunkNode(*this, LEFT_HEMISPHERE))
|
||||
, _rightRoot(new ChunkNode(*this, RIGHT_HEMISPHERE))
|
||||
, globeRadius(1e7)
|
||||
, minSplitDepth(1)
|
||||
, minSplitDepth(2)
|
||||
, maxSplitDepth(22)
|
||||
, _rotation("rotation", "Rotation", 0, 0, 360)
|
||||
{
|
||||
@@ -73,6 +73,8 @@ namespace openspace {
|
||||
// Mainly for debugging purposes @AA
|
||||
addProperty(_rotation);
|
||||
|
||||
|
||||
globeRadius = dictionary.value<double>("Radius");
|
||||
|
||||
|
||||
// ---------
|
||||
@@ -85,8 +87,7 @@ namespace openspace {
|
||||
|
||||
_patchRenderer.reset(new LatLonPatchRenderer(geometry));
|
||||
|
||||
std::shared_ptr<FrustrumCuller> fc(new FrustrumCuller(1.3f));
|
||||
_patchRenderer->setFrustrumCuller(fc);
|
||||
_frustrumCuller = std::shared_ptr<FrustrumCuller>(new FrustrumCuller());
|
||||
|
||||
}
|
||||
|
||||
@@ -111,10 +112,19 @@ namespace openspace {
|
||||
return *_patchRenderer;
|
||||
}
|
||||
|
||||
FrustrumCuller& ChunkLodGlobe::getFrustrumCuller() {
|
||||
return *_frustrumCuller;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ChunkLodGlobe::render(const RenderData& data){
|
||||
minDistToCamera = INFINITY;
|
||||
_leftRoot->render(data);
|
||||
_rightRoot->render(data);
|
||||
ChunkIndex leftRootTileIndex = { 0, 0, 1 };
|
||||
_leftRoot->render(data, leftRootTileIndex);
|
||||
|
||||
ChunkIndex rightRootTileIndex = { 1, 0, 1 };
|
||||
_rightRoot->render(data, rightRootTileIndex);
|
||||
|
||||
//LDEBUG("min distnace to camera: " << minDistToCamera);
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace openspace {
|
||||
~ChunkLodGlobe();
|
||||
|
||||
PatchRenderer& getPatchRenderer();
|
||||
FrustrumCuller& getFrustrumCuller();
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
@@ -67,7 +68,7 @@ namespace openspace {
|
||||
|
||||
double minDistToCamera;
|
||||
|
||||
const Scalar globeRadius;
|
||||
Scalar globeRadius;
|
||||
|
||||
const int minSplitDepth;
|
||||
const int maxSplitDepth;
|
||||
@@ -81,6 +82,9 @@ namespace openspace {
|
||||
// Covers all positive longitudes
|
||||
std::unique_ptr<ChunkNode> _rightRoot;
|
||||
|
||||
// Frustrum culler
|
||||
std::shared_ptr<FrustrumCuller> _frustrumCuller;
|
||||
|
||||
// the patch used for actual rendering
|
||||
std::unique_ptr<PatchRenderer> _patchRenderer;
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace openspace {
|
||||
// Set patches to follow camera
|
||||
for (size_t i = 0; i < _patches.size(); i++)
|
||||
{
|
||||
_patches[i].center = LatLon::fromCartesian(data.camera.position().dvec3());
|
||||
_patches[i].setCenter(LatLon::fromCartesian(data.camera.position().dvec3()));
|
||||
}
|
||||
// render patches
|
||||
for (size_t i = 0; i < _patches.size(); i++)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*****************************************************************************************
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
@@ -34,8 +34,7 @@ namespace openspace {
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
FrustrumCuller::FrustrumCuller(float tolerance)
|
||||
: _tolerance(tolerance)
|
||||
FrustrumCuller::FrustrumCuller()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -45,23 +44,66 @@ namespace openspace {
|
||||
}
|
||||
|
||||
|
||||
bool FrustrumCuller::isVisible(const vec3& point, const mat4x4& modelViewProjection) {
|
||||
vec4 pointModelSpace(point, 1.0f);
|
||||
vec4 pointProjectionSpace = modelViewProjection * pointModelSpace;
|
||||
vec2 pointScreenSpace = (1.0f / pointProjectionSpace.w) * pointProjectionSpace.xy;
|
||||
|
||||
bool FrustrumCuller::isVisible(const RenderData& data, const vec3& point, const glm::vec2& marginScreenSpace) {
|
||||
|
||||
// just for readability
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
mat4 viewTransform = data.camera.combinedViewMatrix();
|
||||
mat4 modelViewProjectionTransform = data.camera.projectionMatrix()
|
||||
* viewTransform * modelTransform;
|
||||
|
||||
vec2 pointScreenSpace = transformToScreenSpace(point, modelViewProjectionTransform);
|
||||
return testPoint(pointScreenSpace, marginScreenSpace);
|
||||
}
|
||||
|
||||
|
||||
bool FrustrumCuller::isVisible(const RenderData& data, const LatLonPatch& patch, double radius) {
|
||||
// An axis aligned bounding box based on the patch's minimum boudning sphere is
|
||||
// used for testnig
|
||||
|
||||
// Calculate the MVP matrix
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
mat4 viewTransform = data.camera.combinedViewMatrix();
|
||||
mat4 modelViewProjectionTransform = data.camera.projectionMatrix()
|
||||
* viewTransform * modelTransform;
|
||||
|
||||
// Calculate the patch's center point in screen space
|
||||
vec4 patchCenterModelSpace = vec4(radius * patch.center().asUnitCartesian(), 1);
|
||||
vec4 patchCenterProjectionSpace = modelViewProjectionTransform * patchCenterModelSpace;
|
||||
vec2 pointScreenSpace = (1.0f / patchCenterProjectionSpace.w) * patchCenterProjectionSpace.xy;
|
||||
|
||||
// Calculate the screen space margin that represents an axis aligned bounding
|
||||
// box based on the patch's minimum boudning sphere
|
||||
double boundingRadius = radius * patch.minimalBoundingRadius();
|
||||
vec4 marginProjectionSpace = vec4(vec3(boundingRadius), 0) * data.camera.projectionMatrix();
|
||||
vec2 marginScreenSpace = (1.0f / patchCenterProjectionSpace.w) * marginProjectionSpace.xy;
|
||||
|
||||
// Test the bounding box by testing the center point and the corresponding margin
|
||||
return testPoint(pointScreenSpace, marginScreenSpace);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool FrustrumCuller::testPoint(const glm::vec2& pointScreenSpace,
|
||||
const glm::vec2& marginScreenSpace) const
|
||||
{
|
||||
|
||||
const vec2& p = pointScreenSpace;
|
||||
return ((-_tolerance < p.x && p.x < _tolerance) &
|
||||
(-_tolerance < p.y && p.y < _tolerance));
|
||||
|
||||
|
||||
vec2 cullBounds = vec2(1) + marginScreenSpace;
|
||||
return ((-cullBounds.x < p.x && p.x < cullBounds.x) &&
|
||||
(-cullBounds.y < p.y && p.y < cullBounds.y));
|
||||
}
|
||||
|
||||
bool FrustrumCuller::isVisible(const LatLonPatch& patch, double radius, const mat4x4& modelViewProjection) {
|
||||
return isVisible(radius * patch.northWestCorner().asUnitCartesian(), modelViewProjection)
|
||||
|| isVisible(radius * patch.northEastCorner().asUnitCartesian(), modelViewProjection)
|
||||
|| isVisible(radius * patch.southWestCorner().asUnitCartesian(), modelViewProjection)
|
||||
|| isVisible(radius * patch.southEastCorner().asUnitCartesian(), modelViewProjection);
|
||||
|
||||
glm::vec2 FrustrumCuller::transformToScreenSpace(const vec3& point,
|
||||
const mat4x4& modelViewProjection) const
|
||||
{
|
||||
vec4 pointProjectionSpace = modelViewProjection * vec4(point, 1.0f);
|
||||
vec2 pointScreenSpace = (1.0f / pointProjectionSpace.w) * pointProjectionSpace.xy;
|
||||
return pointScreenSpace;
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -45,15 +45,39 @@ namespace openspace {
|
||||
class FrustrumCuller {
|
||||
public:
|
||||
|
||||
FrustrumCuller(float tolerance = 1.0f);
|
||||
FrustrumCuller();
|
||||
~FrustrumCuller();
|
||||
|
||||
bool isVisible(const vec3& point, const mat4x4& modelViewProjection);
|
||||
bool isVisible(const LatLonPatch& patch, double radius, const mat4x4& modelViewProjection);
|
||||
/// Returns true if the point is inside the view frustrum defined in RenderData.
|
||||
/// The third argument marginScreenSpace is added to the default screen space
|
||||
/// boundaries. E.g. for marginScreenSpace = {0.2, 0.2}, all points with
|
||||
/// 1.2 < x,y < 1.2 would cause isVisible to return true.
|
||||
bool isVisible(
|
||||
const RenderData& data,
|
||||
const vec3& point,
|
||||
const vec2& marginScreenSpace = vec2(0));
|
||||
|
||||
|
||||
/// Returns false if the patch element is guaranteed to be outside the view
|
||||
/// frustrum, and true is the patch element MAY be inside the view frustrum.
|
||||
bool isVisible(
|
||||
const RenderData& data,
|
||||
const LatLonPatch& patch,
|
||||
double radius);
|
||||
|
||||
|
||||
protected:
|
||||
float _tolerance;
|
||||
private:
|
||||
|
||||
|
||||
/// Returns true if the point in screen space is inside the view frustrum.
|
||||
/// The optional screen space margin vector is used to resize area defining
|
||||
/// what is considered to be inside the view frustrum.
|
||||
bool testPoint(
|
||||
const glm::vec2& pointScreenSpace,
|
||||
const glm::vec2& marginScreenSpace) const;
|
||||
|
||||
|
||||
glm::vec2 transformToScreenSpace(const vec3& point, const mat4x4& modelViewProjection) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -69,9 +69,7 @@ namespace openspace {
|
||||
}
|
||||
}
|
||||
|
||||
void PatchRenderer::setFrustrumCuller(std::shared_ptr<FrustrumCuller> fc) {
|
||||
_frustrumCuller = fc;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// LATLON PATCH RENDERER //
|
||||
@@ -105,17 +103,6 @@ namespace openspace {
|
||||
mat4 modelViewProjectionTransform = data.camera.projectionMatrix()
|
||||
* viewTransform * modelTransform;
|
||||
|
||||
|
||||
// View frustrum culling
|
||||
if (_frustrumCuller != nullptr) {
|
||||
//LatLon center = patch.center;
|
||||
//vec3 centerPoint = radius * center.asUnitCartesian();
|
||||
if (!_frustrumCuller->isVisible(patch, radius, modelViewProjectionTransform)) {
|
||||
// dont render the patch
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the textures that should be used for rendering
|
||||
glm::ivec3 tileIndex = tileSet.getTileIndex(patch);
|
||||
LatLonPatch tilePatch = tileSet.getTilePositionAndScale(tileIndex);
|
||||
@@ -130,7 +117,7 @@ namespace openspace {
|
||||
LatLon swCorner = patch.southWestCorner();
|
||||
_programObject->setUniform("modelViewProjectionTransform", modelViewProjectionTransform);
|
||||
_programObject->setUniform("minLatLon", vec2(swCorner.toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", 2.0f * vec2(patch.halfSize.toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", 2.0f * vec2(patch.halfSize().toLonLatVec2()));
|
||||
_programObject->setUniform("globeRadius", float(radius));
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -174,18 +161,19 @@ namespace openspace {
|
||||
|
||||
// Snap patch position
|
||||
int segmentsPerPatch = 32;
|
||||
LatLon halfSize = patch.halfSize();
|
||||
LatLon stepSize = LatLon(
|
||||
patch.halfSize.lat * 2 / segmentsPerPatch,
|
||||
patch.halfSize.lon * 2 / segmentsPerPatch);
|
||||
halfSize.lat * 2 / segmentsPerPatch,
|
||||
halfSize.lon * 2 / segmentsPerPatch);
|
||||
ivec2 patchesToCoverGlobe = ivec2(
|
||||
M_PI / (patch.halfSize.lat * 2) + 0.5,
|
||||
M_PI * 2 / (patch.halfSize.lon * 2) + 0.5);
|
||||
M_PI / (halfSize.lat * 2) + 0.5,
|
||||
M_PI * 2 / (halfSize.lon * 2) + 0.5);
|
||||
ivec2 intSnapCoord = ivec2(
|
||||
patch.center.lat / (M_PI * 2) * segmentsPerPatch * patchesToCoverGlobe.y,
|
||||
patch.center.lon / (M_PI) * segmentsPerPatch * patchesToCoverGlobe.x);
|
||||
patch.center().lat / (M_PI * 2) * segmentsPerPatch * patchesToCoverGlobe.y,
|
||||
patch.center().lon / (M_PI) * segmentsPerPatch * patchesToCoverGlobe.x);
|
||||
LatLon swCorner = LatLon(
|
||||
stepSize.lat * intSnapCoord.x - patch.halfSize.lat,
|
||||
stepSize.lon * intSnapCoord.y - patch.halfSize.lon);
|
||||
stepSize.lat * intSnapCoord.x - halfSize.lat,
|
||||
stepSize.lon * intSnapCoord.y - halfSize.lon);
|
||||
|
||||
ivec2 contraction = ivec2(intSnapCoord.y % 2, intSnapCoord.x % 2);
|
||||
|
||||
@@ -207,7 +195,7 @@ namespace openspace {
|
||||
|
||||
_programObject->setUniform("modelViewProjectionTransform", data.camera.projectionMatrix() * viewTransform * modelTransform);
|
||||
_programObject->setUniform("minLatLon", vec2(swCorner.toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", 2.0f * vec2(patch.halfSize.toLonLatVec2()));
|
||||
_programObject->setUniform("lonLatScalingFactor", 2.0f * vec2(halfSize.toLonLatVec2()));
|
||||
_programObject->setUniform("globeRadius", float(radius));
|
||||
_programObject->setUniform("contraction", contraction);
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ namespace openspace {
|
||||
|
||||
unique_ptr<ProgramObject> _programObject;
|
||||
shared_ptr<Geometry> _geometry;
|
||||
shared_ptr<FrustrumCuller> _frustrumCuller;
|
||||
|
||||
TextureTileSet tileSet;
|
||||
};
|
||||
|
||||
@@ -58,10 +58,11 @@ namespace openspace {
|
||||
glm::ivec3 TextureTileSet::getTileIndex(LatLonPatch patch)
|
||||
{
|
||||
int level = log2(static_cast<int>(glm::max(
|
||||
_sizeLevel0.lat / patch.halfSize.lat * 2,
|
||||
_sizeLevel0.lon / patch.halfSize.lon * 2)));
|
||||
_sizeLevel0.lat / patch.halfSize().lat * 2,
|
||||
_sizeLevel0.lon / patch.halfSize().lon * 2)));
|
||||
Vec2 TileSize = _sizeLevel0.toLonLatVec2() / pow(2, level);
|
||||
glm::ivec2 tileIndex = -(patch.northWestCorner().toLonLatVec2() + _offsetLevel0.toLonLatVec2()) / TileSize;
|
||||
|
||||
return glm::ivec3(tileIndex, level);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user