diff --git a/include/openspace/rendering/renderablefov.h b/include/openspace/rendering/renderablefov.h index 15f1a48f9d..7b2da806d3 100644 --- a/include/openspace/rendering/renderablefov.h +++ b/include/openspace/rendering/renderablefov.h @@ -22,14 +22,20 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __RENDERABLEFOV_H__ -#define __RENDERABLEFOV_H__ +#ifndef __RenderableFov_H__ +#define __RenderableFov_H__ // open space includes #include + #include +#include + +// ghoul includes +#include +#include +//#include #include -#include namespace openspace { class RenderableFov : public Renderable{ @@ -48,54 +54,123 @@ public: properties::StringProperty _colorTexturePath; ghoul::opengl::ProgramObject* _programObject; ghoul::opengl::Texture* _texture; - void loadTexture(); - void fullYearSweep(); + openspace::SceneGraphNode* _targetNode; + + void loadTexture(); + void allocateData(); + void insertPoint(std::vector& arr, psc& p, glm::vec4& c); + void fovProjection(bool H[], std::vector 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); + + double distanceBetweenPoints(psc p1, psc p2); + // instance variables + int _nrInserted = 0; + int _isteps; + bool _rebuild = false; + bool _interceptTag[5]; + bool _withinFOV; + psc _projectionBounds[4]; + psc _interceptVector; - // modfile reads // spice - std::string _target; + std::string _spacecraft; std::string _observer; std::string _frame; - // color + std::string _instrumentID; + std::string _method; + std::string _aberrationCorrection; + std::string _fovTarget; + + glm::dvec3 ipoint, ivec; + glm::dvec3 _previousHalf; glm::vec3 _c; double _r, _g, _b; - // orbit relational data - double _tropic; - double _ratio; - double _day; - // need to write robust method for vbo id selection - // (right now galactic grid has to be present) (why though?) solve later... - GLuint _vaoID ; - GLuint _vBufferID ; - GLuint _iBufferID; + // 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 _varray1; + std::vector _varray2; + int* _iarray1[2]; void updateData(); void sendToGPU(); glm::dmat3 _stateMatrix; - unsigned int _isize; - unsigned int _vsize; - unsigned int _vtotal; - unsigned int _stride; - - double _startTrail; - - //Vertex* _varray; - std::vector _varray; - std::vector _iarray; - - bool _once = false; - - //used for update of trail - psc _pscpos, _pscvel; - double _increment; + // time double _time = 0; double _oldTime = 0; - int _delta = 0; - int _dtprogress = 0; }; } -#endif \ No newline at end of file +#endif +// Scrap stuff i need to keep for now (michal) + + +/* // idk how we will compute the aberrated state. +double RenderableFov::computeTargetLocalTime(PowerScaledScalar d){ +double c = 299792456.075; // m/s +double dt = ( (d[0]*pow(10, d[1])) / c ); +double t_local = _time - dt*86400; + +std::string localTime; +std::string currentTime; + +openspace::SpiceManager::ref().getDateFromET(t_local, localTime); +openspace::SpiceManager::ref().getDateFromET(_time , currentTime); + +std::cout << "time at jupiter : " << localTime << "\time at NH" << currentTime << std::endl; +return t_local; +}*/ + +/* +psc RenderableFov::sphericalInterpolate(glm::dvec3 p0, glm::dvec3 p1, float t){ +double targetEt, lt; +glm::dvec3 ip, iv; +psc targetPos; +SpiceManager::ref().getTargetPosition("JUPITER", _spacecraft, _frame, _aberrationCorrection, _time, targetPos, lt); + +openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID, +_frame, _method, _aberrationCorrection, _time, targetEt, p0, ip, iv); +psc psc0 = PowerScaledCoordinate::CreatePowerScaledCoordinate(iv[0], iv[1], iv[2]); +openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID, +_frame, _method, _aberrationCorrection, _time, targetEt, p1, ip, iv); +psc psc1 = PowerScaledCoordinate::CreatePowerScaledCoordinate(iv[0], iv[1], iv[2]); +psc0[3] += 3; +psc1[3] += 3; + +psc0 -= targetPos; +psc1 -= targetPos; + +double angle = psc0.angle(psc1); + +std::cout << angle << std::endl; + +double sin_a = sin(angle); // opt +double l[2] = { sin((1.f - t)*angle) / sin_a, sin((t)*angle) / sin_a }; + +std::cout << l[0] << " " << l[1] << std::endl; + +float s = ((t-1)*psc0[3] + (t)*psc1[3]); +float x = (l[0]*psc0[0] + l[1]*psc1[0]); +float y = (l[0]*psc0[1] + l[1]*psc1[1]); +float z = (l[0]*psc0[2] + l[1]*psc1[2]); + +psc interpolated = PowerScaledCoordinate::PowerScaledCoordinate(x, y, z, 10); +return interpolated; +} +*/ diff --git a/scripts/default_startup.lua b/scripts/default_startup.lua index 601a131c43..10bb2b91e0 100644 --- a/scripts/default_startup.lua +++ b/scripts/default_startup.lua @@ -1,5 +1,5 @@ --openspace.setPropertyValue('Earth.renderable.colorTexture', '${OPENSPACE_DATA}/modules/mars/textures/mars.png') -openspace.time.setTime("2007-02-25T14:03:57") +openspace.time.setTime("2007-02-26T17:30:00") --openspace.time.setTime("2006-08-22T20:00:00") --openspace.time.setDeltaTime(200000.0) diff --git a/src/rendering/planets/renderableplanetprojection.cpp b/src/rendering/planets/renderableplanetprojection.cpp index 2d1588f1bf..94ae882c2f 100644 --- a/src/rendering/planets/renderableplanetprojection.cpp +++ b/src/rendering/planets/renderableplanetprojection.cpp @@ -217,10 +217,10 @@ void RenderablePlanetProjection::updateTex(){ ghoul::opengl::TextureUnit unit; unit.activate(); - //_texture->bind(); - glUniform1i(location, unit); - GLint format = _texture->internalFormat(); - glBindImageTexture(unit, *_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + _texture->bind(); + //glUniform1i(location, unit); + //GLint format = _texture->internalFormat(); + //glBindImageTexture(unit, *_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); glDispatchCompute(_texture->width() / 16, _texture->height() / 16, 1); glUseProgram(0); @@ -314,9 +314,10 @@ void RenderablePlanetProjection::render(const RenderData& data) _geometry->render(); // disable shader + //updateTex(); + _programObject->deactivate(); - updateTex(); } void RenderablePlanetProjection::imageProject(){ @@ -395,7 +396,6 @@ void RenderablePlanetProjection::imageProject(){ return rgb(v[0], v[1], v[2]); }; - const float w = _texture->width(); const float h = _texture->height(); const float wp = _textureProj->width(); @@ -462,7 +462,7 @@ void RenderablePlanetProjection::loadTexture() delete _texture; _texture = nullptr; if (_colorTexturePath.value() != "") { - _texture = ghoul::io::TextureReader::loadTexture(absPath(_colorTexturePath)); + _texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath)); if (_texture) { LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); _texture->uploadTexture(); @@ -476,7 +476,7 @@ void RenderablePlanetProjection::loadTexture() delete _textureProj; _textureProj = nullptr; if (_colorTexturePath.value() != "") { - _textureProj = ghoul::io::TextureReader::loadTexture(absPath(_projectionTexturePath)); + _textureProj = ghoul::io::TextureReader::ref().loadTexture(absPath(_projectionTexturePath)); if (_textureProj) { LDEBUG("Loaded texture from '" << absPath(_projectionTexturePath) << "'"); _textureProj->uploadTexture(); diff --git a/src/rendering/renderablefov.cpp b/src/rendering/renderablefov.cpp index 1b3507ded7..2bbdc19d7a 100644 --- a/src/rendering/renderablefov.cpp +++ b/src/rendering/renderablefov.cpp @@ -1,242 +1,498 @@ /***************************************************************************************** - * * - * 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. * - ****************************************************************************************/ +* * +* 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 #include #include #include -#include +#include #include +#include + #include #include -#include +#include +#include namespace { - const std::string _loggerCat = "RenderableFov"; - //constants - const std::string keyBody = "Body"; - const std::string keyObserver = "Observer"; - const std::string keyFrame = "Frame"; - const std::string keyPathModule = "ModulePath"; - const std::string keyColor = "RGB"; -} + 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"; + +} //#define DEBUG namespace openspace{ -RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary) - : Renderable(dictionary) - , _colorTexturePath("colorTexture", "Color Texture") - , _programObject(nullptr) - , _texture(nullptr) - , _vaoID(0) - , _vBufferID(0) - , _iBufferID(0) -{ - // @TODO Uncomment when used again, do not depend on assert in constructor --jonasstrandstedt - //dictionary.getValue(keyBody, _target); - //dictionary.getValue(keyObserver, _observer); - //dictionary.getValue(keyFrame, _frame); + // colors, move later + glm::vec4 origin(0); + glm::vec4 col_gray(0.3, 0.3, 0.3, 1); + glm::vec4 col_start(1.00, 0.89, 0.00, 1); + glm::vec4 col_end(1.00, 0.29, 0.00, 1); + glm::vec4 col_sq(1.00, 0.29, 0.00, 1); - if (!dictionary.getValue(keyColor, _c)){ - _c = glm::vec3(0.0); - }else{ - _r = 1 / _c[0]; - _g = 1 / _c[1]; - _b = 1 / _c[2]; - } + glm::vec4 col_proj(1, 1, 1, 1); + + RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _colorTexturePath("colorTexture", "Color Texture") + , _programObject(nullptr) + , _texture(nullptr) + , _mode(GL_LINES){ + + assert(dictionary.getValue(keyBody , _spacecraft)); + assert(dictionary.getValue(keyFrame , _frame)); + assert(dictionary.getValue(keyInstrument , _instrumentID)); + assert(dictionary.getValue(keyInstrumentMethod , _method)); + assert(dictionary.getValue(keyInstrumentAberration , _aberrationCorrection)); } -void RenderableFov::fullYearSweep(){ - +void RenderableFov::allocateData(){ int points = 8; - _stride = 8; - _isize = points; - _iarray.clear(); - + _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++){ - _varray.push_back(0); // pos + _varray1.push_back(0); // pos } for (int j = 0; j < 4; j++){ - _varray.push_back(0); // col + _varray1.push_back(0); // col } - _iarray.push_back(i); + _iarray1[0][i] = i; } - _stride = 8; - _vsize = _varray.size(); - _vtotal = static_cast(_vsize / _stride); + _stride[0] = 8; + _vsize[0] = _varray1.size(); + _vtotal[0] = static_cast(_vsize[0] / _stride[0]); + + // allocate second vbo data + int cornerPoints = 5; + _isize[1] = cornerPoints; + _iarray1[1] = new int[_isize[1]]; + for (int i = 0; i < _isize[1]; i++){ + _iarray1[1][i] = i; + } + _varray2.resize(40); + _vsize[1] = 40; + _vtotal[1] = 5; + _isteps = 5; } RenderableFov::~RenderableFov(){ deinitialize(); } -bool RenderableFov::isReady() const { - bool ready = true; - ready &= (_programObject != nullptr); - - return ready; -} - -void RenderableFov::sendToGPU(){ - // Initialize and upload to graphics card - glGenVertexArrays(1, &_vaoID); - glGenBuffers(1, &_vBufferID); - glGenBuffers(1, &_iBufferID); - - glBindVertexArray(_vaoID); - glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glBufferData(GL_ARRAY_BUFFER, _vsize * sizeof(GLfloat), NULL, GL_STREAM_DRAW); // orphaning the buffer, sending NULL data. - glBufferSubData(GL_ARRAY_BUFFER, 0, _vsize * sizeof(GLfloat), &_varray[0]); - - GLsizei st = sizeof(GLfloat) * _stride; - - 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, _iBufferID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _isize * sizeof(int), _iarray.data(), GL_STATIC_DRAW); - - glBindVertexArray(0); -} - bool RenderableFov::initialize(){ bool completeSuccess = true; if (_programObject == nullptr) completeSuccess &= OsEng.ref().configurationManager().getValue("EphemerisProgram", _programObject); - - SpiceManager::ref().getETfromDate("2007 feb 26 20:00:00", _startTrail); - fullYearSweep(); - sendToGPU(); + allocateData(); + sendToGPU(); return completeSuccess; } bool RenderableFov::deinitialize(){ - if (_texture) - delete _texture; + delete _texture; _texture = nullptr; - - glDeleteVertexArrays(1, &_vaoID); - glDeleteBuffers(1, &_vBufferID); - glDeleteBuffers(1, &_iBufferID); - 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_STREAM_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_STREAM_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& 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++; +} +double RenderableFov::distanceBetweenPoints(psc p1, psc p2){ + PowerScaledScalar dist = (p1 - p2).length(); + return dist[0] * pow(10, dist[1]); +} + +psc RenderableFov::pscInterpolate(psc p0, psc p1, float t){ + assert(t >= 0 && t <= 1); + float t2 = (1.f - t); + return PowerScaledCoordinate::PowerScaledCoordinate(t2*p0[0] + t*p1[0], + t2*p0[1] + t*p1[1], + t2*p0[2] + t*p1[2], + t2*p0[3] + t*p1[3]); +} +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 = openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID, + _frame, _method, _aberrationCorrection, + _time, targetEt, ray, ipoint, ivec); + _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 = openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID, + _frame, _method, _aberrationCorrection, + _time, targetEt, half, ipoint, ivec); + if (glm::distance(_previousHalf, half) < tolerance){ + _previousHalf = glm::dvec3(0); + return half; + } + _previousHalf = half; + //recursive search + if (intercepted == false){ + 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 bounds){ + _nrInserted = 0; + _varray2.clear();// empty the array + + double t; + double tolerance = 0.0000001; // very low tolerance factor + + glm::dvec3 mid; + glm::dvec3 interpolated; + glm::dvec3 current; + glm::dvec3 next; + + for (int i = 0; i < 4; i++){ + int k = (i + 1 > 3) ? 0 : i + 1; + current = bounds[i]; + next = bounds[k]; + if (H[i] == false){ // If point is non-interceptive, project it. + insertPoint(_varray2, orthogonalProjection(current), glm::vec4(1)); + } + 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++){ + t = ((double)j / _isteps); + // TODO: change the interpolate scheme to place points not on a straight line but instead + // using either slerp or some other viable method (goal: eliminate checkForIntercept -method) + 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++){ + t = ((double)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++){ + t = ((double)j / _isteps); + interpolated = interpolate(current, next, t); + _interceptVector = checkForIntercept(interpolated); + insertPoint(_varray2, _interceptVector, col_sq); + } + } + } + // only if new points are inserted are we interested in rebuilding the + // vbo. Note that this can be optimized but is left as is for now. + if (_nrInserted == 0){ + _rebuild = false; + }else{ + _rebuild = true; + //update size etc; + _vtotal[1] = _nrInserted; + _isize[1] = _nrInserted; + _vsize[1] = _varray2.size(); + _iarray1[1] = new int[_isize[1]]; + for (int i = 0; i < _isize[1]; i++) + _iarray1[1][i] = i; + } + +} + void RenderableFov::updateData(){ - glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glBufferSubData(GL_ARRAY_BUFFER, 0, _vsize * sizeof(GLfloat), &_varray[0]); + 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_STREAM_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::render(const RenderData& data){ + assert(_programObject); _programObject->activate(); - // fetch data - glm::mat4 tmat = glm::mat4(1); - glm::mat4 transform(1); glm::mat4 tmp = glm::mat4(1); - glm::mat4 rot = glm::rotate(transform, 90.f, glm::vec3(0, 1, 0)); - for (int i = 0; i < 3; i++){ for (int j = 0; j < 3; j++){ tmp[i][j] = _stateMatrix[i][j]; } } - transform = tmp*rot; - + // setup the data to the shader _programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); _programObject->setUniform("ModelTransform", transform); setPscUniforms(_programObject, &data.camera, data.position); + // update only when time progresses. + if (_oldTime != _time){ + std::string shape, instrument; + std::vector 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"); // fixlater - //boresight vector - std::string shape, name; - shape.resize(32); - name.resize(32); - std::vector bounds; - glm::dvec3 boresight; + float size = 4 * sizeof(float); + int indx = 0; - bool found = openspace::SpiceManager::ref().getFieldOfView("NH_LORRI", shape, name, boresight, bounds); + // set target based on visibility to specific instrument, + // from here on the _fovTarget is the target for all spice functions. + std::string potential[5] = { "Jupiter", "Io", "Europa", "Ganymede", "Callisto" }; + _fovTarget = potential[0]; //default + for (int i = 0; i < 5; i++){ + _withinFOV = openspace::SpiceManager::ref().targetWithinFieldOfView(_instrumentID, potential[i], + _spacecraft, _method, + _aberrationCorrection, _time); + if (_withinFOV){ + _fovTarget = potential[i]; + break; + } + } + + //somehow get target in there. + //_targetNode = sceneGraphNode(_fovTarget); + /*std::vector properties = _targetNode->subOwners(); + for (auto & element : properties) { + std::cout << element->name() << std::endl; + }*/ + //std::cout << _targetNode->renderable.hasProperty("PlanetGeometry") << std::endl; - float size = 4 * sizeof(float); - float *begin = &_varray[0]; - glm::vec4 origin(0); - glm::vec4 col_start(1.00, 0.89, 0.00, 1); - glm::vec4 col_end(1.00, 0.29, 0.00, 1); - glm::vec4 bsight_t(boresight[0], boresight[1], boresight[2], data.position[3]-3); + // for each FOV vector + for (int i = 0; i < 4; i++){ + double targetEpoch; + // compute surface intercept + _interceptTag[i] = openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID, + _frame, _method, _aberrationCorrection, + _time, targetEpoch, bounds[i], ipoint, ivec); + // if not found, use the orthogonal projected point + if (!_interceptTag[i]) _projectionBounds[i] = orthogonalProjection(bounds[i]); + - float sc = 2.2; - glm::vec4 corner1(bounds[0][0], bounds[0][1], bounds[0][2], data.position[3]-sc); - memcpy(begin, glm::value_ptr(origin), size); - memcpy(begin + 4, glm::value_ptr(col_start), size); - memcpy(begin + 8, glm::value_ptr(corner1), size); - memcpy(begin + 12, glm::value_ptr(col_end), size); - - glm::vec4 corner2(bounds[1][0], bounds[1][1], bounds[1][2], data.position[3]-sc); - memcpy(begin + 16, glm::value_ptr(origin), size); - memcpy(begin + 20, glm::value_ptr(col_start), size); - memcpy(begin + 24, glm::value_ptr(corner2), size); - memcpy(begin + 28, glm::value_ptr(col_end), size); - - glm::vec4 corner3(bounds[2][0], bounds[2][1], bounds[2][2], data.position[3]-sc); - memcpy(begin + 32, glm::value_ptr(origin), size); - memcpy(begin + 36, glm::value_ptr(col_start), size); - memcpy(begin + 40, glm::value_ptr(corner3), size); - memcpy(begin + 44, glm::value_ptr(col_end), size); - - glm::vec4 corner4(bounds[3][0], bounds[3][1], bounds[3][2], data.position[3]-sc); - memcpy(begin + 48, glm::value_ptr(origin), size); - memcpy(begin + 52, glm::value_ptr(col_start), size); - memcpy(begin + 56, glm::value_ptr(corner4), size); - memcpy(begin + 60, glm::value_ptr(col_end), size); - - updateData(); - - glBindVertexArray(_vaoID); - glDrawArrays(GL_LINE_STRIP, 0, _vtotal); + // VBO1 : draw vectors representing outer points of FOV. + if (_interceptTag[i]){ + _interceptVector = PowerScaledCoordinate::CreatePowerScaledCoordinate(ivec[0], ivec[1], ivec[2]); + _interceptVector[3] += 3; + // INTERCEPTIONS + memcpy(&_varray1[indx], glm::value_ptr(origin), 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 LARGER THAN OBJECT + memcpy(&_varray1[indx], glm::value_ptr(origin), 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[i].vec4()), size); + indx += 4; + memcpy(&_varray1[indx], glm::value_ptr(glm::vec4(0, 0.5, 0.7, 1)), size); + indx += 4; + }else{ + glm::vec4 corner(bounds[i][0], bounds[i][1], bounds[i][2], data.position[3]); + corner = tmp*corner; + // "INFINITE" FOV + memcpy(&_varray1[indx], glm::value_ptr(origin), 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[4] = _interceptTag[0]; // 0 & 5 same point + // Draw surface square! + fovProjection(_interceptTag, bounds); + updateData(); + } + _oldTime = _time; + + glLineWidth(1.f); + glBindVertexArray(_vaoID[0]); + glDrawArrays(_mode, 0, _vtotal[0]); glBindVertexArray(0); + //render points + glPointSize(2.f); + glBindVertexArray(_vaoID[0]); + glDrawArrays(GL_POINTS, 0, _vtotal[0]); + glBindVertexArray(0); + + //second vbo + glLineWidth(2.f); + glBindVertexArray(_vaoID[1]); + glDrawArrays(GL_LINE_LOOP, 0, _vtotal[1]); + glBindVertexArray(0); + + /*glPointSize(5.f); + glBindVertexArray(_vaoID2); + glDrawArrays(GL_POINTS, 0, _vtotal2); + glBindVertexArray(0); + */ _programObject->deactivate(); } void RenderableFov::update(const UpdateData& data){ - double lightTime; _time = data.time; _delta = data.delta; - - openspace::SpiceManager::ref().getPositionTransformMatrix("NH_SPACECRAFT", "GALACTIC", data.time, _stateMatrix); + openspace::SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _frame, data.time, _stateMatrix); } void RenderableFov::loadTexture() diff --git a/src/util/factorymanager.cpp b/src/util/factorymanager.cpp index b219a47cb1..c86935f333 100644 --- a/src/util/factorymanager.cpp +++ b/src/util/factorymanager.cpp @@ -45,6 +45,12 @@ #include #include +// projection +#include +#include +#include + + // std #include @@ -63,6 +69,7 @@ void FactoryManager::initialize() // Add Renderables _manager->addFactory(new ghoul::TemplateFactory); _manager->factory()->registerClass("RenderablePlanet"); + _manager->factory()->registerClass("RenderablePlanetProjection"); _manager->factory()->registerClass("RenderableStars"); _manager->factory()->registerClass ("RenderableConstellationBounds"); @@ -94,6 +101,11 @@ void FactoryManager::initialize() _manager->factory() ->registerClass("SimpleSphere"); + // Add PlanetGeometryProjection + _manager->addFactory(new ghoul::TemplateFactory); + _manager->factory() + ->registerClass("SimpleSphereProjection"); + // Add ModelGeometry _manager->addFactory(new ghoul::TemplateFactory); _manager->factory()