mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-09 04:59:56 -06:00
Refactored RenderableLatLonPatch to a simple base class PatchRenderer
This commit is contained in:
@@ -33,7 +33,7 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/geometry.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gridgeometry.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/globemesh.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablelatlonpatch.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/patchrenderer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/clipmapglobe.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunklodglobe.h
|
||||
|
||||
@@ -50,7 +50,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/geometry.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/gridgeometry.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/globemesh.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablelatlonpatch.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/patchrenderer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/clipmapglobe.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunklodglobe.cpp
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace openspace {
|
||||
|
||||
int ChunkNode::instanceCount = 0;
|
||||
|
||||
ChunkNode::ChunkNode(ChunkLodGlobe& owner, const LatLonPatch& bounds, ChunkNode* parent)
|
||||
ChunkNode::ChunkNode(ChunkLodGlobe& owner, const LatLonPatch& patch, ChunkNode* parent)
|
||||
: _owner(owner)
|
||||
, bounds(bounds)
|
||||
, _patch(patch)
|
||||
, _parent(parent)
|
||||
{
|
||||
_children[0] = nullptr;
|
||||
@@ -126,9 +126,8 @@ bool ChunkNode::internalUpdateChunkTree(const RenderData& data, int depth) {
|
||||
|
||||
void ChunkNode::internalRender(const RenderData& data, int currLevel) {
|
||||
if (isLeaf()) {
|
||||
RenderableLatLonPatch& templatePatch = _owner.getTemplatePatch();
|
||||
templatePatch.setPatch(bounds);
|
||||
templatePatch.render(data);
|
||||
PatchRenderer& patchRenderer = _owner.getPatchRenderer();
|
||||
patchRenderer.renderPatch(_patch, data, _owner.globeRadius);
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@@ -138,7 +137,7 @@ void ChunkNode::internalRender(const RenderData& data, int currLevel) {
|
||||
}
|
||||
|
||||
int ChunkNode::desiredSplitDepth(const RenderData& data) {
|
||||
Vec3 normal = bounds.center.asUnitCartesian();
|
||||
Vec3 normal = _patch.center.asUnitCartesian();
|
||||
Vec3 pos = data.position.dvec3() + _owner.globeRadius * normal;
|
||||
|
||||
// Temporay ugly fix for Camera::position() is broken.
|
||||
@@ -160,7 +159,7 @@ int ChunkNode::desiredSplitDepth(const RenderData& data) {
|
||||
|
||||
int depthRange = _owner.maxSplitDepth - _owner.minSplitDepth;
|
||||
|
||||
Scalar scaleFactor = depthRange * _owner.globeRadius * 25*bounds.unitArea();
|
||||
Scalar scaleFactor = depthRange * _owner.globeRadius * 25*_patch.unitArea();
|
||||
|
||||
int desiredDepth = _owner.minSplitDepth + floor(scaleFactor / distance);
|
||||
return glm::clamp(desiredDepth, _owner.minSplitDepth, _owner.maxSplitDepth);
|
||||
@@ -185,8 +184,8 @@ void ChunkNode::split(int depth) {
|
||||
if (depth > 0 && isLeaf()) {
|
||||
|
||||
// Defining short handles for center, halfSize and quarterSize
|
||||
const LatLon& c = bounds.center;
|
||||
const LatLon& hs = bounds.halfSize;
|
||||
const LatLon& c = _patch.center;
|
||||
const LatLon& hs = _patch.halfSize;
|
||||
LatLon qs = LatLon(0.5 * hs.lat, 0.5 * hs.lon);
|
||||
|
||||
// Subdivide bounds
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <ostream>
|
||||
|
||||
#include <modules/globebrowsing/datastructures/latlon.h>
|
||||
#include <modules/globebrowsing/rendering/renderablelatlonpatch.h>
|
||||
#include <modules/globebrowsing/rendering/patchrenderer.h>
|
||||
|
||||
|
||||
|
||||
@@ -75,8 +75,6 @@ public:
|
||||
void render(const RenderData& data) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
LatLonPatch bounds;
|
||||
|
||||
static int instanceCount;
|
||||
|
||||
private:
|
||||
@@ -92,12 +90,10 @@ private:
|
||||
|
||||
ChunkLodGlobe& _owner;
|
||||
|
||||
|
||||
|
||||
LatLonPatch _patch;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ namespace openspace {
|
||||
: _leftRoot(new ChunkNode(*this, LEFT_HEMISPHERE))
|
||||
, _rightRoot(new ChunkNode(*this, RIGHT_HEMISPHERE))
|
||||
, globeRadius(6.3e6)
|
||||
, _templatePatch(10,10, 0, 0, 0, 0, globeRadius)
|
||||
, minSplitDepth(1)
|
||||
, maxSplitDepth(7)
|
||||
, _rotation("rotation", "Rotation", 0, 0, 360)
|
||||
@@ -73,25 +72,30 @@ namespace openspace {
|
||||
|
||||
// Mainly for debugging purposes @AA
|
||||
addProperty(_rotation);
|
||||
|
||||
// ---------
|
||||
// init Renderer
|
||||
auto geometry = std::shared_ptr<Geometry>(new GridGeometry(10, 10,
|
||||
Geometry::Positions::No,
|
||||
Geometry::TextureCoordinates::Yes,
|
||||
Geometry::Normals::No));
|
||||
|
||||
auto patchRenderer = new LatLonPatchRenderer(geometry);
|
||||
_patchRenderer.reset(patchRenderer);
|
||||
|
||||
}
|
||||
|
||||
ChunkLodGlobe::~ChunkLodGlobe() {
|
||||
|
||||
}
|
||||
|
||||
RenderableLatLonPatch& 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;
|
||||
@@ -99,12 +103,15 @@ namespace openspace {
|
||||
|
||||
bool ChunkLodGlobe::isReady() const {
|
||||
bool ready = true;
|
||||
ready &= _templatePatch.isReady();
|
||||
ready &= _leftRoot->isReady();
|
||||
ready &= _rightRoot->isReady();
|
||||
return ready;
|
||||
}
|
||||
|
||||
PatchRenderer& ChunkLodGlobe::getPatchRenderer() {
|
||||
return *_patchRenderer;
|
||||
}
|
||||
|
||||
void ChunkLodGlobe::render(const RenderData& data){
|
||||
minDistToCamera = INFINITY;
|
||||
_leftRoot->render(data);
|
||||
@@ -119,7 +126,6 @@ namespace openspace {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -32,12 +32,15 @@
|
||||
|
||||
|
||||
// open space includes
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#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/renderablelatlonpatch.h>
|
||||
#include <modules/globebrowsing/rendering/patchrenderer.h>
|
||||
|
||||
namespace ghoul {
|
||||
namespace opengl {
|
||||
@@ -53,7 +56,7 @@ namespace openspace {
|
||||
ChunkLodGlobe(const ghoul::Dictionary& dictionary);
|
||||
~ChunkLodGlobe();
|
||||
|
||||
RenderableLatLonPatch& getTemplatePatch();
|
||||
PatchRenderer& getPatchRenderer();
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
@@ -79,7 +82,7 @@ namespace openspace {
|
||||
std::unique_ptr<ChunkNode> _rightRoot;
|
||||
|
||||
// the patch used for actual rendering
|
||||
RenderableLatLonPatch _templatePatch;
|
||||
std::unique_ptr<PatchRenderer> _patchRenderer;
|
||||
|
||||
|
||||
static const LatLonPatch LEFT_HEMISPHERE;
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/rendering/clipmapglobe.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
#include <modules/globebrowsing/rendering/clipmapglobe.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>
|
||||
@@ -36,8 +38,6 @@
|
||||
// ghoul includes
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "ClipMapGlobe";
|
||||
@@ -51,8 +51,7 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
ClipMapGlobe::ClipMapGlobe(const ghoul::Dictionary& dictionary)
|
||||
: _patch(40, 40, 0, 0, M_PI / 4, M_PI / 4, 6.3e6)
|
||||
, _patch1(40, 40, 0, 0, M_PI / 8, M_PI / 8, 6.3e6)
|
||||
: _patch(0.0, 0.0, M_PI / 4, M_PI / 4)
|
||||
, _rotation("rotation", "Rotation", 0, 0, 360)
|
||||
{
|
||||
std::string name;
|
||||
@@ -68,27 +67,31 @@ namespace openspace {
|
||||
|
||||
// Mainly for debugging purposes @AA
|
||||
addProperty(_rotation);
|
||||
|
||||
// ---------
|
||||
// init Renderer
|
||||
auto geometry = std::shared_ptr<Geometry>(new GridGeometry(10, 10,
|
||||
Geometry::Positions::No,
|
||||
Geometry::TextureCoordinates::Yes,
|
||||
Geometry::Normals::No));
|
||||
|
||||
auto patchRenderer = new LatLonPatchRenderer(geometry);
|
||||
_patchRenderer.reset(patchRenderer);
|
||||
}
|
||||
|
||||
ClipMapGlobe::~ClipMapGlobe() {
|
||||
}
|
||||
|
||||
bool ClipMapGlobe::initialize() {
|
||||
_patch.initialize();
|
||||
_patch1.initialize();
|
||||
return isReady();
|
||||
}
|
||||
|
||||
bool ClipMapGlobe::deinitialize() {
|
||||
_patch.deinitialize();
|
||||
_patch1.deinitialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClipMapGlobe::isReady() const {
|
||||
bool ready = true;
|
||||
ready &= _patch.isReady();
|
||||
ready &= _patch1.isReady();
|
||||
return ready;
|
||||
}
|
||||
|
||||
@@ -110,14 +113,12 @@ namespace openspace {
|
||||
//_patch.getPatch().setCenter(LatLon::fromCartesian(data.camera.position().dvec3()));
|
||||
//_patch1.getPatch().setCenter(LatLon::fromCartesian(data.camera.position().dvec3()));
|
||||
// render
|
||||
|
||||
_patch.render(data);
|
||||
_patch1.render(data);
|
||||
Vec3 cameraPos = data.camera.position().dvec3();
|
||||
_patch.center = LatLon::fromCartesian(cameraPos);
|
||||
_patchRenderer->renderPatch(_patch, data, 6.3e6);
|
||||
}
|
||||
|
||||
void ClipMapGlobe::update(const UpdateData& data) {
|
||||
_patch.update(data);
|
||||
_patch1.update(data);
|
||||
// set spice-orientation in accordance to timestamp
|
||||
_stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time);
|
||||
_time = data.time;
|
||||
|
||||
@@ -27,15 +27,13 @@
|
||||
|
||||
// open space includes
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#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/renderablelatlonpatch.h>
|
||||
#include <modules/globebrowsing/rendering/patchrenderer.h>
|
||||
|
||||
|
||||
|
||||
@@ -60,8 +58,9 @@ namespace openspace {
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
private:
|
||||
RenderableLatLonPatch _patch;
|
||||
RenderableLatLonPatch _patch1;
|
||||
std::unique_ptr<PatchRenderer> _patchRenderer;
|
||||
LatLonPatch _patch;
|
||||
|
||||
|
||||
properties::IntProperty _rotation;
|
||||
|
||||
|
||||
125
modules/globebrowsing/rendering/patchrenderer.cpp
Normal file
125
modules/globebrowsing/rendering/patchrenderer.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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/patchrenderer.h>
|
||||
#include <modules/globebrowsing/util/converter.h>
|
||||
|
||||
// open space includes
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
|
||||
// ghoul includes
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "LatLonPatch";
|
||||
|
||||
const std::string keyFrame = "Frame";
|
||||
const std::string keyGeometry = "Geometry";
|
||||
const std::string keyShading = "PerformShading";
|
||||
|
||||
const std::string keyBody = "Body";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
PatchRenderer::PatchRenderer(shared_ptr<Geometry> geometry)
|
||||
: _geometry(geometry)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PatchRenderer::~PatchRenderer() {
|
||||
if (_programObject) {
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
renderEngine.removeRenderProgram(_programObject);
|
||||
_programObject = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PatchRenderer::renderPatch(const LatLonPatch& patch, const RenderData& data, double radius) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// LATLON PATCH RENDERER //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
LatLonPatchRenderer::LatLonPatchRenderer(shared_ptr<Geometry> geometry)
|
||||
: PatchRenderer(geometry)
|
||||
{
|
||||
_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);
|
||||
}
|
||||
|
||||
void LatLonPatchRenderer::renderPatch(
|
||||
const LatLonPatch& patch, const RenderData& data, double radius)
|
||||
{
|
||||
// activate shader
|
||||
_programObject->activate();
|
||||
using namespace glm;
|
||||
|
||||
|
||||
// Get camera transform matrix
|
||||
// TODO : Should only need to fetch the camera transform and use directly
|
||||
// but this is not currently possible in the camera class.
|
||||
vec3 cameraPosition = data.camera.position().vec3();
|
||||
mat4 viewTransform = inverse(translate(mat4(1.0), cameraPosition));
|
||||
viewTransform = mat4(data.camera.viewRotationMatrix()) * viewTransform;
|
||||
|
||||
// TODO : Model transform should be fetched as a matrix directly.
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
|
||||
LatLon swCorner = patch.southWestCorner();
|
||||
|
||||
_programObject->setUniform("modelViewProjectionTransform", data.camera.projectionMatrix() * viewTransform * modelTransform);
|
||||
_programObject->setUniform("minLatLon", vec2(swCorner.lat, swCorner.lon));
|
||||
_programObject->setUniform("latLonScalingFactor", 2.0f * vec2(patch.halfSize.lat, patch.halfSize.lon));
|
||||
_programObject->setUniform("globeRadius", float(radius));
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// render
|
||||
_geometry->drawUsingActiveProgram();
|
||||
|
||||
// disable shader
|
||||
_programObject->deactivate();
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef __LATLONPATCH_H__
|
||||
#define __LATLONPATCH_H__
|
||||
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
// open space includes
|
||||
@@ -34,6 +35,8 @@
|
||||
#include <modules/globebrowsing/datastructures/latlon.h>
|
||||
#include <modules/globebrowsing/rendering/gridgeometry.h>
|
||||
|
||||
|
||||
|
||||
namespace ghoul {
|
||||
namespace opengl {
|
||||
class ProgramObject;
|
||||
@@ -44,66 +47,42 @@ namespace opengl {
|
||||
namespace openspace {
|
||||
|
||||
class LonLatPatch;
|
||||
class Geometry;
|
||||
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
using ghoul::opengl::ProgramObject;
|
||||
|
||||
class RenderableLatLonPatch : public Renderable
|
||||
{
|
||||
class PatchRenderer {
|
||||
public:
|
||||
RenderableLatLonPatch(
|
||||
unsigned int xRes,
|
||||
unsigned int yRes,
|
||||
double posLat,
|
||||
double posLon,
|
||||
double sizeLat,
|
||||
double sizeLon,
|
||||
double globeRadius);
|
||||
|
||||
~RenderableLatLonPatch();
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
bool isReady() const override;
|
||||
|
||||
void render(const RenderData& data) override;
|
||||
void update(const UpdateData& data) override;
|
||||
|
||||
void setPositionLatLon(glm::dvec2 posLatLon);
|
||||
void setSizeLatLon(glm::dvec2 posLatLon);
|
||||
void setGlobeRadius(double globeRadius);
|
||||
PatchRenderer(shared_ptr<Geometry>);
|
||||
~PatchRenderer();
|
||||
|
||||
void setPatch(LatLonPatch patch);
|
||||
LatLonPatch getPatch();
|
||||
|
||||
|
||||
glm::dvec3 calculateCornerPointBottomLeft();
|
||||
glm::dvec3 calculateCornerPointBottomRight();
|
||||
glm::dvec3 calculateCornerPointTopLeft();
|
||||
glm::dvec3 calculateCornerPointTopRight();
|
||||
|
||||
//!
|
||||
//! Finds a third control point between the two parameter points assuming
|
||||
//! they both lie on a sphere with the origin in the center.
|
||||
//! The three control points will then be used to interpolate NURBS curves
|
||||
//! that exactly describes circle segments.
|
||||
//! \param p0 is the first control point
|
||||
//! \param n0 is the normal corresponding to the first control point. The normal
|
||||
//! should point out from the center of the circle and be normalized
|
||||
//! \param p2 is the third control point
|
||||
//! \param n2 is the normal corresponding to the third control point. The normal
|
||||
//! should point out from the center of the circle and be normalized
|
||||
//! \returns the second control point to be used for circle segment interpolation.
|
||||
//!
|
||||
glm::dvec3 calculateCenterPoint(glm::dvec3 p0, glm::dvec3 n0, glm::dvec3 p2, glm::dvec3 n2);
|
||||
|
||||
virtual void renderPatch(const LatLonPatch& patch, const RenderData& data, double radius);
|
||||
|
||||
private:
|
||||
LatLonPatch _patch;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _programObject;
|
||||
protected:
|
||||
|
||||
double _globeRadius;
|
||||
unique_ptr<ProgramObject> _programObject;
|
||||
shared_ptr<Geometry> _geometry;
|
||||
|
||||
GridGeometry _grid;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// PATCH RENDERER SUBCLASSES //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LatLonPatchRenderer : public PatchRenderer {
|
||||
public:
|
||||
LatLonPatchRenderer(shared_ptr<Geometry>);
|
||||
|
||||
virtual void renderPatch(
|
||||
const LatLonPatch& patch,
|
||||
const RenderData& data,
|
||||
double radius) override;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __LATLONPATCH_H__
|
||||
@@ -1,334 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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/renderablelatlonpatch.h>
|
||||
|
||||
#include <modules/globebrowsing/util/converter.h>
|
||||
|
||||
// open space includes
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
// ghoul includes
|
||||
#include <ghoul/misc/assert.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "LatLonPatch";
|
||||
|
||||
const std::string keyFrame = "Frame";
|
||||
const std::string keyGeometry = "Geometry";
|
||||
const std::string keyShading = "PerformShading";
|
||||
|
||||
const std::string keyBody = "Body";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
RenderableLatLonPatch::RenderableLatLonPatch(
|
||||
unsigned int xRes,
|
||||
unsigned int yRes,
|
||||
double posLat,
|
||||
double posLon,
|
||||
double sizeLat,
|
||||
double sizeLon,
|
||||
double globeRadius)
|
||||
: _grid(
|
||||
xRes,
|
||||
yRes,
|
||||
Geometry::Positions::No,
|
||||
Geometry::TextureCoordinates::Yes,
|
||||
Geometry::Normals::No)
|
||||
, _programObject(nullptr)
|
||||
, _patch(LatLonPatch(LatLon(posLat, posLon), LatLon(sizeLat, sizeLon)))
|
||||
, _globeRadius(globeRadius)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
RenderableLatLonPatch::~RenderableLatLonPatch() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool RenderableLatLonPatch::initialize() {
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
if (_programObject == nullptr) {
|
||||
_programObject = renderEngine.buildRenderProgram(
|
||||
"LatLonSphereMappingProgram",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/latlonpatch_spheremapping_vs.glsl",
|
||||
"${MODULE_GLOBEBROWSING}/shaders/simple_fs.glsl");
|
||||
if (!_programObject) return false;
|
||||
}
|
||||
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_programObject->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
|
||||
return isReady();
|
||||
}
|
||||
|
||||
bool RenderableLatLonPatch::deinitialize() {
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
if (_programObject) {
|
||||
renderEngine.removeRenderProgram(_programObject);
|
||||
_programObject = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderableLatLonPatch::isReady() const {
|
||||
bool ready = true;
|
||||
ready &= (_programObject != nullptr);
|
||||
return ready;
|
||||
}
|
||||
|
||||
void RenderableLatLonPatch::render(const RenderData& data) {
|
||||
|
||||
// activate shader
|
||||
_programObject->activate();
|
||||
using namespace glm;
|
||||
|
||||
|
||||
// Get camera transform matrix
|
||||
// TODO : Should only need to fetch the camera transform and use directly
|
||||
// but this is not currently possible in the camera class.
|
||||
vec3 cameraPosition = data.camera.position().vec3();
|
||||
mat4 viewTransform = inverse(translate(mat4(1.0), cameraPosition));
|
||||
viewTransform = mat4(data.camera.viewRotationMatrix()) * viewTransform;
|
||||
|
||||
// TODO : Model transform should be fetched as a matrix directly.
|
||||
mat4 modelTransform = translate(mat4(1), data.position.vec3());
|
||||
|
||||
LatLon swCorner = _patch.southWestCorner();
|
||||
|
||||
_programObject->setUniform("modelViewProjectionTransform", data.camera.projectionMatrix() * viewTransform * modelTransform);
|
||||
_programObject->setUniform("minLatLon", vec2(swCorner.lat, swCorner.lon));
|
||||
_programObject->setUniform("latLonScalingFactor", 2.0f * vec2(_patch.halfSize.lat, _patch.halfSize.lon));
|
||||
_programObject->setUniform("globeRadius", float(_globeRadius));
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// render
|
||||
_grid.drawUsingActiveProgram();
|
||||
|
||||
// disable shader
|
||||
_programObject->deactivate();
|
||||
|
||||
#if 0
|
||||
|
||||
// activate shader
|
||||
_programObject->activate();
|
||||
|
||||
// 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 = 6.3e6;
|
||||
|
||||
// Create control points and normals(double)
|
||||
glm::dvec3 p00, p01, p02, p10, p11, p12, p20, p21, p22;
|
||||
glm::dvec3 n00, n01, n02, n10, n11, n12, n20, n21, n22;
|
||||
glm::dvec3 nHorizontal0, nHorizontal1, nHorizontal2;
|
||||
float w10, w11, w12;
|
||||
|
||||
// Calculate positions of corner control points
|
||||
p00 = calculateCornerPointBottomLeft();
|
||||
p20 = calculateCornerPointBottomRight();
|
||||
p02 = calculateCornerPointTopLeft();
|
||||
p22 = calculateCornerPointTopRight();
|
||||
|
||||
// Calculate the horizontal normals
|
||||
nHorizontal0 = glm::normalize(converter::latLonToCartesian(
|
||||
0,
|
||||
_patch.getCenter().lon - _patch.getHalfSize().lon,
|
||||
r));
|
||||
nHorizontal1 = glm::normalize(converter::latLonToCartesian(
|
||||
0,
|
||||
_patch.getCenter().lon,
|
||||
r));
|
||||
nHorizontal2 = glm::normalize(converter::latLonToCartesian(
|
||||
0,
|
||||
_patch.getCenter().lon + _patch.getHalfSize().lon,
|
||||
r));
|
||||
|
||||
// Get position of center control points
|
||||
p01 = calculateCenterPoint(p00, glm::normalize(p00), p02, glm::normalize(p02));
|
||||
p21 = calculateCenterPoint(p20, glm::normalize(p20), p22, glm::normalize(p22));
|
||||
p10 = calculateCenterPoint(p00, nHorizontal0, p20, nHorizontal2);
|
||||
p12 = calculateCenterPoint(p02, nHorizontal0, p22, nHorizontal2);
|
||||
p11 = calculateCenterPoint(p01, nHorizontal0, p21, nHorizontal2);
|
||||
|
||||
// Calculate normals from control point positions
|
||||
n00 = normalize(p00);
|
||||
n01 = normalize(p01);
|
||||
n02 = normalize(p02);
|
||||
n10 = normalize(p10);
|
||||
n11 = normalize(p11);
|
||||
n12 = normalize(p12);
|
||||
n20 = normalize(p20);
|
||||
n21 = normalize(p21);
|
||||
n22 = normalize(p22);
|
||||
|
||||
// Calculate three weights to send to GPU for interpolation
|
||||
w10 = glm::dot(nHorizontal0, nHorizontal1);
|
||||
w11 = w10;
|
||||
w12 = w10;
|
||||
|
||||
// TODO : Transformation to world space from model space should also consider
|
||||
// rotations. Now it only uses translatation for simplicity. Should be done
|
||||
// With a matrix transform
|
||||
// TODO : Normals should also be transformed
|
||||
glm::dvec3 position = data.position.dvec3();
|
||||
p00 += position;
|
||||
p10 += position;
|
||||
p20 += position;
|
||||
p01 += position;
|
||||
p11 += position;
|
||||
p21 += position;
|
||||
p02 += position;
|
||||
p12 += position;
|
||||
p22 += position;
|
||||
|
||||
// Calculate global position of camera
|
||||
// TODO : Should only need to fetch the camera transform and use directly
|
||||
// Now the viewTransform is wrong due to the constant lookUpVector
|
||||
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;
|
||||
|
||||
// Transform control points to camera space
|
||||
p00 = glm::dvec3(viewTransform * glm::dvec4(p00, 1.0));
|
||||
p10 = glm::dvec3(viewTransform * glm::dvec4(p10, 1.0));
|
||||
p20 = glm::dvec3(viewTransform * glm::dvec4(p20, 1.0));
|
||||
p01 = glm::dvec3(viewTransform * glm::dvec4(p01, 1.0));
|
||||
p11 = glm::dvec3(viewTransform * glm::dvec4(p11, 1.0));
|
||||
p21 = glm::dvec3(viewTransform * glm::dvec4(p21, 1.0));
|
||||
p02 = glm::dvec3(viewTransform * glm::dvec4(p02, 1.0));
|
||||
p12 = glm::dvec3(viewTransform * glm::dvec4(p12, 1.0));
|
||||
p22 = glm::dvec3(viewTransform * glm::dvec4(p22, 1.0));
|
||||
|
||||
// Transform normals to camera space
|
||||
n00 = glm::dvec3(viewTransform * glm::dvec4(n00, 0.0));
|
||||
n10 = glm::dvec3(viewTransform * glm::dvec4(n10, 0.0));
|
||||
n20 = glm::dvec3(viewTransform * glm::dvec4(n20, 0.0));
|
||||
n01 = glm::dvec3(viewTransform * glm::dvec4(n01, 0.0));
|
||||
n11 = glm::dvec3(viewTransform * glm::dvec4(n11, 0.0));
|
||||
n21 = glm::dvec3(viewTransform * glm::dvec4(n21, 0.0));
|
||||
n02 = glm::dvec3(viewTransform * glm::dvec4(n02, 0.0));
|
||||
n12 = glm::dvec3(viewTransform * glm::dvec4(n12, 0.0));
|
||||
n22 = glm::dvec3(viewTransform * glm::dvec4(n22, 0.0));
|
||||
|
||||
// Send control points and normals to GPU to be used in shader
|
||||
_programObject->setUniform("p00", glm::vec3(p00));
|
||||
_programObject->setUniform("p10", glm::vec3(p10));
|
||||
_programObject->setUniform("p20", glm::vec3(p20));
|
||||
_programObject->setUniform("p01", glm::vec3(p01));
|
||||
_programObject->setUniform("p11", glm::vec3(p11));
|
||||
_programObject->setUniform("p21", glm::vec3(p21));
|
||||
_programObject->setUniform("p02", glm::vec3(p02));
|
||||
_programObject->setUniform("p12", glm::vec3(p12));
|
||||
_programObject->setUniform("p22", glm::vec3(p22));
|
||||
|
||||
_programObject->setUniform("w10", w10);
|
||||
_programObject->setUniform("w11", w11);
|
||||
_programObject->setUniform("w12", w12);
|
||||
|
||||
/*
|
||||
_programObject->setUniform("n00", glm::vec3(n00));
|
||||
_programObject->setUniform("n10", glm::vec3(n10));
|
||||
_programObject->setUniform("n20", glm::vec3(n20));
|
||||
_programObject->setUniform("n01", glm::vec3(n01));
|
||||
_programObject->setUniform("n11", glm::vec3(n11));
|
||||
_programObject->setUniform("n21", glm::vec3(n21));
|
||||
_programObject->setUniform("n02", glm::vec3(n02));
|
||||
_programObject->setUniform("n12", glm::vec3(n12));
|
||||
_programObject->setUniform("n22", glm::vec3(n22));
|
||||
*/
|
||||
_programObject->setUniform("Projection", data.camera.projectionMatrix());
|
||||
|
||||
// Render triangles (use texture coordinates to interpolate to new positions)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
|
||||
|
||||
// render
|
||||
_grid.drawUsingActiveProgram();
|
||||
|
||||
// disable shader
|
||||
_programObject->deactivate();
|
||||
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
void RenderableLatLonPatch::update(const UpdateData& data) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
glm::dvec3 RenderableLatLonPatch::calculateCornerPointBottomLeft() {
|
||||
return _globeRadius * _patch.southEastCorner().asUnitCartesian();
|
||||
}
|
||||
glm::dvec3 RenderableLatLonPatch::calculateCornerPointBottomRight() {
|
||||
return _globeRadius * _patch.southEastCorner().asUnitCartesian();
|
||||
}
|
||||
glm::dvec3 RenderableLatLonPatch::calculateCornerPointTopLeft() {
|
||||
return _globeRadius * _patch.northWestCorner().asUnitCartesian();
|
||||
}
|
||||
glm::dvec3 RenderableLatLonPatch::calculateCornerPointTopRight() {
|
||||
return _globeRadius * _patch.northEastCorner().asUnitCartesian();
|
||||
}
|
||||
|
||||
glm::dvec3 RenderableLatLonPatch::calculateCenterPoint(
|
||||
glm::dvec3 p0,
|
||||
glm::dvec3 n0,
|
||||
glm::dvec3 p2,
|
||||
glm::dvec3 n2) {
|
||||
// Solution derived
|
||||
glm::dvec2 u = glm::dvec2(0, glm::dot(p2, n2) - glm::dot(p0, n2));
|
||||
double cosNormalAngle = glm::dot(n0, n2);
|
||||
glm::dmat2 A = glm::dmat2({ 1, cosNormalAngle, cosNormalAngle, 1 });
|
||||
glm::dvec2 stParam = glm::inverse(A) * u;
|
||||
glm::dvec3 p1 = p0 + stParam.s * n0 + stParam.t * n2;
|
||||
return p1;
|
||||
}
|
||||
|
||||
void RenderableLatLonPatch::setPatch(LatLonPatch patch) {
|
||||
_patch = patch;
|
||||
}
|
||||
|
||||
LatLonPatch RenderableLatLonPatch::getPatch() {
|
||||
return _patch;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
Reference in New Issue
Block a user