Modularize the newhorizons and volume classes

This commit is contained in:
Alexander Bock
2015-05-20 21:08:21 +02:00
parent 523abd6529
commit 59e474d5cd
26 changed files with 250 additions and 25 deletions
@@ -0,0 +1,79 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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/newhorizons/rendering/planetgeometryprojection.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/factorymanager.h>
namespace {
const std::string _loggerCat = "PlanetGeometryProjection";
const std::string KeyType = "Type";
}
namespace openspace {
namespace planetgeometryprojection {
PlanetGeometryProjection* PlanetGeometryProjection::createFromDictionary(const ghoul::Dictionary& dictionary)
{
std::string geometryType;
const bool success = dictionary.getValue(KeyType, geometryType);
if (!success) {
LERROR("PlanetGeometry did not contain a correct value of the key '"
<< KeyType << "'");
return nullptr;
}
ghoul::TemplateFactory<PlanetGeometryProjection>* factory
= FactoryManager::ref().factory<PlanetGeometryProjection>();
PlanetGeometryProjection* result = factory->create(geometryType, dictionary);
if (result == nullptr) {
LERROR("Failed to create a PlanetGeometry object of type '" << geometryType
<< "'");
return nullptr;
}
return result;
}
PlanetGeometryProjection::PlanetGeometryProjection()
: _parent(nullptr)
{
setName("PlanetGeometryProjection");
}
PlanetGeometryProjection::~PlanetGeometryProjection()
{
}
bool PlanetGeometryProjection::initialize(RenderablePlanetProjection* parent)
{
_parent = parent;
return true;
}
void PlanetGeometryProjection::deinitialize()
{
}
} // namespace planetgeometry
} // namespace openspace
@@ -0,0 +1,53 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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 __PlanetGeometryProjection_H__
#define __PlanetGeometryProjection_H__
#include <openspace/properties/propertyowner.h>
#include <modules/newhorizons/rendering/renderableplanetprojection.h>
#include <ghoul/misc/dictionary.h>
namespace openspace {
namespace planetgeometryprojection {
class PlanetGeometryProjection : public properties::PropertyOwner {
public:
static PlanetGeometryProjection* createFromDictionary(const ghoul::Dictionary& dictionary);
PlanetGeometryProjection();
virtual ~PlanetGeometryProjection();
virtual bool initialize(RenderablePlanetProjection* parent);
virtual void deinitialize();
virtual void render() = 0;
protected:
RenderablePlanetProjection* _parent;
};
} // namespace planetgeometry
} // namespace openspace
#endif // __PLANETGEOMETRY_H__
@@ -0,0 +1,578 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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/newhorizons/rendering/renderablefov.h>
#include <openspace/engine/configurationmanager.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/constants.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/imagesequencer2.h> // testing
#include <openspace/util/time.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/filesystem/filesystem.h>
#include <openspace/query/query.h>
#include <openspace/util/spicemanager.h>
#include <iomanip>
#include <utility>
#include <chrono>
namespace {
const std::string _loggerCat = "RenderableFov";
//constants
const std::string keyBody = "Body";
const std::string keyFrame = "Frame";
const std::string keyPathModule = "ModulePath";
const std::string keyColor = "RGB";
const std::string keyInstrument = "Instrument.Name";
const std::string keyInstrumentMethod = "Instrument.Method";
const std::string keyInstrumentAberration = "Instrument.Aberration";
const std::string keyPotentialTargets = "PotentialTargets";
// colors, move later
glm::vec4 col_sq;
glm::vec4 c_project;
glm::vec4 col_end;
glm::vec4 blue;
glm::vec4 col_gray;
glm::vec4 col_start;
}
namespace openspace {
RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _lineWidth("lineWidth", "Line Width", 1.f, 1.f, 20.f)
, _drawSolid("solidDraw", "Draw as Quads", false)
, _programObject(nullptr)
, _texture(nullptr)
, _mode(GL_LINES)
{
bool success = dictionary.getValue(keyBody, _spacecraft);
ghoul_assert(success, "");
success = dictionary.getValue(keyFrame, _frame);
ghoul_assert(success, "");
success = dictionary.getValue(keyInstrument, _instrumentID);
ghoul_assert(success, "");
success = dictionary.getValue(keyInstrumentMethod, _method);
ghoul_assert(success, "");
success = dictionary.getValue(keyInstrumentAberration, _aberrationCorrection);
ghoul_assert(success, "");
ghoul::Dictionary potentialTargets;
success = dictionary.getValue(keyPotentialTargets, potentialTargets);
ghoul_assert(success, "");
_potentialTargets.resize(potentialTargets.size());
for (int i = 0; i < potentialTargets.size(); ++i) {
std::string target;
potentialTargets.getValue(std::to_string(i + 1), target);
_potentialTargets[i] = target;
}
addProperty(_lineWidth);
addProperty(_drawSolid);
}
void RenderableFov::allocateData() {
int points = 20;
_stride[0] = points;
_isize[0] = points;
_iarray1[0] = new int[_isize[0]];
for (int i = 0; i < points; i++){
for (int j = 0; j < 4; j++){
_varray1.push_back(0); // pos
}
for (int j = 0; j < 4; j++){
_varray1.push_back(0); // col
}
_iarray1[0][i] = i;
}
_stride[0] = 8;
_vsize[0] = static_cast<unsigned int>(_varray1.size());
_vtotal[0] = static_cast<int>(_vsize[0] / _stride[0]);
// allocate second vbo data
int cornerPoints = 12;
_isize[1] = cornerPoints;
_iarray1[1] = new int[_isize[1]];
for (unsigned int i = 0; i < _isize[1]; i++){
_iarray1[1][i] = i;
}
_varray2.resize(40);
_vsize[1] = 40;
_vtotal[1] = 5;
_isteps = 10;
}
RenderableFov::~RenderableFov() {
deinitialize();
}
bool RenderableFov::initialize() {
bool completeSuccess = true;
if (_programObject == nullptr) {
_programObject = ghoul::opengl::ProgramObject::Build("FovProgram",
"${SHADERS}/modules/projection/fov_vs.glsl",
"${SHADERS}/modules/projection/fov_fs.glsl");
if (!_programObject)
return false;
}
allocateData();
sendToGPU();
return completeSuccess;
}
bool RenderableFov::deinitialize() {
return true;
}
bool RenderableFov::isReady() const {
return _programObject != nullptr;
}
void RenderableFov::sendToGPU() {
// Initialize and upload to graphics card
glGenVertexArrays(1, &_vaoID[0]);
glGenBuffers(1, &_vboID[0]);
glGenBuffers(1, &_iboID[0]);
glBindVertexArray(_vaoID[0]);
glBindBuffer(GL_ARRAY_BUFFER, _vboID[0]);
glBufferData(GL_ARRAY_BUFFER, _vsize[0] * sizeof(GLfloat), NULL, GL_STATIC_DRAW); // orphaning the buffer, sending NULL data.
glBufferSubData(GL_ARRAY_BUFFER, 0, _vsize[0] * sizeof(GLfloat), &_varray1[0]);
GLsizei st = sizeof(GLfloat) * _stride[0];
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, st, (void*)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, st, (void*)(4 * sizeof(GLfloat)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _isize[0] * sizeof(int), _iarray1, GL_STATIC_DRAW);
glBindVertexArray(0);
// second vbo
glGenVertexArrays(1, &_vaoID[1]);
glGenBuffers(1, &_vboID[1]);
glGenBuffers(1, &_iboID[1]);
glBindVertexArray(_vaoID[1]);
glBindBuffer(GL_ARRAY_BUFFER, _vboID[1]);
glBufferData(GL_ARRAY_BUFFER, _vsize[1] * sizeof(GLfloat), NULL, GL_STATIC_DRAW); // orphaning the buffer, sending NULL data.
glBufferSubData(GL_ARRAY_BUFFER, 0, _vsize[1] * sizeof(GLfloat), &_varray2[0]);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, st, (void*)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, st, (void*)(4 * sizeof(GLfloat)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _isize[1] * sizeof(int), _iarray1[1], GL_STATIC_DRAW);
glBindVertexArray(0);
}
// various helper methods
void RenderableFov::insertPoint(std::vector<float>& arr, psc p, glm::vec4 c) {
for (int i = 0; i < 4; i++){
arr.push_back(p[i]);
}
for (int i = 0; i < 4; i++){
arr.push_back(c[i]);
}
_nrInserted++;
}
glm::dvec3 RenderableFov::interpolate(glm::dvec3 p0, glm::dvec3 p1, float t) {
assert(t >= 0 && t <= 1);
float t2 = (1.f - t);
return glm::dvec3(p0.x*t2 + p1.x*t, p0.y*t2 + p1.y*t, p0.z*t2 + p1.z*t);
}
// This method is the current bottleneck.
psc RenderableFov::checkForIntercept(glm::dvec3 ray) {
double targetEt;
bool intercepted = false;
openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
_frame, _method, _aberrationCorrection,
_time, targetEt, ray, ipoint, ivec, intercepted);
_interceptVector = PowerScaledCoordinate::CreatePowerScaledCoordinate(ivec[0], ivec[1], ivec[2]);
_interceptVector[3] += 3;
return _interceptVector;
}
// Orthogonal projection next to planets surface, can also be optimized.
psc RenderableFov::orthogonalProjection(glm::dvec3 vecFov) {
glm::dvec3 vecToTarget;
double lt;
SpiceManager::ref().getTargetPosition(_fovTarget, _spacecraft, _frame, _aberrationCorrection, _time, vecToTarget, lt);
openspace::SpiceManager::ref().frameConversion(vecFov, _instrumentID, _frame, _time);
glm::dvec3 p = openspace::SpiceManager::ref().orthogonalProjection(vecToTarget, vecFov);
psc projection = PowerScaledCoordinate::CreatePowerScaledCoordinate(p[0], p[1], p[2]);
projection[3] += 3;
return projection;
}
// Bisection method, simple recurtion
glm::dvec3 RenderableFov::bisection(glm::dvec3 p1, glm::dvec3 p2, double tolerance) {
//check if point is on surface
double targetEt;
glm::dvec3 half = interpolate(p1, p2, 0.5f);
bool intercepted = false;
openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
_frame, _method, _aberrationCorrection,
_time, targetEt, half, ipoint, ivec, intercepted);
if (glm::distance(_previousHalf, half) < tolerance){
_previousHalf = glm::dvec3(0);
return half;
}
_previousHalf = half;
//recursive search
if (!intercepted){
return bisection(p1, half, tolerance);
}else{
return bisection(half, p2, tolerance);
}
}
/*
README:
There are 4 different cases as each boundary vector can either have detected
an intercept or is outside of the planets surface. When no such intercepts are
detected the algorithm performs an orthogonal projection to 'clip' the current
fov vector next to the planets surface. If two or more intercepts are detected
the algorithm continues with the bisection method O(logn) for points [Pn, Pn+1]
to locate the point Pb where the orthogonal plane meets the planets surface
(within ~20 iterations this will narrow down to centimeter resolution).
Upon finding Pb a linear interpolation is performed for [Pn, Pb], at this stage
the points are located on a straight line between the surface intercept and the
surface-bound fov-corner. In order to correctly place these points on the
targets surface, each consecutive point is queried for a surface intercept and
thereby moved to the hull.
*/
void RenderableFov::fovProjection(bool H[], std::vector<glm::dvec3> bounds) {
_nrInserted = 0;
_varray2.clear();// empty the array
double tolerance = 0.0000001; // very low tolerance factor
glm::dvec3 mid;
glm::dvec3 interpolated;
glm::dvec3 current;
glm::dvec3 next;
glm::vec4 tmp(1);
if (bounds.size() > 1){
for (int i = 0; i < bounds.size(); i++){
int k = (i + 1 > bounds.size() - 1) ? 0 : i + 1;
current = bounds[i];
next = bounds[k];
if (H[i] == false){ // If point is non-interceptive, project it.
insertPoint(_varray2, orthogonalProjection(current), tmp);
}
if (H[i] == true && H[i + 1] == false){ // current point is interceptive, next is not
// find outer most point for interpolation
mid = bisection(current, next, tolerance);
for (int j = 1; j <= _isteps; j++){
float t = (static_cast<float>(j) / _isteps);
interpolated = interpolate(current, mid, t);
_interceptVector = (j < _isteps) ? checkForIntercept(interpolated) : orthogonalProjection(interpolated);
insertPoint(_varray2, _interceptVector, col_sq);
}
}
if (H[i] == false && H[i + 1] == true){ // current point is non-interceptive, next is
mid = bisection(next, current, tolerance);
for (int j = 1; j <= _isteps; j++){
float t = (static_cast<float>(j) / _isteps);
interpolated = interpolate(mid, next, t);
_interceptVector = (j > 1) ? checkForIntercept(interpolated) : orthogonalProjection(interpolated);
insertPoint(_varray2, _interceptVector, col_sq);
}
}
if (H[i] == true && H[i + 1] == true){ // both points intercept
for (int j = 0; j <= _isteps; j++){
float t = (static_cast<float>(j) / _isteps);
interpolated = interpolate(current, next, t);
_interceptVector = checkForIntercept(interpolated);
insertPoint(_varray2, _interceptVector, col_sq);
}
}
}
}
if (_nrInserted == 0){
_rebuild = false;
}
else {
_rebuild = true;
//update size etc;
_vtotal[1] = _nrInserted;
_isize[1] = _nrInserted;
_vsize[1] = static_cast<unsigned int>(_varray2.size());
_iarray1[1] = new int[_isize[1]];
for (unsigned int i = 0; i < _isize[1]; i++)
_iarray1[1][i] = i;
}
}
void RenderableFov::updateData() {
glBindBuffer(GL_ARRAY_BUFFER, _vboID[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, _vsize[0] * sizeof(GLfloat), &_varray1[0]);
if (!_rebuild){
glBindBuffer(GL_ARRAY_BUFFER, _vboID[1]);
glBufferSubData(GL_ARRAY_BUFFER, 0, _vsize[1] * sizeof(GLfloat), &_varray2[0]);
}else{
glBindVertexArray(_vaoID[1]);
glBindBuffer(GL_ARRAY_BUFFER, _vboID[1]);
glBufferData(GL_ARRAY_BUFFER, _vsize[1] * sizeof(GLfloat), NULL, GL_STATIC_DRAW); // orphaning the buffer, sending NULL data.
glBufferSubData(GL_ARRAY_BUFFER, 0, _vsize[1] * sizeof(GLfloat), &_varray2[0]);
GLsizei st = sizeof(GLfloat) * _stride[0];
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, st, (void*)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, st, (void*)(4 * sizeof(GLfloat)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _isize[1] * sizeof(int), _iarray1[1], GL_STATIC_DRAW);
glBindVertexArray(0);
}
}
void RenderableFov::computeColors() {
double t2 = openspace::ImageSequencer2::ref().getNextCaptureTime();
double diff = (t2 - _time);
float t = 0.0;
if (diff <= 7.0)
t = static_cast<float>(1.0 - (diff / 7.0));
if (diff < 0.0)
t = 0.f;
// i need to add an *.h file with colortables....
c_project = glm::vec4(0.0, 1.0, 0.00,1);
col_end = glm::vec4(1.00, 0.29, 0.00, 1);
blue = glm::vec4(0, 0.5, 0.7, 1);
col_gray = glm::vec4(0.7);
col_start = glm::vec4(1.00, 0.89, 0.00, 1);
col_sq = glm::vec4(1.00, 0.29, 0.00, 1);
col_end.x = c_project.x*t + col_end.x*(1 - t);
col_end.y = c_project.y*t + col_end.y*(1 - t);
col_end.z = c_project.z*t + col_end.z*(1 - t);
blue.x = c_project.x*t + blue.x*(1 - t);
blue.y = c_project.y*t + blue.y*(1 - t);
blue.z = c_project.z*t + blue.z*(1 - t);
col_sq.x = c_project.x*t + col_sq.x*(1 - t);
col_sq.y = c_project.y*t + col_sq.y*(1 - t);
col_sq.z = c_project.z*t + col_sq.z*(1 - t);
blue.w = 0.5;
c_project.w = 0.5;
col_end.w = 0.5;
}
void RenderableFov::render(const RenderData& data) {
assert(_programObject);
_programObject->activate();
// fetch data
glm::mat4 transform(1);
glm::mat4 spacecraftRot = glm::mat4(1);
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
spacecraftRot[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
bool drawFOV = false;
// setup the data to the shader
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
setPscUniforms(_programObject, &data.camera, data.position);
if (openspace::ImageSequencer2::ref().isReady()){
drawFOV = ImageSequencer2::ref().instrumentActive(_instrumentID);
}
if (drawFOV){
// update only when time progresses.
if (_oldTime != _time){
std::string shape, instrument;
std::vector<glm::dvec3> bounds;
glm::dvec3 boresight;
// fetch data for specific instrument (shape, boresight, bounds etc)
bool found = openspace::SpiceManager::ref().getFieldOfView(_instrumentID, shape, instrument, boresight, bounds);
if (!found) {
LERROR("Could not locate instrument");
return;
}
const unsigned int size = 4 * sizeof(float);
int indx = 0;
_fovTarget = _potentialTargets[0]; //default
for (int i = 0; i < _potentialTargets.size(); i++){
bool success = openspace::SpiceManager::ref().targetWithinFieldOfView(
_instrumentID,
_potentialTargets[i],
_spacecraft,
_method,
_aberrationCorrection,
_time,
_withinFOV);
if (success && _withinFOV){
_fovTarget = _potentialTargets[i];
break;
}
}
computeColors();
double targetEpoch;
// for each FOV vector
for (int i = 0; i <= bounds.size(); i++){
int r = (i == bounds.size()) ? 0 : i;
// compute surface intercept
openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
_frame, _method, _aberrationCorrection,
_time, targetEpoch, bounds[r], ipoint, ivec, _interceptTag[r]);
// if not found, use the orthogonal projected point
if (!_interceptTag[r]) _projectionBounds[r] = orthogonalProjection(bounds[r]);
// VBO1 : draw vectors representing outer points of FOV.
if (_interceptTag[r]){
_interceptVector = PowerScaledCoordinate::CreatePowerScaledCoordinate(ivec[0], ivec[1], ivec[2]);
_interceptVector[3] += 3;
// INTERCEPTIONS
memcpy(&_varray1[indx], glm::value_ptr(glm::vec4(0)), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(col_start), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(_interceptVector.vec4()), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(col_end), size);
indx += 4;
}
else if (_withinFOV){
// FOV OUTSIDE OBJECT
memcpy(&_varray1[indx], glm::value_ptr(glm::vec4(0)), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(glm::vec4(0, 0, 1, 1)), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(_projectionBounds[r].vec4()), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(blue), size);
indx += 4;
}
else{
glm::vec4 corner(bounds[r][0], bounds[r][1], bounds[r][2], data.position[3] + 2);
corner = spacecraftRot*corner;
// "INFINITE" FOV
memcpy(&_varray1[indx], glm::value_ptr(glm::vec4(0)), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(col_gray), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(corner), size);
indx += 4;
memcpy(&_varray1[indx], glm::value_ptr(glm::vec4(0)), size);
indx += 4;
}
}
_interceptTag[bounds.size()] = _interceptTag[0];
if (!(_instrumentID == "NH_LORRI")) // image plane replaces fov square
fovProjection(_interceptTag, bounds);
updateData();
glm::vec3 aim = (spacecraftRot * glm::vec4(boresight, 1)).xyz;
psc position;
double lt;
SpiceManager::ref().getTargetPosition(_fovTarget,
_spacecraft,
_frame,
_aberrationCorrection,
_time,
position,
lt);
//if aimed 80 deg away from target, dont draw white square
if (glm::dot(glm::normalize(aim), glm::normalize(position.vec3())) < 0.2){
drawFOV = false;
}
}
_oldTime = _time;
if (!_drawSolid) _mode = GL_LINES;
else _mode = GL_TRIANGLE_STRIP;
glLineWidth(_lineWidth);
glBindVertexArray(_vaoID[0]);
glDrawArrays(_mode, 0, _vtotal[0]);
glBindVertexArray(0);
glLineWidth(_lineWidth);
glBindVertexArray(_vaoID[0]);
glDrawArrays(GL_LINES, 0, _vtotal[0]);
glBindVertexArray(0);
if (drawFOV){
glLineWidth(1.f);
glBindVertexArray(_vaoID[1]);
glDrawArrays(GL_LINE_LOOP, 0, _vtotal[1]);
glBindVertexArray(0);
}
glLineWidth(1.f);
}
_programObject->deactivate();
}
void RenderableFov::update(const UpdateData& data) {
_time = data.time;
openspace::SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _frame, data.time, _stateMatrix);
}
} // namespace openspace
@@ -0,0 +1,127 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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 __RenderableFov_H__
#define __RenderableFov_H__
// open space includes
#include <openspace/rendering/renderable.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/query/query.h>
// ghoul includes
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
//#include <openspace/util/runtimedata.h>
#include <openspace/util/powerscaledcoordinate.h>
namespace openspace {
class RenderableFov : public Renderable{
public:
RenderableFov(const ghoul::Dictionary& dictionary);
~RenderableFov();
bool initialize() override;
bool deinitialize() override;
bool isReady() const override;
void render(const RenderData& data) override;
void update(const UpdateData& data) override;
private:
properties::FloatProperty _lineWidth;
properties::BoolProperty _drawSolid;
ghoul::opengl::ProgramObject* _programObject;
ghoul::opengl::Texture* _texture;
openspace::SceneGraphNode* _targetNode;
void loadTexture();
void allocateData();
void insertPoint(std::vector<float>& arr, psc p, glm::vec4 c);
void fovProjection(bool H[], std::vector<glm::dvec3> bounds);
psc orthogonalProjection(glm::dvec3 camvec);
psc checkForIntercept(glm::dvec3 ray);
psc pscInterpolate(psc p0, psc p1, float t);
psc sphericalInterpolate(glm::dvec3 p0, glm::dvec3 p1, float t);
glm::dvec3 interpolate(glm::dvec3 p0, glm::dvec3 p1, float t);
glm::dvec3 bisection(glm::dvec3 p1, glm::dvec3 p2, double tolerance);
void computeColors();
// instance variables
int _nrInserted = 0;
int _isteps;
bool _rebuild = false;
bool _interceptTag[9];
bool _withinFOV;
psc _projectionBounds[8];
psc _interceptVector;
// spice
std::string _spacecraft;
std::string _observer;
std::string _frame;
std::string _instrumentID;
std::string _method;
std::string _aberrationCorrection;
std::string _fovTarget;
std::vector<std::string> _potentialTargets;
glm::dvec3 ipoint, ivec;
glm::dvec3 _previousHalf;
glm::vec3 _c;
double _r, _g, _b;
// GPU stuff
GLuint _vaoID[2] ;
GLuint _vboID[2] ;
GLuint _iboID[2];
GLenum _mode;
unsigned int _isize[2];
unsigned int _vsize[2];
unsigned int _vtotal[2];
unsigned int _stride[2];
std::vector<float> _varray1;
std::vector<float> _varray2;
int* _iarray1[2];
void updateData();
void sendToGPU();
glm::dmat3 _stateMatrix;
// time
double _time = 0;
double _oldTime = 0;
// capturetime
double _timeInterval;
double _nextCaptureTime;
};
}
#endif
@@ -0,0 +1,339 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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/newhorizons/rendering/renderableplaneprojection.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/configurationmanager.h>
#include <openspace/util/constants.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/spicemanager.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/staticephemeris.h>
#include <openspace/scene/dynamicephemeris.h>
#include <ghoul/filesystem/filesystem>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <openspace/util/time.h>
namespace {
const std::string _loggerCat = "RenderablePlaneProjection";
const std::string KeySpacecraft = "Spacecraft";
const std::string KeyInstrument = "Instrument";
const std::string KeyMoving = "Moving";
const std::string KeyTexture = "Texture";
const std::string KeyName = "Name";
const std::string GalacticFrame = "GALACTIC";
const double REALLY_FAR = 99999999999;
}
namespace openspace {
RenderablePlaneProjection::RenderablePlaneProjection(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _texturePath("")
, _planeIsDirty(false)
, _shader(nullptr)
, _textureIsDirty(false)
, _texture(nullptr)
, _quad(0)
, _vertexPositionBuffer(0)
, _name("ImagePlane")
, _previousTime(0)
{
dictionary.getValue(KeySpacecraft, _spacecraft);
dictionary.getValue(KeyInstrument, _instrument);
dictionary.getValue(KeyMoving, _moving);
dictionary.getValue(KeyName, _name);
std::string texturePath = "";
bool success = dictionary.getValue(KeyTexture, _texturePath);
if (success) {
_texturePath = absPath(_texturePath);
_textureFile = new ghoul::filesystem::File(_texturePath);
}
loadTexture();
}
RenderablePlaneProjection::~RenderablePlaneProjection() {
delete _textureFile;
}
bool RenderablePlaneProjection::isReady() const {
bool ready = true;
if (!_shader)
ready &= false;
if (!_texture)
ready &= false;
return ready;
}
bool RenderablePlaneProjection::initialize() {
glGenVertexArrays(1, &_quad); // generate array
glGenBuffers(1, &_vertexPositionBuffer); // generate buffer
// Plane program
if (_shader == nullptr) {
// Image Plane Program
_shader = ghoul::opengl::ProgramObject::Build("ImagePlaneProgram",
"${SHADERS}/modules/imageplane/imageplane_vs.glsl",
"${SHADERS}/modules/imageplane/imageplane_fs.glsl");
if (!_shader) return false;
}
setTarget("JUPITER");
loadTexture();
return isReady();
}
bool RenderablePlaneProjection::deinitialize() {
glDeleteVertexArrays(1, &_quad);
_quad = 0;
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
delete _texture;
return true;
}
void RenderablePlaneProjection::render(const RenderData& data) {
glm::mat4 transform = glm::mat4(1.0);
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
transform[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
// Activate shader
_shader->activate();
_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_shader->setUniform("ModelTransform", transform);
setPscUniforms(_shader, &data.camera, data.position);
ghoul::opengl::TextureUnit unit;
unit.activate();
_texture->bind();
_shader->setUniform("texture1", unit);
glBindVertexArray(_quad);
glDrawArrays(GL_TRIANGLES, 0, 6);
_shader->deactivate();
}
void RenderablePlaneProjection::update(const UpdateData& data) {
double time = data.time;
const Image img = openspace::ImageSequencer2::ref().getLatestImageForInstrument(_instrument);
openspace::SpiceManager::ref().getPositionTransformMatrix(_target.frame, GalacticFrame, time, _stateMatrix);
double timePast = 0.0;
if (img.path != "")
{
timePast = abs(img.startTime - _previousTime);
}
std::string tex = _texturePath;
if (img.path != "" && (_moving || _planeIsDirty))
updatePlane(img, time);
else if (img.path != "" && timePast > DBL_EPSILON) {
_previousTime = time = img.startTime;
updatePlane(img, time);
}
if (_shader->isDirty())
_shader->rebuildFromFile();
if (_textureIsDirty) {
loadTexture();
_textureIsDirty = false;
}
}
void RenderablePlaneProjection::loadTexture() {
if (_texturePath != "") {
ghoul::opengl::Texture* texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath));
if (texture) {
texture->uploadTexture();
texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
if (_texture)
delete _texture;
_texture = texture;
delete _textureFile;
_textureFile = new ghoul::filesystem::File(_texturePath);
_textureFile->setCallback([&](const ghoul::filesystem::File&) { _textureIsDirty = true; });
}
}
}
void RenderablePlaneProjection::updatePlane(const Image img, double currentTime) {
std::string shape, frame;
std::vector<glm::dvec3> bounds;
glm::dvec3 boresight;
std::string target = "JUPITER"; //default
if (!_moving) {
target = findClosestTarget(currentTime);
}
if (img.path != "")
target = img.target;
setTarget(target);
bool found = openspace::SpiceManager::ref().getFieldOfView(_instrument, shape, frame, boresight, bounds);
if (!found) {
LERROR("Could not locate instrument");
return;
}
glm::dvec3 vecToTarget;
double lt;
psc projection[4];
SpiceManager::ref().getTargetPosition(_target.body, _spacecraft, GalacticFrame, "CN+S", currentTime, vecToTarget, lt);
// The apparent position, CN+S, makes image align best with target
for (int j = 0; j < bounds.size(); ++j) {
openspace::SpiceManager::ref().frameConversion(bounds[j], frame, GalacticFrame, currentTime);
glm::dvec3 cornerPosition = openspace::SpiceManager::ref().orthogonalProjection(vecToTarget, bounds[j]);
if (!_moving) {
cornerPosition -= vecToTarget;
}
openspace::SpiceManager::ref().frameConversion(cornerPosition, GalacticFrame, _target.frame, currentTime);
projection[j] = PowerScaledCoordinate::CreatePowerScaledCoordinate(cornerPosition[0], cornerPosition[1], cornerPosition[2]);
projection[j][3] += 3;
}
if (!_moving) {
SceneGraphNode* thisNode = OsEng.renderEngine()->scene()->sceneGraphNode(_name);
SceneGraphNode* newParent = OsEng.renderEngine()->scene()->sceneGraphNode(_target.node);
if (thisNode != nullptr && newParent != nullptr)
thisNode->setParent(newParent);
}
const GLfloat vertex_data[] = { // square of two triangles drawn within fov in target coordinates
// x y z w s t
projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 1, // Lower left 1
projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 0, // Upper right 2
projection[2][0], projection[2][1], projection[2][2], projection[2][3], 0, 0, // Upper left 3
projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 1, // Lower left 4 = 1
projection[0][0], projection[0][1], projection[0][2], projection[0][3], 1, 1, // Lower right 5
projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 0, // Upper left 6 = 2
};
glBindVertexArray(_quad); // bind array
glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(sizeof(GLfloat) * 4));
if (!_moving && img.path != "") {
_texturePath = img.path;
loadTexture();
}
}
void RenderablePlaneProjection::setTarget(std::string body) {
if (body == "")
return;
std::vector<SceneGraphNode*> nodes = OsEng.renderEngine()->scene()->allSceneGraphNodes();
Renderable* possibleTarget;
bool hasBody, found = false;
std::string targetBody;
for (auto node : nodes)
{
possibleTarget = node->renderable();
if (possibleTarget != nullptr) {
hasBody = possibleTarget->hasBody();
if (hasBody && possibleTarget->getBody(targetBody) && (targetBody == body)) {
_target.node = node->name(); // get name from propertyOwner
found = true;
break;
}
}
}
if (found) {
_target.body = body;
_target.frame = openspace::SpiceManager::ref().frameFromBody(body);
}
}
std::string RenderablePlaneProjection::findClosestTarget(double currentTime) {
std::vector<std::string> targets;
std::vector<SceneGraphNode*> nodes = OsEng.renderEngine()->scene()->allSceneGraphNodes();
Renderable* possibleTarget;
std::string targetBody;
bool hasBody, found = false;
PowerScaledScalar min = PowerScaledScalar::CreatePSS(REALLY_FAR);
PowerScaledScalar distance = PowerScaledScalar::CreatePSS(0.0);
std::string closestTarget = "";
psc spacecraftPos;
double lt;
SpiceManager::ref().getTargetPosition(_spacecraft, "SSB", GalacticFrame, "NONE", currentTime, spacecraftPos, lt);
for (auto node : nodes)
{
possibleTarget = node->renderable();
if (possibleTarget != nullptr) {
hasBody = possibleTarget->hasBody();
if (hasBody && possibleTarget->getBody(targetBody)) {
openspace::SpiceManager::ref().targetWithinFieldOfView(_instrument, targetBody, _spacecraft, "ELLIPSOID", "NONE", currentTime, found);
if (found){
targets.push_back(node->name()); // get name from propertyOwner
distance = (node->worldPosition() - spacecraftPos).length();
if (distance < min)
closestTarget = targetBody;
}
}
}
}
return closestTarget;
}
} // namespace openspace
@@ -0,0 +1,98 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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 _RENDERABLEPLANEPROJECTION_H_
#define _RENDERABLEPLANEPROJECTION_H_
#include <openspace/rendering/renderable.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/util/imagesequencer2.h>
#include <openspace/properties/vectorproperty.h>
#include <openspace/util/updatestructures.h>
namespace ghoul {
namespace filesystem {
class File;
}
namespace opengl {
class ProgramObject;
class Texture;
}
}
namespace openspace {
struct LinePoint;
struct target {
std::string body;
std::string frame;
std::string node;
};
class RenderablePlaneProjection : public Renderable {
public:
RenderablePlaneProjection(const ghoul::Dictionary& dictionary);
~RenderablePlaneProjection();
bool initialize() override;
bool deinitialize() override;
bool isReady() const override;
void render(const RenderData& data) override;
void update(const UpdateData& data) override;
private:
void loadTexture();
void updatePlane(const Image img, double currentTime);
std::string findClosestTarget(double currentTime);
void setTarget(std::string body);
std::string _texturePath;
bool _planeIsDirty;
glm::dmat3 _stateMatrix;
std::string _frame;
ghoul::opengl::ProgramObject* _shader;
bool _textureIsDirty;
ghoul::opengl::Texture* _texture;
ghoul::filesystem::File* _textureFile;
GLuint _quad;
GLuint _vertexPositionBuffer;
std::string _spacecraft;
std::string _instrument;
double _previousTime;
target _target;
std::string _name;
bool _moving;
};
} // namespace openspace
#endif
@@ -0,0 +1,543 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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. *
****************************************************************************************/
// open space includes
#include <modules/newhorizons/rendering/renderableplanetprojection.h>
#include <openspace/util/constants.h>
#include <modules/newhorizons/rendering/planetgeometryprojection.h>
#include <openspace/engine/configurationmanager.h>
#include <ghoul/io/texture/texturereader.h>
//#include <ghoul/opengl/textureunit.h>
#include <ghoul/filesystem/filesystem.h>
#include <openspace/util/time.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/factorymanager.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/configurationmanager.h>
#include <sgct.h>
#include <iomanip>
#include <string>
#include <thread>
#define _USE_MATH_DEFINES
#include <math.h>
namespace {
const std::string _loggerCat = "RenderablePlanetProjection";
const std::string keyProjObserver = "Projection.Observer";
const std::string keyProjTarget = "Projection.Target";
const std::string keyProjAberration = "Projection.Aberration";
const std::string keyInstrument = "Instrument.Name";
const std::string keyInstrumentFovy = "Instrument.Fovy";
const std::string keyInstrumentAspect = "Instrument.Aspect";
const std::string keyInstrumentNear = "Instrument.Near";
const std::string keyInstrumentFar = "Instrument.Far";
const std::string keySequenceDir = "Projection.Sequence";
const std::string keySequenceType = "Projection.SequenceType";
const std::string keyPotentialTargets = "PotentialTargets";
const std::string keyTranslation = "DataInputTranslation";
const std::string keyFrame = "Frame";
const std::string keyGeometry = "Geometry";
const std::string keyShading = "PerformShading";
const std::string keyBody = "Body";
const std::string _mainFrame = "GALACTIC";
const std::string sequenceTypeImage = "image-sequence";
const std::string sequenceTypePlaybook = "playbook";
}
namespace openspace {
//#define ORIGINAL_SEQUENCER
RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _colorTexturePath("planetTexture", "RGB Texture")
, _projectionTexturePath("projectionTexture", "RGB Texture")
, _rotation("rotation", "Rotation", 0, 0, 360)
, _fadeProjection("fadeProjections", "Image Fading Factor", 0.f, 0.f, 1.f)
, _performProjection("performProjection", "Perform Projections", true)
, _clearAllProjections("clearAllProjections", "Clear Projections", false)
, _programObject(nullptr)
, _fboProgramObject(nullptr)
, _texture(nullptr)
, _textureOriginal(nullptr)
, _textureProj(nullptr)
, _textureWhiteSquare(nullptr)
, _geometry(nullptr)
, _clearingImage(absPath("${OPENSPACE_DATA}/scene/common/textures/clear.png"))
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
ghoul_assert(success, "");
_defaultProjImage = absPath("textures/defaultProj.png");
ghoul::Dictionary geometryDictionary;
success = dictionary.getValue(
keyGeometry, geometryDictionary);
if (success) {
geometryDictionary.setValue(constants::scenegraphnode::keyName, name);
_geometry = planetgeometryprojection::PlanetGeometryProjection::createFromDictionary(geometryDictionary);
}
dictionary.getValue(keyFrame, _frame);
dictionary.getValue(keyBody, _target);
if (_target != "")
setBody(_target);
bool b1 = dictionary.getValue(keyInstrument, _instrumentID);
bool b2 = dictionary.getValue(keyProjObserver, _projectorID);
bool b3 = dictionary.getValue(keyProjTarget, _projecteeID);
bool b4 = dictionary.getValue(keyProjAberration, _aberration);
bool b5 = dictionary.getValue(keyInstrumentFovy, _fovy);
bool b6 = dictionary.getValue(keyInstrumentAspect, _aspectRatio);
bool b7 = dictionary.getValue(keyInstrumentNear, _nearPlane);
bool b8 = dictionary.getValue(keyInstrumentFar, _farPlane);
ghoul_assert(b1, "");
ghoul_assert(b2, "");
ghoul_assert(b3, "");
ghoul_assert(b4, "");
ghoul_assert(b5, "");
ghoul_assert(b6, "");
ghoul_assert(b7, "");
ghoul_assert(b8, "");
// @TODO copy-n-paste from renderablefov ---abock
ghoul::Dictionary potentialTargets;
success = dictionary.getValue(keyPotentialTargets, potentialTargets);
ghoul_assert(success, "");
_potentialTargets.resize(potentialTargets.size());
for (int i = 0; i < potentialTargets.size(); ++i) {
std::string target;
potentialTargets.getValue(std::to_string(i + 1), target);
_potentialTargets[i] = target;
}
// TODO: textures need to be replaced by a good system similar to the geometry as soon
// as the requirements are fixed (ab)
std::string texturePath = "";
success = dictionary.getValue("Textures.Color", texturePath);
if (success){
_colorTexturePath = absPath(texturePath);
}
success = dictionary.getValue("Textures.Project", texturePath);
if (success){
_projectionTexturePath = absPath(texturePath);
}
addPropertySubOwner(_geometry);
addProperty(_rotation);
addProperty(_fadeProjection);
addProperty(_performProjection);
addProperty(_clearAllProjections);
addProperty(_colorTexturePath);
_colorTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this));
addProperty(_projectionTexturePath);
_projectionTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadProjectionTexture, this));
SequenceParser* parser;
// std::string sequenceSource;
bool _foundSequence = dictionary.getValue(keySequenceDir, _sequenceSource);
if (_foundSequence) {
_sequenceSource = absPath(_sequenceSource);
_foundSequence = dictionary.getValue(keySequenceType, _sequenceType);
//Important: client must define translation-list in mod file IFF playbook
if (dictionary.hasKey(keyTranslation)){
ghoul::Dictionary translationDictionary;
//get translation dictionary
dictionary.getValue(keyTranslation, translationDictionary);
if (_sequenceType == sequenceTypePlaybook){
parser = new HongKangParser(_sequenceSource,
"NEW HORIZONS",
translationDictionary,
_potentialTargets);
openspace::ImageSequencer2::ref().runSequenceParser(parser);
}
else if (_sequenceType == sequenceTypeImage){
parser = new LabelParser(_sequenceSource, translationDictionary);
openspace::ImageSequencer2::ref().runSequenceParser(parser);
}
}
else{
LWARNING("No playbook translation provided, please make sure all spice calls match playbook!");
}
}
}
RenderablePlanetProjection::~RenderablePlanetProjection() {
deinitialize();
}
bool RenderablePlanetProjection::initialize() {
bool completeSuccess = true;
if (_programObject == nullptr) {
// projection program
_programObject = ghoul::opengl::ProgramObject::Build("projectiveProgram",
"${SHADERS}/modules/projection/projectiveTexture_vs.glsl",
"${SHADERS}/modules/projection/projectiveTexture_fs.glsl");
if (!_programObject)
return false;
}
if (_fboProgramObject == nullptr)
completeSuccess
&= OsEng.ref().configurationManager()->getValue("fboPassProgram", _fboProgramObject);
loadTexture();
loadProjectionTexture();
completeSuccess &= (_texture != nullptr);
completeSuccess &= (_textureOriginal != nullptr);
completeSuccess &= (_textureProj != nullptr);
completeSuccess &= (_textureWhiteSquare != nullptr);
completeSuccess &= _geometry->initialize(this);
completeSuccess &= auxiliaryRendertarget();
return completeSuccess;
}
bool RenderablePlanetProjection::auxiliaryRendertarget(){
bool completeSuccess = true;
// setup FBO
glGenFramebuffers(1, &_fboID);
glBindFramebuffer(GL_FRAMEBUFFER, _fboID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *_texture, 0);
// check FBO status
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
completeSuccess &= false;
// switch back to window-system-provided framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// SCREEN-QUAD
const GLfloat size = 1.0f;
const GLfloat w = 1.0f;
const GLfloat vertex_data[] = {
-size, -size, 0.0f, w, 0, 1,
size, size, 0.0f, w, 1, 0,
-size, size, 0.0f, w, 0, 0,
-size, -size, 0.0f, w, 0, 1,
size, -size, 0.0f, w, 1, 1,
size, size, 0.0f, w, 1, 0,
};
glGenVertexArrays(1, &_quad); // generate array
glBindVertexArray(_quad); // bind array
glGenBuffers(1, &_vertexPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(0));
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(sizeof(GLfloat) * 4));
return completeSuccess;
}
bool RenderablePlanetProjection::deinitialize(){
delete _texture;
_texture = nullptr;
delete _textureProj;
_textureProj = nullptr;
delete _textureOriginal;
_textureOriginal = nullptr;
delete _textureWhiteSquare;
_textureWhiteSquare = nullptr;
delete _geometry;
_geometry = nullptr;
return true;
}
bool RenderablePlanetProjection::isReady() const {
return (_geometry != nullptr);
}
void RenderablePlanetProjection::imageProjectGPU(){
// keep handle to the current bound FBO
GLint defaultFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
GLint m_viewport[4];
glGetIntegerv(GL_VIEWPORT, m_viewport);
//counter = 0;
glBindFramebuffer(GL_FRAMEBUFFER, _fboID);
// set blend eq
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ZERO);
glViewport(0, 0, static_cast<GLsizei>(_texture->width()), static_cast<GLsizei>(_texture->height()));
_fboProgramObject->activate();
ghoul::opengl::TextureUnit unitFbo;
unitFbo.activate();
_textureProj->bind();
_fboProgramObject->setUniform("texture1" , unitFbo);
ghoul::opengl::TextureUnit unitFbo2;
unitFbo2.activate();
_textureOriginal->bind();
_fboProgramObject->setUniform("texture2", unitFbo2);
_fboProgramObject->setUniform("projectionFading", _fadeProjection);
_fboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix);
_fboProgramObject->setUniform("ModelTransform" , _transform);
_fboProgramObject->setUniform("_scaling" , _camScaling);
_fboProgramObject->setUniform("boresight" , _boresight);
if (_geometry->hasProperty("radius")){
boost::any r = _geometry->property("radius")->get();
if (glm::vec4* radius = boost::any_cast<glm::vec4>(&r)){
_fboProgramObject->setUniform("radius", radius);
}
}else{
LERROR("Geometry object needs to provide radius");
}
if (_geometry->hasProperty("segments")){
boost::any s = _geometry->property("segments")->get();
if (int* segments = boost::any_cast<int>(&s)){
_fboProgramObject->setAttribute("segments", segments[0]);
}
}else{
LERROR("Geometry object needs to provide segment count");
}
glBindVertexArray(_quad);
glDrawArrays(GL_TRIANGLES, 0, 6);
_fboProgramObject->deactivate();
glDisable(GL_BLEND);
//bind back to default
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glViewport(m_viewport[0], m_viewport[1],
m_viewport[2], m_viewport[3]);
}
glm::mat4 RenderablePlanetProjection::computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up){
//rotate boresight into correct alignment
_boresight = _instrumentMatrix*aim;
glm::vec3 uptmp(_instrumentMatrix*glm::dvec3(up));
// create view matrix
glm::vec3 e3 = glm::normalize(_boresight);
glm::vec3 e1 = glm::normalize(glm::cross(uptmp, e3));
glm::vec3 e2 = glm::normalize(glm::cross(e3, e1));
glm::mat4 projViewMatrix = glm::mat4(e1.x, e2.x, e3.x, 0.f,
e1.y, e2.y, e3.y, 0.f,
e1.z, e2.z, e3.z, 0.f,
-glm::dot(e1, loc), -glm::dot(e2, loc), -glm::dot(e3, loc), 1.f);
// create perspective projection matrix
glm::mat4 projProjectionMatrix = glm::perspective(_fovy, _aspectRatio, _nearPlane, _farPlane);
// bias matrix
glm::mat4 projNormalizationMatrix = glm::mat4(0.5f, 0, 0, 0,
0, 0.5f, 0, 0,
0, 0, 0.5f, 0,
0.5f, 0.5f, 0.5f, 1);
return projNormalizationMatrix*projProjectionMatrix*projViewMatrix;
}
void RenderablePlanetProjection::attitudeParameters(double time){
// precomputations for shader
openspace::SpiceManager::ref().getPositionTransformMatrix(_frame, _mainFrame, time, _stateMatrix);
openspace::SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _mainFrame, time, _instrumentMatrix);
_transform = glm::mat4(1);
//90 deg rotation w.r.t spice req.
glm::mat4 rot = glm::rotate(_transform, 90.f, glm::vec3(1, 0, 0));
glm::mat4 roty = glm::rotate(_transform, 90.f, glm::vec3(0, -1, 0));
glm::mat4 rotProp = glm::rotate(_transform, static_cast<float>(_rotation), glm::vec3(0, 1, 0));
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
_transform[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
_transform = _transform * rot * roty * rotProp;
std::string shape, instrument;
std::vector<glm::dvec3> bounds;
glm::dvec3 bs;
bool found = openspace::SpiceManager::ref().getFieldOfView(_instrumentID, shape, instrument, bs, bounds);
//if (!found) LERROR("Could not locate instrument");
if (!found)
return ;
psc position; //observer target
found = SpiceManager::ref().getTargetPosition(_projectorID, _projecteeID, _mainFrame, _aberration, time, position, lightTime);
//change to KM and add psc camera scaling.
position[3] += (3 + _camScaling[1]);
glm::vec3 cpos = position.vec3();
_projectorMatrix = computeProjectorMatrix(cpos, bs, _up);
}
void RenderablePlanetProjection::textureBind(){
ghoul::opengl::TextureUnit unit[2];
unit[0].activate();
_texture->bind();
_programObject->setUniform("texture1", unit[0]);
unit[1].activate();
_textureWhiteSquare->bind();
_programObject->setUniform("texture2", unit[1]);
}
void RenderablePlanetProjection::project(){
for (auto img : _imageTimes){
std::thread t1(&RenderablePlanetProjection::attitudeParameters, this, img.startTime);
t1.join();
_projectionTexturePath = img.path; // path to current images
imageProjectGPU(); //fbopass
}
_capture = false;
}
void RenderablePlanetProjection::clearAllProjections(){
float tmp = _fadeProjection;
_fadeProjection = 1.f;
_projectionTexturePath = _clearingImage;
imageProjectGPU();
_fadeProjection = tmp;
_clearAllProjections = false;
}
#define GPU_PROJ
void RenderablePlanetProjection::render(const RenderData& data){
if (!_programObject) return;
if (!_textureProj) return;
if (_clearAllProjections) clearAllProjections();
_camScaling = data.camera.scaling();
_up = data.camera.lookUpVector();
#ifdef GPU_PROJ
if (_capture && _performProjection)
project();
#endif
attitudeParameters(_time);
_imageTimes.clear();
psc sun_pos;
double lt;
openspace::SpiceManager::ref().getTargetPosition("SUN", _projecteeID, "GALACTIC", "NONE", _time, sun_pos, lt);
// Main renderpass
_programObject->activate();
// setup the data to the shader
_programObject->setUniform("sun_pos", sun_pos.vec3());
_programObject->setUniform("ProjectorMatrix", _projectorMatrix);
_programObject->setUniform("ViewProjection" , data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform" , _transform);
_programObject->setUniform("boresight" , _boresight);
setPscUniforms(_programObject, &data.camera, data.position);
textureBind();
// render geometry
_geometry->render();
// disable shader
_programObject->deactivate();
}
void RenderablePlanetProjection::update(const UpdateData& data){
// set spice-orientation in accordance to timestamp
_time = Time::ref().currentTime();
_capture = false;
if (openspace::ImageSequencer2::ref().isReady() && _performProjection){
openspace::ImageSequencer2::ref().updateSequencer(_time);
_capture = openspace::ImageSequencer2::ref().getImagePaths(_imageTimes, _projecteeID, _instrumentID);
}
if (_programObject->isDirty())
_programObject->rebuildFromFile();
}
void RenderablePlanetProjection::loadProjectionTexture(){
delete _textureProj;
_textureProj = nullptr;
if (_colorTexturePath.value() != "") {
_textureProj = ghoul::io::TextureReader::ref().loadTexture(absPath(_projectionTexturePath));
if (_textureProj) {
_textureProj->uploadTexture();
_textureProj->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
_textureProj->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder);
}
}
}
void RenderablePlanetProjection::loadTexture(){
delete _texture;
_texture = nullptr;
if (_colorTexturePath.value() != "") {
_texture = ghoul::io::TextureReader::ref().loadTexture(_colorTexturePath);
if (_texture) {
_texture->uploadTexture();
_texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
}
}
delete _textureOriginal;
_textureOriginal = nullptr;
if (_colorTexturePath.value() != "") {
_textureOriginal = ghoul::io::TextureReader::ref().loadTexture(_colorTexturePath);
if (_textureOriginal) {
_textureOriginal->uploadTexture();
_textureOriginal->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
}
}
delete _textureWhiteSquare;
_textureWhiteSquare = nullptr;
if (_colorTexturePath.value() != "") {
_textureWhiteSquare = ghoul::io::TextureReader::ref().loadTexture(_defaultProjImage);
if (_textureWhiteSquare) {
_textureWhiteSquare->uploadTexture();
_textureWhiteSquare->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
}
}
}
} // namespace openspace
@@ -0,0 +1,155 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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 __RENDERABLEPLANETPROJECTION_H__
#define __RENDERABLEPLANETPROJECTION_H__
#include <ghoul/opengl/textureunit.h>
// open space includes
#include <openspace/rendering/renderable.h>
#include <openspace/util/imagesequencer2.h>
#include <openspace/util/sequenceparser.h>
#include <openspace/util/hongkangparser.h>
#include <openspace/util/labelparser.h>
#include <openspace/util/decoder.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/triggerproperty.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/opengl/framebufferobject.h>
// ghoul includes
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <openspace/query/query.h>
namespace openspace {
namespace planetgeometryprojection {
class PlanetGeometryProjection;
}
class RenderablePlanetProjection : public Renderable {
public:
RenderablePlanetProjection(const ghoul::Dictionary& dictionary);
~RenderablePlanetProjection();
bool initialize() override;
bool deinitialize() override;
bool isReady() const override;
void render(const RenderData& data) override;
void update(const UpdateData& data) override;
protected:
void loadTexture();
void loadProjectionTexture();
bool auxiliaryRendertarget();
glm::mat4 computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up);
void attitudeParameters(double time);
void textureBind();
void project();
void clearAllProjections();
private:
void imageProjectGPU();
std::map<std::string, Decoder*> _fileTranslation;
properties::StringProperty _colorTexturePath;
properties::StringProperty _projectionTexturePath;
properties::IntProperty _rotation;
properties::FloatProperty _fadeProjection;
properties::BoolProperty _performProjection;
properties::BoolProperty _clearAllProjections;
ghoul::opengl::ProgramObject* _programObject;
ghoul::opengl::ProgramObject* _fboProgramObject;
ghoul::opengl::Texture* _texture;
ghoul::opengl::Texture* _textureOriginal;
ghoul::opengl::Texture* _textureProj;
ghoul::opengl::Texture* _textureWhiteSquare;
planetgeometryprojection::PlanetGeometryProjection* _geometry;
glm::vec2 _camScaling;
glm::vec3 _up;
glm::mat4 _transform;
glm::mat4 _projectorMatrix;
//sequenceloading
std::string _sequenceSource;
std::string _sequenceType;
bool _foundSequence;
// spice
std::string _instrumentID;
std::string _projectorID;
std::string _projecteeID;
std::string _aberration;
std::vector<std::string> _potentialTargets; // @TODO copy-n-paste from renderablefov
float _fovy;
float _aspectRatio;
float _nearPlane;
float _farPlane;
glm::dmat3 _stateMatrix;
glm::dmat3 _instrumentMatrix;
glm::vec3 _boresight;
double _time;
double _previousTime;
double _previousCapture;
double lightTime;
std::vector<Image> _imageTimes;
int _sequenceID;
std::string _target;
std::string _frame;
std::string _defaultProjImage;
std::string _clearingImage;
std::string _next;
bool _capture;
// FBO stuff
GLuint _fboID;
GLuint _quad;
GLuint _vertexPositionBuffer;
};
} // namespace openspace
#endif // __RENDERABLEPLANETPROJECTION_H__
@@ -0,0 +1,127 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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/newhorizons/rendering/simplespheregeometryprojection.h>
#include <openspace/util/constants.h>
namespace {
const std::string _loggerCat = "SimpleSphereGeometryProjection";
}
namespace openspace {
namespace constants {
namespace simplespheregeometryprojection {
const std::string keyRadius = "Radius";
const std::string keySegments = "Segments";
} // namespace simplespheregeometry
}
namespace planetgeometryprojection {
SimpleSphereGeometryProjection::SimpleSphereGeometryProjection(const ghoul::Dictionary& dictionary)
: PlanetGeometryProjection()
, _realRadius("radius", "Radius", glm::vec4(1.f, 1.f, 1.f, 0.f), glm::vec4(-10.f, -10.f, -10.f, -20.f),
glm::vec4(10.f, 10.f, 10.f, 20.f))
, _segments("segments", "Segments", 20, 1, 1000)
, _planet(nullptr)
{
using constants::scenegraphnode::keyName;
using constants::simplespheregeometryprojection::keyRadius;
using constants::simplespheregeometryprojection::keySegments;
// The name is passed down from the SceneGraphNode
bool success = dictionary.getValue(keyName, _name);
assert(success);
// removing "Projection"-suffix from name for SPICE compability, TODO: better solution @AA
if(_name.find("Projection"))
_name = _name.substr(0, _name.size() - 10);
glm::vec4 radius;
success = dictionary.getValue(keyRadius, _modRadius);
if (!success) {
LERROR("SimpleSphereGeometry of '" << _name << "' did not provide a key '"
<< keyRadius << "'");
}
else {
radius[0] = _modRadius[0];
radius[1] = _modRadius[0];
radius[2] = _modRadius[0];
radius[3] = _modRadius[1];
_realRadius = radius;
}
double segments;
success = dictionary.getValue(keySegments, segments);
if (!success) {
LERROR("SimpleSphereGeometry of '" << _name << "' did not provide a key '"
<< keySegments << "'");
}
else
_segments = static_cast<int>(segments);
addProperty(_realRadius);
//_realRadius.onChange(std::bind(&SimpleSphereGeometryProjection::createSphere, this));
addProperty(_segments);
_segments.onChange(std::bind(&SimpleSphereGeometryProjection::createSphere, this));
}
SimpleSphereGeometryProjection::~SimpleSphereGeometryProjection()
{
}
bool SimpleSphereGeometryProjection::initialize(RenderablePlanetProjection* parent)
{
bool success = PlanetGeometryProjection::initialize(parent);
createSphere();
//need to have this accessible in planetgeometryprojection for now -- Michal
return success;
}
void SimpleSphereGeometryProjection::deinitialize()
{
delete _planet;
_planet = nullptr;
}
void SimpleSphereGeometryProjection::render()
{
_planet->render();
}
void SimpleSphereGeometryProjection::createSphere()
{
//create the power scaled scalar
PowerScaledScalar planetSize(_modRadius);
_parent->setBoundingSphere(planetSize);
delete _planet;
_planet = new PowerScaledSphere(_realRadius, _segments, _name);
_planet->initialize();
}
} // namespace planetgeometry
} // namespace openspace
@@ -0,0 +1,63 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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 __SIMPLESPHEREGEOMETRYPROJECTION_H__
#define __SIMPLESPHEREGEOMETRYPROJECTION_H__
#include <modules/newhorizons/rendering/planetgeometryprojection.h>
#include <openspace/properties/vectorproperty.h>
#include <openspace/properties/scalarproperty.h>
#include <openspace/util/powerscaledsphere.h>
namespace openspace {
class RenderablePlanet;
namespace planetgeometryprojection {
class SimpleSphereGeometryProjection : public PlanetGeometryProjection {
public:
SimpleSphereGeometryProjection(const ghoul::Dictionary& dictionary);
~SimpleSphereGeometryProjection();
bool initialize(RenderablePlanetProjection* parent) override;
void deinitialize() override;
void render() override;
private:
void createSphere();
glm::vec2 _modRadius;
properties::Vec4Property _realRadius;
properties::IntProperty _segments;
std::string _name;
PowerScaledSphere* _planet;
};
} // namespace planetgeometry
} // namespace openspace
#endif // __SIMPLESPHEREGEOMETRY_H__
@@ -0,0 +1,71 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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 __RENDERABLEPLANET_H__
#define __RENDERABLEPLANET_H__
// open space includes
#include <openspace/rendering/renderable.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/util/updatestructures.h>
// ghoul includes
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
namespace openspace {
namespace planetgeometry {
class PlanetGeometry;
}
class RenderablePlanet : public Renderable {
public:
RenderablePlanet(const ghoul::Dictionary& dictionary);
~RenderablePlanet();
bool initialize() override;
bool deinitialize() override;
void render(const RenderData& data) override;
void update(const UpdateData& data) override;
protected:
void loadTexture();
private:
properties::StringProperty _colorTexturePath;
ghoul::opengl::ProgramObject* _programObject;
ghoul::opengl::Texture* _texture;
planetgeometry::PlanetGeometry* _geometry;
glm::dmat3 _stateMatrix;
std::string _target;
};
} // namespace openspace
#endif // __RENDERABLEPLANET_H__