Created Chunk LOD Globe. Currently renders patches at constant depth

This commit is contained in:
Erik Broberg
2016-04-06 17:10:29 -04:00
parent 25a917bf1a
commit efe2bef2d4
13 changed files with 373 additions and 37 deletions

View File

@@ -36,10 +36,11 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/latlonpatch.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/clipmapglobe.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunklodglobe.h
${CMAKE_CURRENT_SOURCE_DIR}/util/converter.h
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.h
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.inl
${CMAKE_CURRENT_SOURCE_DIR}/util/converter.h
)
set(SOURCE_FILES
@@ -51,6 +52,9 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/latlonpatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/clipmapglobe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunklodglobe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/datastructures/chunknode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/util/converter.cpp

View File

@@ -23,7 +23,7 @@
****************************************************************************************/
#include <modules/globebrowsing/datastructures/chunknode.h>
#include <modules/globebrowsing/rendering/chunklodglobe.h>
namespace openspace {
@@ -36,8 +36,12 @@ BoundingRect::BoundingRect(const Vec2& center, const Vec2& halfSize)
ChunkNode::ChunkNode(const BoundingRect& bounds, ChunkNode* parent)
: bounds(bounds), _parent(parent)
ChunkNode::ChunkNode(ChunkLodGlobe& owner, const BoundingRect& bounds, ChunkNode* parent)
: _owner(owner)
, bounds(bounds)
, _parent(parent)
{
_children[0] = nullptr;
_children[1] = nullptr;
@@ -58,23 +62,88 @@ bool ChunkNode::isLeaf() const {
}
void ChunkNode::split() {
// Defining short handles for center, halfSize and quarterSize
const Vec2& c = bounds.center;
const Vec2& hs =bounds.halfSize;
Vec2 qs = 0.5 * bounds.halfSize;
// Subdivide bounds
BoundingRect nwBounds = BoundingRect(c + Vec2(-qs.x, -qs.y), qs);
BoundingRect neBounds = BoundingRect(c + Vec2(+qs.x, -qs.y), qs);
BoundingRect swBounds = BoundingRect(c + Vec2(-qs.x, +qs.y), qs);
BoundingRect seBounds = BoundingRect(c + Vec2(+qs.x, +qs.y), qs);
bool ChunkNode::initialize() {
if (!isLeaf()) {
for (int i = 0; i < 4; ++i) {
_children[i]->initialize();
}
}
return isReady();
}
// Create new chunk nodes
_children[Quad::NORTH_WEST] = std::unique_ptr<ChunkNode>(new ChunkNode(nwBounds, this));
_children[Quad::NORTH_EAST] = std::unique_ptr<ChunkNode>(new ChunkNode(neBounds, this));
_children[Quad::SOUTH_WEST] = std::unique_ptr<ChunkNode>(new ChunkNode(swBounds, this));
_children[Quad::SOUTH_EAST] = std::unique_ptr<ChunkNode>(new ChunkNode(seBounds, this));
bool ChunkNode::deinitialize() {
if (!isLeaf()) {
for (int i = 0; i < 4; ++i) {
_children[i]->deinitialize();
}
}
return true;
}
bool ChunkNode::isReady() const{
bool ready = true;
return ready;
}
void ChunkNode::render(const RenderData& data) {
internalRender(data, 0);
}
void ChunkNode::internalRender(const RenderData& data, int currLevel) {
if (isLeaf()) {
LatLonPatch& templatePatch = _owner.getTemplatePatch();
templatePatch.setPositionLatLon(bounds.center);
templatePatch.setSizeLatLon(bounds.halfSize);
templatePatch.render(data);
}
else {
for (int i = 0; i < 4; ++i) {
_children[i]->internalRender(data, currLevel+1);
}
}
}
void ChunkNode::update(const UpdateData& data) {
internalUpdate(data, 0);
}
void ChunkNode::internalUpdate(const UpdateData& data, int currLevel) {
if (!isLeaf()) {
for (int i = 0; i < 4; ++i) {
_children[i]->internalUpdate(data, currLevel + 1);
}
}
}
void ChunkNode::split(int depth) {
if (depth > 0 && isLeaf()) {
// Defining short handles for center, halfSize and quarterSize
const Vec2& c = bounds.center;
const Vec2& hs = bounds.halfSize;
Vec2 qs = 0.5 * bounds.halfSize;
// Subdivide bounds
BoundingRect nwBounds = BoundingRect(c + Vec2(-qs.x, -qs.y), qs);
BoundingRect neBounds = BoundingRect(c + Vec2(+qs.x, -qs.y), qs);
BoundingRect swBounds = BoundingRect(c + Vec2(-qs.x, +qs.y), qs);
BoundingRect seBounds = BoundingRect(c + Vec2(+qs.x, +qs.y), 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));
}
if (depth - 1 > 0) {
for (int i = 0; i < 4; ++i) {
_children[i]->split(depth - 1);
}
}
}

View File

@@ -30,6 +30,16 @@
#include <memory>
#include <ostream>
#include <modules/globebrowsing/rendering/latlonpatch.h>
// forward declaration
namespace openspace {
class ChunkLodGlobe;
}
// Using double precision
typedef double Scalar;
typedef glm::dvec2 Vec2;
@@ -56,28 +66,41 @@ struct BoundingRect {
class ChunkNode {
class ChunkNode : public Renderable{
public:
ChunkNode(const BoundingRect&, ChunkNode* parent = nullptr);
ChunkNode(ChunkLodGlobe&, const BoundingRect&, ChunkNode* parent = nullptr);
~ChunkNode();
void split();
void split(int depth = 1);
void merge();
bool isRoot() const;
bool isLeaf() const;
const ChunkNode& getChild(Quad quad) const;
const BoundingRect bounds;
bool initialize() override;
bool deinitialize() override;
bool isReady() const override;
void render(const RenderData& data) override;
void update(const UpdateData& data) override;
void internalRender(const RenderData& data, int currLevel);
void internalUpdate(const UpdateData& data, int currLevel);
private:
ChunkNode* _parent;
std::unique_ptr<ChunkNode> _children[4];
ChunkLodGlobe& _owner;
};
@@ -85,7 +108,5 @@ private:
} // namespace openspace
#include <modules/globebrowsing/datastructures/chunknode.inl>
#endif // __QUADTREE_H__

View File

@@ -37,7 +37,7 @@
namespace openspace {
GlobeBrowsingModule::GlobeBrowsingModule()
: OpenSpaceModule("GlobeBrowsing")
: OpenSpaceModule("GlobeBrowsing")
{}
void GlobeBrowsingModule::internalInitialize() {

View File

@@ -0,0 +1,131 @@
/*****************************************************************************************
* *
* 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 <modules/globebrowsing/rendering/chunklodglobe.h>
#include <modules/globebrowsing/util/converter.h>
// open space includes
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/spicemanager.h>
#include <openspace/scene/scenegraphnode.h>
// ghoul includes
#include <ghoul/misc/assert.h>
#define _USE_MATH_DEFINES
#include <math.h>
namespace {
const std::string _loggerCat = "ChunkLodGlobe";
const std::string keyFrame = "Frame";
const std::string keyGeometry = "Geometry";
const std::string keyShading = "PerformShading";
const std::string keyBody = "Body";
}
namespace openspace {
const BoundingRect ChunkLodGlobe::LEFT_HEMISPHERE = BoundingRect(0, -M_PI/2, M_PI/2, M_PI/2);
const BoundingRect ChunkLodGlobe::RIGHT_HEMISPHERE = BoundingRect(0, M_PI/2, M_PI/2, M_PI/2);
ChunkLodGlobe::ChunkLodGlobe(const ghoul::Dictionary& dictionary)
: _leftRoot(new ChunkNode(*this, LEFT_HEMISPHERE))
, _rightRoot(new ChunkNode(*this, RIGHT_HEMISPHERE))
, _templatePatch(10,10, 0, 0, 0, 0)
, _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);
// Mainly for debugging purposes @AA
addProperty(_rotation);
// ----- specific for this class only ------ //
_leftRoot->split(5);
_rightRoot->split(5);
}
ChunkLodGlobe::~ChunkLodGlobe() {
}
LatLonPatch& ChunkLodGlobe::getTemplatePatch() {
return _templatePatch;
}
bool ChunkLodGlobe::initialize() {
_templatePatch.initialize();
_leftRoot->initialize();
_rightRoot->initialize();
return isReady();
}
bool ChunkLodGlobe::deinitialize() {
_templatePatch.deinitialize();
_leftRoot->deinitialize();
_rightRoot->deinitialize();
return true;
}
bool ChunkLodGlobe::isReady() const {
bool ready = true;
ready &= _templatePatch.isReady();
ready &= _leftRoot->isReady();
ready &= _rightRoot->isReady();
return ready;
}
void ChunkLodGlobe::render(const RenderData& data)
{
// Set patch to follow camera
//_patch.setPositionLatLon(converter::cartesianToLatLon(data.camera.position().dvec3()));
// render
_leftRoot->render(data);
_rightRoot->render(data);
}
void ChunkLodGlobe::update(const UpdateData& data) {
_templatePatch.update(data);
// set spice-orientation in accordance to timestamp
_stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time);
_time = data.time;
}
} // namespace openspace

View File

@@ -0,0 +1,92 @@
/*****************************************************************************************
* *
* 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_LOD_GLOBE__
#define __CHUNK_LOD_GLOBE__
#include <memory>
// open space includes
#include <openspace/rendering/renderable.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/util/updatestructures.h>
#include <modules/globebrowsing/datastructures/chunknode.h>
#include <modules/globebrowsing/rendering/geometry.h>
#include <modules/globebrowsing/rendering/gridgeometry.h>
#include <modules/globebrowsing/rendering/distanceswitch.h>
#include <modules/globebrowsing/rendering/latlonpatch.h>
namespace ghoul {
namespace opengl {
class ProgramObject;
}
}
namespace openspace {
class ChunkLodGlobe :
public Renderable, public std::enable_shared_from_this<ChunkLodGlobe>{
public:
ChunkLodGlobe(const ghoul::Dictionary& dictionary);
~ChunkLodGlobe();
LatLonPatch& getTemplatePatch();
bool initialize() override;
bool deinitialize() override;
bool isReady() const override;
void render(const RenderData& data) override;
void update(const UpdateData& data) override;
private:
// Covers all negative longitudes
std::unique_ptr<ChunkNode> _leftRoot;
// Covers all positive longitudes
std::unique_ptr<ChunkNode> _rightRoot;
// the patch used for actual rendering
LatLonPatch _templatePatch;
static const BoundingRect LEFT_HEMISPHERE;
static const BoundingRect RIGHT_HEMISPHERE;
properties::IntProperty _rotation;
glm::dmat3 _stateMatrix;
std::string _frame;
std::string _target;
double _time;
};
} // namespace openspace
#endif // __CHUNK_LOD_GLOBE__

View File

@@ -31,11 +31,14 @@
#include <openspace/properties/stringproperty.h>
#include <openspace/util/updatestructures.h>
#include <modules/globebrowsing/rendering/geometry.h>
#include <modules/globebrowsing/rendering/gridgeometry.h>
#include <modules/globebrowsing/rendering/distanceswitch.h>
#include <modules/globebrowsing/rendering/latlonpatch.h>
namespace ghoul {
namespace opengl {
class ProgramObject;

View File

@@ -86,13 +86,13 @@ std::vector<GLuint> GridGeometry::CreateElements(unsigned int xRes, unsigned int
// add upper triangle
elements.push_back(v00);
elements.push_back(v10);
elements.push_back(v01);
elements.push_back(v10);
// add lower triangle
elements.push_back(v01);
elements.push_back(v10);
elements.push_back(v11);
elements.push_back(v10);
//LDEBUG(v00 << ", " << v10 << ", " << v01);
//LDEBUG(v01 << ", " << v10 << ", " << v11);

View File

@@ -110,7 +110,7 @@ namespace openspace {
// TODO : Not sure if double precision will be needed for all these calculations
// Using doubles in case but might slow things down.
// TODO : Need to get the radius of the globe
double r = 6e6;
double r = 6.3e6;
// Create control points (double)
glm::dvec3 p00, p01, p10, p11;
@@ -148,10 +148,13 @@ namespace openspace {
glm::dvec3 camPos = data.camera.position().dvec3();
glm::dvec3 camDir = glm::normalize(position - camPos);
glm::dvec3 camUp = glm::dvec3(0,1,0);// data.camera.lookUpVector();
// Get camera transform matrix (double precision)
glm::dmat4 viewTransform = glm::inverse(glm::translate(glm::dmat4(1.0), camPos));
//glm::dmat4 viewTransform = glm::lookAt(camPos, camPos + camDir, camUp);
viewTransform = glm::dmat4( data.camera.viewRotationMatrix()) * viewTransform;
viewTransform = glm::dmat4(data.camera.viewRotationMatrix())*viewTransform;
// Transform control points to camera space
p00 = glm::dvec3(viewTransform * glm::dvec4(p00, 1.0));
p10 = glm::dvec3(viewTransform * glm::dvec4(p10, 1.0));
@@ -169,8 +172,8 @@ namespace openspace {
_programObject->setUniform("Projection", data.camera.projectionMatrix());
// Render triangles (use texture coordinates to interpolate to new positions)
glDisable(GL_CULL_FACE);
//glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// render
_grid.drawUsingActiveProgram();
@@ -187,4 +190,9 @@ namespace openspace {
_posLatLon = posLatLon;
}
void LatLonPatch::setSizeLatLon(glm::dvec2 sizeLatLon) {
_sizeLatLon = sizeLatLon;
}
} // namespace openspace

View File

@@ -60,6 +60,7 @@ namespace openspace {
void update(const UpdateData& data) override;
void setPositionLatLon(glm::dvec2 posLatLon);
void setSizeLatLon(glm::dvec2 posLatLon);
private:
std::unique_ptr<ghoul::opengl::ProgramObject> _programObject;

View File

@@ -26,6 +26,7 @@
#include <modules/globebrowsing/rendering/globemesh.h>
#include <modules/globebrowsing/rendering/clipmapglobe.h>
#include <modules/globebrowsing/rendering/chunklodglobe.h>
// open space includes
#include <openspace/engine/openspaceengine.h>
@@ -69,7 +70,8 @@ namespace openspace {
// Mainly for debugging purposes @AA
addProperty(_rotation);
addSwitchValue(std::shared_ptr<ClipMapGlobe>(new ClipMapGlobe(dictionary)), 1e9);
//addSwitchValue(std::shared_ptr<ClipMapGlobe>(new ClipMapGlobe(dictionary)), 1e9);
addSwitchValue(std::shared_ptr<ChunkLodGlobe>(new ChunkLodGlobe(dictionary)), 1e9);
addSwitchValue(std::shared_ptr<GlobeMesh>(new GlobeMesh(dictionary)), 1e10);
}

View File

@@ -34,11 +34,14 @@ uniform vec3 p11;
layout(location = 1) in vec2 in_UV;
out vec4 vs_position;
out vec2 vs_uv;
#include "PowerScaling/powerScaling_vs.hglsl"
void main()
{
vs_uv = in_UV;
// Bilinear interpolation
vec3 p0 = (1 - in_UV.x) * p00 + in_UV.x * p10;
vec3 p1 = (1 - in_UV.x) * p01 + in_UV.x * p11;

View File

@@ -36,6 +36,8 @@ uniform sampler2D texture1;
uniform sampler2D nightTex;
in vec4 vs_position;
in vec2 vs_uv;
#include "PowerScaling/powerScaling_fs.hglsl"
#include "fragment.glsl"
@@ -43,7 +45,7 @@ in vec4 vs_position;
Fragment getFragment() {
Fragment frag;
frag.color = vec4(1,1,1,1);
frag.color = vec4(vs_uv,1,1);
frag.depth = pscDepth(vs_position);
return frag;