From cf562ed83f7f2841b7603610590b46efb6b06e79 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 31 Jan 2016 16:48:08 +0100 Subject: [PATCH 01/38] Update data to use the new horizons kernels --- data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data b/data index 48485d99ac..d49e4e4632 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 48485d99ac7ba5e2c378869d4069f03484872e25 +Subproject commit d49e4e4632ea773e7bc8a3d101ab0208b2e74f63 From 14c8621577cf57dfad86848d2e1726bbf3f806a5 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 3 Feb 2016 18:37:02 +0100 Subject: [PATCH 02/38] Fix more GLM degrees->radians changes --- modules/base/rendering/renderableplanet.cpp | 9 ++++++--- modules/base/rendering/renderablesphere.cpp | 4 +++- modules/base/rendering/renderablesphericalgrid.cpp | 2 +- .../newhorizons/rendering/renderablemodelprojection.cpp | 6 +++--- .../newhorizons/rendering/renderableplanetprojection.cpp | 8 ++++---- src/interaction/interactionhandler.cpp | 6 +++--- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/modules/base/rendering/renderableplanet.cpp b/modules/base/rendering/renderableplanet.cpp index a6e49e24ef..ac63ea1d3c 100644 --- a/modules/base/rendering/renderableplanet.cpp +++ b/modules/base/rendering/renderableplanet.cpp @@ -39,6 +39,9 @@ #include #include +#define _USE_MATH_DEFINES +#include + namespace { const std::string _loggerCat = "RenderablePlanet"; @@ -162,9 +165,9 @@ void RenderablePlanet::render(const RenderData& data) glm::mat4 transform = glm::mat4(1); //earth needs to be rotated for that to work. - 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(_rotation), glm::vec3(0, 1, 0)); + glm::mat4 rot = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(1, 0, 0)); + glm::mat4 roty = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(0, -1, 0)); + glm::mat4 rotProp = glm::rotate(transform, glm::radians(static_cast(_rotation)), glm::vec3(0, 1, 0)); for (int i = 0; i < 3; i++){ for (int j = 0; j < 3; j++){ diff --git a/modules/base/rendering/renderablesphere.cpp b/modules/base/rendering/renderablesphere.cpp index eb37cddacd..1f693823f9 100644 --- a/modules/base/rendering/renderablesphere.cpp +++ b/modules/base/rendering/renderablesphere.cpp @@ -31,6 +31,8 @@ #include +#define _USE_MATH_DEFINES +#include namespace { const std::string _loggerCat = "RenderableSphere"; @@ -141,7 +143,7 @@ void RenderableSphere::render(const RenderData& data) { glm::mat4 transform = glm::mat4(1.0); - transform = glm::rotate(transform, 90.f, glm::vec3(1, 0, 0)); + transform = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(1, 0, 0)); // Activate shader diff --git a/modules/base/rendering/renderablesphericalgrid.cpp b/modules/base/rendering/renderablesphericalgrid.cpp index 97023f1daa..936068624a 100644 --- a/modules/base/rendering/renderablesphericalgrid.cpp +++ b/modules/base/rendering/renderablesphericalgrid.cpp @@ -110,7 +110,7 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio _varray[nr].tex[1] = t2; glm::vec4 tmp(x, y, z, 1); - glm::mat4 rot = glm::rotate(glm::mat4(1), 90.f, glm::vec3(1, 0, 0)); + glm::mat4 rot = glm::rotate(glm::mat4(1), static_cast(M_PI_2), glm::vec3(1, 0, 0)); tmp = _gridMatrix*rot*tmp; for (int i = 0; i < 3; i++){ diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp index 6e1eb0d8d0..c695dd2eba 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.cpp +++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp @@ -403,9 +403,9 @@ void RenderableModelProjection::attitudeParameters(double time) { _transform = glm::mat4(1); - glm::mat4 rotPropX = glm::rotate(_transform, static_cast(_rotationX), glm::vec3(1, 0, 0)); - glm::mat4 rotPropY = glm::rotate(_transform, static_cast(_rotationY), glm::vec3(0, 1, 0)); - glm::mat4 rotPropZ = glm::rotate(_transform, static_cast(_rotationZ), glm::vec3(0, 0, 1)); + glm::mat4 rotPropX = glm::rotate(_transform, glm::radians(static_cast(_rotationX)), glm::vec3(1, 0, 0)); + glm::mat4 rotPropY = glm::rotate(_transform, glm::radians(static_cast(_rotationY)), glm::vec3(0, 1, 0)); + glm::mat4 rotPropZ = glm::rotate(_transform, glm::radians(static_cast(_rotationZ)), glm::vec3(0, 0, 1)); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { diff --git a/modules/newhorizons/rendering/renderableplanetprojection.cpp b/modules/newhorizons/rendering/renderableplanetprojection.cpp index 9d3c7d6eaa..ae9b9c2a6e 100644 --- a/modules/newhorizons/rendering/renderableplanetprojection.cpp +++ b/modules/newhorizons/rendering/renderableplanetprojection.cpp @@ -403,14 +403,14 @@ glm::mat4 RenderablePlanetProjection::computeProjectorMatrix(const glm::vec3 loc void RenderablePlanetProjection::attitudeParameters(double time){ // precomputations for shader - _stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, _mainFrame, _time); + _stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, _mainFrame, time); _instrumentMatrix = SpiceManager::ref().positionTransformMatrix(_instrumentID, _mainFrame, time); _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(_rotation), glm::vec3(0, 1, 0)); + glm::mat4 rot = glm::rotate(_transform, static_cast(M_PI_2), glm::vec3(1, 0, 0)); + glm::mat4 roty = glm::rotate(_transform, static_cast(M_PI_2), glm::vec3(0, -1, 0)); + glm::mat4 rotProp = glm::rotate(_transform, static_cast(glm::radians(static_cast(_rotation))), glm::vec3(0, 1, 0)); for (int i = 0; i < 3; i++){ for (int j = 0; j < 3; j++){ diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index bf5d9cab1a..82540af371 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -367,9 +367,9 @@ void InteractionHandler::orbit(const float &dx, const float &dy, const float &dz glm::vec3 cameraRight = glm::cross(_camera->viewDirection(), cameraUp); glm::mat4 transform; - transform = glm::rotate(dx * 10.f, cameraUp) * transform; - transform = glm::rotate(dy * 10.f, cameraRight) * transform; - transform = glm::rotate(dz * 10.f, _camera->viewDirection()) * transform; + transform = glm::rotate(glm::radians(dx * 100.f), cameraUp) * transform; + transform = glm::rotate(glm::radians(dy * 100.f), cameraRight) * transform; + transform = glm::rotate(glm::radians(dz * 100.f), _camera->viewDirection()) * transform; //get "old" focus position From 0ec155713bb1df2393dfa3e9ec97676c2414ead9 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 6 Feb 2016 12:45:48 +0100 Subject: [PATCH 03/38] Change single.xml to use PlanarProjection and (0,0,0) user pos instead Remove computed detection of view direction --- config/sgct/single.xml | 14 +++++------- src/rendering/renderengine.cpp | 39 +++++++++++++++++----------------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/config/sgct/single.xml b/config/sgct/single.xml index 0507f9f5c0..b357da1600 100644 --- a/config/sgct/single.xml +++ b/config/sgct/single.xml @@ -18,18 +18,14 @@ - - - - - - - - + + + + - + diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 8dcc23133f..56eaf67f79 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -247,7 +247,7 @@ bool RenderEngine::initializeGL() { } else {*/ // get corner positions, calculating the forth to easily calculate center - glm::vec3 corners[4]; + //glm::vec3 corners[4]; /*corners[0] = wPtr->getCurrentViewport()->getViewPlaneCoords( sgct_core::SGCTProjectionPlane::LowerLeft); corners[1] = wPtr->getCurrentViewport()->getViewPlaneCoords( @@ -256,8 +256,8 @@ bool RenderEngine::initializeGL() { sgct_core::SGCTProjectionPlane::UpperRight); corners[3] = glm::vec3(corners[2][0], corners[0][1], corners[2][2]); */ - const glm::vec3 center = (corners[0] + corners[1] + corners[2] + corners[3]) - / 4.0f; + //const glm::vec3 center = (corners[0] + corners[1] + corners[2] + corners[3]) + /// 4.0f; //#if 0 // // @TODO Remove the ifdef when the next SGCT version is released that requests the @@ -270,27 +270,28 @@ bool RenderEngine::initializeGL() { // const glm::vec3 eyePosition // = sgct_core::ClusterManager::instance()->getUserPtr()->getPos(); //#endif - const glm::vec3 eyePosition = sgct_core::ClusterManager::instance()->getDefaultUserPtr()->getPos(); + //const glm::vec3 eyePosition = sgct_core::ClusterManager::instance()->getDefaultUserPtr()->getPos(); // get viewdirection, stores the direction in the camera, used for culling - const glm::vec3 viewdir = glm::normalize(eyePosition - center); - _mainCamera->setCameraDirection(-viewdir); - _mainCamera->setLookUpVector(glm::vec3(0.0, 1.0, 0.0)); + //const glm::vec3 viewdir = glm::normalize(eyePosition - center); + _mainCamera->setCameraDirection(glm::vec3(0.f, 0.f, -1.f)); + _mainCamera->setLookUpVector(glm::vec3(0.f, 1.f, 0.f)); // set the initial fov to be 0.0 which means everything will be culled - float maxFov = 0.0f; + //float maxFov = 0.0f; + float maxFov = std::numeric_limits::max(); - // for each corner - for (int i = 0; i < 4; ++i) { - // calculate radians to corner - glm::vec3 dir = glm::normalize(eyePosition - corners[i]); - float radsbetween = acos(glm::dot(viewdir, dir)) - / (glm::length(viewdir) * glm::length(dir)); + //// for each corner + //for (int i = 0; i < 4; ++i) { + // // calculate radians to corner + // glm::vec3 dir = glm::normalize(eyePosition - corners[i]); + // float radsbetween = acos(glm::dot(viewdir, dir)) + // / (glm::length(viewdir) * glm::length(dir)); - // the angle to a corner is larger than the current maxima - if (radsbetween > maxFov) { - maxFov = radsbetween; - } - } + // // the angle to a corner is larger than the current maxima + // if (radsbetween > maxFov) { + // maxFov = radsbetween; + // } + //} _mainCamera->setMaxFov(maxFov); //} From 351e38471d2057266a44f9262c4ffe861f1921c5 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 6 Feb 2016 18:46:03 +0100 Subject: [PATCH 04/38] Update ghoul for image texture loading --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index d04752c87d..7f72d4ec0a 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit d04752c87df2d7e391a3b5ef1606ed640990b0b7 +Subproject commit 7f72d4ec0a418cea0f7eb320f0c52cd34cc46e00 From 44d884960bb5b791f2061bb88e2e298d5f64187a Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 6 Feb 2016 19:12:29 +0100 Subject: [PATCH 05/38] Remove the hard-coded ABuffer implementation for support on Mac --- openspace.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openspace.cfg b/openspace.cfg index 5cbca2648a..811a824b90 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -54,6 +54,6 @@ return { File = "${BASE_PATH}/Properties.txt" }, DownloadRequestURL = "http://openspace.itn.liu.se/request.cgi", - RenderingMethod = "ABuffer" -- alternative: "Framebuffer" + --RenderingMethod = "ABuffer" -- alternative: "Framebuffer" } \ No newline at end of file From 2117334b152aa43163fd1c8d069be717fc5161d0 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 7 Feb 2016 14:03:04 +0100 Subject: [PATCH 06/38] Minor changes --- apps/OpenSpace/main.cpp | 2 ++ config/sgct/single.xml | 2 +- src/rendering/renderengine.cpp | 48 ++++++++++++++++------------------ 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 2d0d478ed2..753aa07ed3 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -130,6 +130,8 @@ int main(int argc, char** argv) { _sgctEngine->setExternalControlCallback(mainExternalControlCallback); _sgctEngine->setCharCallbackFunction(mainCharCallback); + sgct::MessageHandler::instance()->setNotifyLevel(sgct::MessageHandler::NOTIFY_ALL); + // set encode and decode functions // NOTE: starts synchronizing before init functions sgct::SharedData::instance()->setEncodeFunction(mainEncodeFun); diff --git a/config/sgct/single.xml b/config/sgct/single.xml index b357da1600..54b6d3aa3a 100644 --- a/config/sgct/single.xml +++ b/config/sgct/single.xml @@ -20,7 +20,7 @@ - + diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 56eaf67f79..ce33acc61e 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -247,34 +247,30 @@ bool RenderEngine::initializeGL() { } else {*/ // get corner positions, calculating the forth to easily calculate center - //glm::vec3 corners[4]; - /*corners[0] = wPtr->getCurrentViewport()->getViewPlaneCoords( - sgct_core::SGCTProjectionPlane::LowerLeft); - corners[1] = wPtr->getCurrentViewport()->getViewPlaneCoords( - sgct_core::SGCTProjectionPlane::UpperLeft); - corners[2] = wPtr->getCurrentViewport()->getViewPlaneCoords( - sgct_core::SGCTProjectionPlane::UpperRight); - corners[3] = glm::vec3(corners[2][0], corners[0][1], corners[2][2]); - */ - //const glm::vec3 center = (corners[0] + corners[1] + corners[2] + corners[3]) - /// 4.0f; - -//#if 0 -// // @TODO Remove the ifdef when the next SGCT version is released that requests the -// // getUserPtr to get a name parameter ---abock -// -// // set the eye position, useful during rendering -// const glm::vec3 eyePosition -// = sgct_core::ClusterManager::instance()->getUserPtr("")->getPos(); -//#else -// const glm::vec3 eyePosition -// = sgct_core::ClusterManager::instance()->getUserPtr()->getPos(); -//#endif + + // glm::vec3 corners[4]; + // sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getWindowPtr(0); + // sgct_core::BaseViewport* vp = wPtr->getViewport(0); + // sgct_core::SGCTProjectionPlane* projectionPlane = vp->getProjectionPlane(); + + // corners[0] = *(projectionPlane->getCoordinatePtr(sgct_core::SGCTProjectionPlane::LowerLeft)); + // corners[1] = *(projectionPlane->getCoordinatePtr(sgct_core::SGCTProjectionPlane::UpperLeft)); + // corners[2] = *(projectionPlane->getCoordinatePtr(sgct_core::SGCTProjectionPlane::UpperRight)); + // corners[3] = glm::vec3(corners[2][0], corners[0][1], corners[2][2]); + // + // const glm::vec3 center = (corners[0] + corners[1] + corners[2] + corners[3]); + //// //const glm::vec3 eyePosition = sgct_core::ClusterManager::instance()->getDefaultUserPtr()->getPos(); - // get viewdirection, stores the direction in the camera, used for culling + ////// get viewdirection, stores the direction in the camera, used for culling //const glm::vec3 viewdir = glm::normalize(eyePosition - center); - _mainCamera->setCameraDirection(glm::vec3(0.f, 0.f, -1.f)); - _mainCamera->setLookUpVector(glm::vec3(0.f, 1.f, 0.f)); + + //const glm::vec3 upVector = corners[0] - corners[1]; + + + //_mainCamera->setCameraDirection(glm::normalize(-viewdir)); + _mainCamera->setCameraDirection(glm::vec3(0.f, 0.f, -1.f)); + //_mainCamera->setLookUpVector(glm::normalize(upVector)); + _mainCamera->setLookUpVector(glm::vec3(0.f, 1.f, 0.f)); // set the initial fov to be 0.0 which means everything will be culled //float maxFov = 0.0f; From 2c9a98a5a58f5a28e3e1fe93efec70f8fd76e9ed Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 21 Feb 2016 02:38:20 +0100 Subject: [PATCH 07/38] Remove data directory --- data | 1 - 1 file changed, 1 deletion(-) delete mode 160000 data diff --git a/data b/data deleted file mode 160000 index bea6ee4af7..0000000000 --- a/data +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bea6ee4af76745ce05b84dd6ae6a9b406bf3d99a From 8031a8c2d464bb299b8af41c2e371e7a34584a31 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 18 Mar 2016 23:00:37 +0100 Subject: [PATCH 08/38] Fixed RenderableModelProject problem with degrees v radians Added 67P coordinate system to onscreen gui --- data/scene/67P/67P.mod | 2 +- .../rendering/renderablemodelprojection.cpp | 2 +- modules/onscreengui/src/gui.cpp | 3 + src/rendering/renderengine.cpp | 56 ++++++++++--------- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/data/scene/67P/67P.mod b/data/scene/67P/67P.mod index dce0892f50..0624cf2bcd 100644 --- a/data/scene/67P/67P.mod +++ b/data/scene/67P/67P.mod @@ -130,4 +130,4 @@ return { }, GuiName = "/Solar/67PTrail" } -} +} \ No newline at end of file diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp index 70a0758ae2..57cb3886ab 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.cpp +++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp @@ -461,7 +461,7 @@ glm::mat4 RenderableModelProjection::computeProjectorMatrix(const glm::vec3 loc, -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); + glm::mat4 projProjectionMatrix = glm::perspective(glm::radians(_fovy), _aspectRatio, _nearPlane, _farPlane); // bias matrix glm::mat4 projNormalizationMatrix = glm::mat4(0.5f, 0, 0, 0, 0, 0.5f, 0, 0, diff --git a/modules/onscreengui/src/gui.cpp b/modules/onscreengui/src/gui.cpp index b984aedd0b..66b0926580 100644 --- a/modules/onscreengui/src/gui.cpp +++ b/modules/onscreengui/src/gui.cpp @@ -382,6 +382,7 @@ void GUI::renderMainWindow() { bool toSun = ImGui::Button("Coordinate System to Sun"); bool toPluto = ImGui::Button("Coordinate System to Pluto"); bool toJupiter = ImGui::Button("Coordinate System to Jupiter"); + bool to67P = ImGui::Button("Coordinate System to 67P"); if (toSun) OsEng.scriptEngine().queueScript("openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun');"); @@ -389,6 +390,8 @@ void GUI::renderMainWindow() { OsEng.scriptEngine().queueScript("openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto');"); if (toJupiter) OsEng.scriptEngine().queueScript("openspace.setPropertyValue('Interaction.coordinateSystem', 'Jupiter');"); + if (to67P) + OsEng.scriptEngine().queueScript("openspace.setPropertyValue('Interaction.coordinateSystem', '67P');"); ImGui::Checkbox("Help", &_help._isEnabled); diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 45f08f3518..102c998406 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -727,6 +727,9 @@ void RenderEngine::changeViewPoint(std::string origin) { SceneGraphNode* newHorizonsNode = scene()->sceneGraphNode("NewHorizons"); SceneGraphNode* newHorizonsPathNodeJ = scene()->sceneGraphNode("NewHorizonsPathJupiter"); SceneGraphNode* newHorizonsPathNodeP = scene()->sceneGraphNode("NewHorizonsPathPluto"); + SceneGraphNode* cg67pNode = scene()->sceneGraphNode("67P"); + SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta"); + RenderablePath* nhPath; SceneGraphNode* jupiterBarycenterNode = scene()->sceneGraphNode("JupiterBarycenter"); @@ -735,14 +738,11 @@ void RenderEngine::changeViewPoint(std::string origin) { //SceneGraphNode* dawnNode = scene()->sceneGraphNode("Dawn"); //SceneGraphNode* vestaNode = scene()->sceneGraphNode("Vesta"); - if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr || - newHorizonsNode == nullptr || jupiterBarycenterNode == nullptr - //|| dawnNode == nullptr - //|| vestaNode == nullptr - ) { - LERROR("Necessary nodes does not exist"); - return; - } + // if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr || + //jupiterBarycenterNode == nullptr) { + // LERROR("Necessary nodes does not exist"); + //return; + // } if (origin == "Pluto") { if (newHorizonsPathNodeP) { @@ -1160,26 +1160,28 @@ void RenderEngine::renderInformation() { glm::vec4 targetColor(0.00, 0.75, 1.00, 1); - double lt; - glm::dvec3 p = - SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", {}, currentTime, lt); - psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); - float a, b, c; - glm::dvec3 radii; - SpiceManager::ref().getValue("PLUTO", "RADII", radii); - a = radii.x; - b = radii.y; - c = radii.z; - float radius = (a + b) / 2.f; - float distToSurf = glm::length(nhPos.vec3()) - radius; - - RenderFont(*_fontInfo, - penPosition, - "Distance to Pluto: % .1f (KM)", - distToSurf - ); - penPosition.y -= _fontInfo->height(); + try { + double lt; + glm::dvec3 p = + SpiceManager::ref().targetPosition("PLUTO", "NEW HORIZONS", "GALACTIC", {}, currentTime, lt); + psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); + float a, b, c; + glm::dvec3 radii; + SpiceManager::ref().getValue("PLUTO", "RADII", radii); + a = radii.x; + b = radii.y; + c = radii.z; + float radius = (a + b) / 2.f; + float distToSurf = glm::length(nhPos.vec3()) - radius; + RenderFont(*_fontInfo, + penPosition, + "Distance to Pluto: % .1f (KM)", + distToSurf + ); + penPosition.y -= _fontInfo->height(); + } + catch (...) {} double remaining = openspace::ImageSequencer2::ref().getNextCaptureTime() - currentTime; float t = static_cast(1.0 - remaining / openspace::ImageSequencer2::ref().getIntervalLength()); From fafc856dd5421ea4129d54fee6c66370841161b7 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 13:53:55 +0200 Subject: [PATCH 09/38] Use only one mod file for NewHorizons and determine the kernels used inside --- data/scene/newhorizons/newhorizons.mod | 116 ++++++++++++++++++------- 1 file changed, 83 insertions(+), 33 deletions(-) diff --git a/data/scene/newhorizons/newhorizons.mod b/data/scene/newhorizons/newhorizons.mod index 8e38b010f5..1bc5688390 100644 --- a/data/scene/newhorizons/newhorizons.mod +++ b/data/scene/newhorizons/newhorizons.mod @@ -1,3 +1,85 @@ +UseAccurateKernels = false + +NewHorizonsKernels = {} +if UseAccurateKernels then + NewHorizonsKernels = { + -- SCLK + "${SPICE}/nh_kernels/sclk/new-horizons_0976.tsc", + -- "${SPICE}/NewHorizonsKernels/new_horizons_413.tsc", + + -- SPK + "${SPICE}/nh_kernels/spk/nh_pred_20141201_20190301_od122.bsp", + -- "${SPICE}/nh_kernels/spk/nh_pred_20120501_20160913_od093.bsp", + "${SPICE}/nh_kernels/spk/plu_all_mvi.spk", + "${SPICE}/jup260.bsp", + -- "${SPICE}/NewHorizonsKernels/de413.bsp", + + -- CK + "${SPICE}/nh_kernels/ck/nh_scispi_2015_pred.bc", + "${SPICE}/nh_kernels/ck/nh_scispi_2015_recon.bc", + "${SPICE}/nh_kernels/ck/nh_lorri_wcs.bc", + "${SPICE}/nh_kernels/ck/plutonet_PS104.bc", + + -- FK + "${SPICE}/nh_kernels/fk/nh_soc_misc_v001.tf", + "${SPICE}/nh_kernels/fk/nh_v220.tf", + + -- IK + "${SPICE}/nh_kernels/ik/nh_alice_v120.ti", + "${SPICE}/nh_kernels/ik/nh_allinstruments_v002.ti", + "${SPICE}/nh_kernels/ik/nh_astr_v000.ti", + "${SPICE}/nh_kernels/ik/nh_fss_v000.ti", + "${SPICE}/nh_kernels/ik/nh_lorri_v100.ti", + "${SPICE}/nh_kernels/ik/nh_pepssi_v110.ti", + "${SPICE}/nh_kernels/ik/nh_ralph_v100.ti", + "${SPICE}/nh_kernels/ik/nh_rex_v100.ti", + "${SPICE}/nh_kernels/ik/nh_sdc_v101.ti", + "${SPICE}/nh_kernels/ik/nh_swap_v100.ti", + + -- LSK + "${SPICE}/nh_kernels/lsk/naif0011.tls", + + -- PCK + "${SPICE}/nh_kernels/pck/nh_targets_v001.tpc", + "${SPICE}/nh_kernels/pck/pck00010.tpc", + "${SPICE}/nh_kernels/pck/nh_pcnh_002.tpc" + }; +else + NewHorizonsKernels = { + --SCLK + + "${SPICE}/NewHorizonsKernels/new_horizons_413.tsc", + + "${SPICE}/NewHorizonsKernels/nhops_CORE_v9g_cdh2.bc", + "${SPICE}/NewHorizonsKernels/nh_ref_20080710_20160101_od059B.bsp", + + "${SPICE}/de430_1850-2150.bsp", + -- CK + "${SPICE}/NewHorizonsKernels/merged_nhpc_2006_v011.bc", + "${SPICE}/NewHorizonsKernels/merged_nhpc_2007_v006.bc", + -- FK + "${SPICE}/NewHorizonsKernels/nh_v200.tf", + -- IK + "${SPICE}/NewHorizonsKernels/nh_alice_v110.ti", + "${SPICE}/NewHorizonsKernels/nh_lorri_v100.ti", + "${SPICE}/NewHorizonsKernels/nh_pepssi_v110.ti", + "${SPICE}/NewHorizonsKernels/nh_ralph_v100.ti", + "${SPICE}/NewHorizonsKernels/nh_rex_v100.ti", + "${SPICE}/NewHorizonsKernels/nh_sdc_v101.ti", + "${SPICE}/NewHorizonsKernels/nh_swap_v100.ti", + -- PCK + + -- SPK + "${SPICE}/jup260.bsp", + "${SPICE}/NewHorizonsKernels/de413.bsp", + "${SPICE}/NewHorizonsKernels/nh_nep_ura_000.bsp", + "${SPICE}/NewHorizonsKernels/nh_recon_e2j_v1.bsp", + "${SPICE}/NewHorizonsKernels/nh_recon_j2sep07_prelimv1.bsp", + "${SPICE}/NewHorizonsKernels/sb_2002jf56_2.bsp", + "${SPICE}/NewHorizonsKernels/nh_plu017.bsp", + } +end + return { -- New Horizons Body module { @@ -35,39 +117,7 @@ return { -- Observer = "PLUTO BARYCENTER", Observer = "SUN", -- Observer = "JUPITER BARYCENTER", - Kernels = { - --SCLK - - "${SPICE}/NewHorizonsKernels/new_horizons_413.tsc", - - "${SPICE}/NewHorizonsKernels/nhops_CORE_v9g_cdh2.bc", - "${SPICE}/NewHorizonsKernels/nh_ref_20080710_20160101_od059B.bsp", - - "${SPICE}/de430_1850-2150.bsp", - -- CK - "${SPICE}/NewHorizonsKernels/merged_nhpc_2006_v011.bc", - "${SPICE}/NewHorizonsKernels/merged_nhpc_2007_v006.bc", - -- FK - "${SPICE}/NewHorizonsKernels/nh_v200.tf", - -- IK - "${SPICE}/NewHorizonsKernels/nh_alice_v110.ti", - "${SPICE}/NewHorizonsKernels/nh_lorri_v100.ti", - "${SPICE}/NewHorizonsKernels/nh_pepssi_v110.ti", - "${SPICE}/NewHorizonsKernels/nh_ralph_v100.ti", - "${SPICE}/NewHorizonsKernels/nh_rex_v100.ti", - "${SPICE}/NewHorizonsKernels/nh_sdc_v101.ti", - "${SPICE}/NewHorizonsKernels/nh_swap_v100.ti", - -- PCK - - -- SPK - "${SPICE}/jup260.bsp", - "${SPICE}/NewHorizonsKernels/de413.bsp", - "${SPICE}/NewHorizonsKernels/nh_nep_ura_000.bsp", - "${SPICE}/NewHorizonsKernels/nh_recon_e2j_v1.bsp", - "${SPICE}/NewHorizonsKernels/nh_recon_j2sep07_prelimv1.bsp", - "${SPICE}/NewHorizonsKernels/sb_2002jf56_2.bsp", - "${SPICE}/NewHorizonsKernels/nh_plu017.bsp", - } + Kernels = NewHorizonsKernels }, GuiName = "/Solar/NewHorizons" }, From f86739073a8923be0e23128722a1d6f988db6c8c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 14:55:14 +0200 Subject: [PATCH 10/38] Add variables to be able to toggle between available and accurate kernels --- .../charonprojection/charonprojection.mod | 17 ++++++++++++--- data/scene/hydra/hydra.mod | 16 +++++++++++--- data/scene/kerberos/kerberos.mod | 16 +++++++++++--- data/scene/newhorizons/newhorizons.mod | 1 - data/scene/nix/nix.mod | 16 +++++++++++--- .../plutoprojectionhybrid.mod | 21 +++++++++++++------ data/scene/styx/styx.mod | 16 +++++++++++--- 7 files changed, 81 insertions(+), 22 deletions(-) diff --git a/data/scene/charonprojection/charonprojection.mod b/data/scene/charonprojection/charonprojection.mod index 0e0cde02f8..622ed99782 100644 --- a/data/scene/charonprojection/charonprojection.mod +++ b/data/scene/charonprojection/charonprojection.mod @@ -1,3 +1,16 @@ +UseAccurateKernels = false + +if UseAccurateKernels then + NewHorizonsKernels = { + "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" + } +else + NewHorizonsKernels = { + "${OPENSPACE_DATA}/spice/de430_1850-2150.bsp" + } +end + + return { -- CharonProjection module { @@ -47,9 +60,7 @@ return { Body = "CHARON", Reference = "ECLIPJ2000", Observer = "PLUTO BARYCENTER", - Kernels = { - "${OPENSPACE_DATA}/spice/de430_1850-2150.bsp" - } + Kernels = NewHorizonsKernels }, Rotation = { Type = "Spice", diff --git a/data/scene/hydra/hydra.mod b/data/scene/hydra/hydra.mod index bf74b5d2e2..f6053a2e61 100644 --- a/data/scene/hydra/hydra.mod +++ b/data/scene/hydra/hydra.mod @@ -1,3 +1,15 @@ +UseAccurateKernels = false + +if UseAccurateKernels then + NewHorizonsKernels = { + "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" + } +else + NewHorizonsKernels = { + "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" + } +end + return { -- Hydra module { @@ -27,9 +39,7 @@ return { Body = "Hydra", Reference = "ECLIPJ2000", Observer = "PLUTO BARYCENTER", - Kernels = { - "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" - } + Kernels = NewHorizonsKernels }, Rotation = { Type = "Spice", diff --git a/data/scene/kerberos/kerberos.mod b/data/scene/kerberos/kerberos.mod index e4f2773943..ecb10bb6c8 100644 --- a/data/scene/kerberos/kerberos.mod +++ b/data/scene/kerberos/kerberos.mod @@ -1,3 +1,15 @@ +UseAccurateKernels = false + +if UseAccurateKernels then + NewHorizonsKernels = { + "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" + } +else + NewHorizonsKernels = { + "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" + } +end + return { -- Styx module { @@ -27,9 +39,7 @@ return { Body = "KERBEROS", Reference = "ECLIPJ2000", Observer = "PLUTO BARYCENTER", - Kernels = { - "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" - } + Kernels = NewHorizonsKernels }, Rotation = { Type = "Spice", diff --git a/data/scene/newhorizons/newhorizons.mod b/data/scene/newhorizons/newhorizons.mod index 1bc5688390..87dacae1a2 100644 --- a/data/scene/newhorizons/newhorizons.mod +++ b/data/scene/newhorizons/newhorizons.mod @@ -1,6 +1,5 @@ UseAccurateKernels = false -NewHorizonsKernels = {} if UseAccurateKernels then NewHorizonsKernels = { -- SCLK diff --git a/data/scene/nix/nix.mod b/data/scene/nix/nix.mod index 5b94f825b1..91a11dcd29 100644 --- a/data/scene/nix/nix.mod +++ b/data/scene/nix/nix.mod @@ -1,3 +1,15 @@ +UseAccurateKernels = false + +if UseAccurateKernels then + NewHorizonsKernels = { + "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" + } +else + NewHorizonsKernels = { + "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" + } +end + return { -- Nix module { @@ -27,9 +39,7 @@ return { Body = "NIX", Reference = "ECLIPJ2000", Observer = "PLUTO BARYCENTER", - Kernels = { - "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" - } + Kernels = NewHorizonsKernels }, Rotation = { Type = "Spice", diff --git a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod b/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod index 5adeb060ff..1ae2d6186e 100644 --- a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod +++ b/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod @@ -1,3 +1,16 @@ +UseAccurateKernels = false + +if UseAccurateKernels then + NewHorizonsKernels = { + "${SPICE}/nh_kernels/spk/NavPE_de433_od122.bsp", + "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" + } +else + NewHorizonsKernels = { + "${SPICE}/NewHorizonsKernels/nh_plu017.bsp" + } +end + return { -- Pluto barycenter module { @@ -8,9 +21,7 @@ return { Body = "PLUTO BARYCENTER", Reference = "ECLIPJ2000", Observer = "SUN", - Kernels = { - "${OPENSPACE_DATA}/spice/de430_1850-2150.bsp" - } + Kernels = NewHorizonsKernels }, }, -- PlutoProjection module @@ -149,9 +160,7 @@ return { Body = "PLUTO", Reference = "GALACTIC", Observer = "PLUTO BARYCENTER", - Kernels = { - "${SPICE}/NewHorizonsKernels/nh_plu017.bsp" - } + Kernels = NewHorizonsKernels }, Rotation = { Type = "Spice", diff --git a/data/scene/styx/styx.mod b/data/scene/styx/styx.mod index 2e4163373b..205dafb3fb 100644 --- a/data/scene/styx/styx.mod +++ b/data/scene/styx/styx.mod @@ -1,3 +1,15 @@ +UseAccurateKernels = false + +if UseAccurateKernels then + NewHorizonsKernels = { + "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" + } +else + NewHorizonsKernels = { + "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" + } +end + return { -- Styx module { @@ -27,9 +39,7 @@ return { Body = "STYX", Reference = "ECLIPJ2000", Observer = "PLUTO BARYCENTER", - Kernels = { - "${SPICE}/NewHorizonsKernels/nh_p4p5_revised.bsp" - } + Kernels = NewHorizonsKernels }, Rotation = { Type = "Spice", From 8f4d3c20ebaa1fcb0790bc68e0be4a8c95e8653c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 15:00:43 +0200 Subject: [PATCH 11/38] Untabify RenderableStars --- modules/base/rendering/renderablestars.cpp | 736 ++++++++++----------- 1 file changed, 368 insertions(+), 368 deletions(-) diff --git a/modules/base/rendering/renderablestars.cpp b/modules/base/rendering/renderablestars.cpp index 503eaa1c67..799f2d3086 100644 --- a/modules/base/rendering/renderablestars.cpp +++ b/modules/base/rendering/renderablestars.cpp @@ -38,7 +38,7 @@ #include namespace { - const std::string _loggerCat = "RenderableStars"; + const std::string _loggerCat = "RenderableStars"; const std::string KeyFile = "File"; const std::string KeyTexture = "Texture"; @@ -47,89 +47,89 @@ namespace { ghoul::filesystem::File* _psfTextureFile; ghoul::filesystem::File* _colorTextureFile; - const int8_t CurrentCacheVersion = 1; + const int8_t CurrentCacheVersion = 1; - struct ColorVBOLayout { - std::array position; // (x,y,z,e) + struct ColorVBOLayout { + std::array position; // (x,y,z,e) - float bvColor; // B-V color value - float luminance; - float absoluteMagnitude; - }; + float bvColor; // B-V color value + float luminance; + float absoluteMagnitude; + }; - struct VelocityVBOLayout { - std::array position; // (x,y,z,e) + struct VelocityVBOLayout { + std::array position; // (x,y,z,e) - float bvColor; // B-V color value - float luminance; - float absoluteMagnitude; + float bvColor; // B-V color value + float luminance; + float absoluteMagnitude; - float vx; // v_x - float vy; // v_y - float vz; // v_z - }; + float vx; // v_x + float vy; // v_y + float vz; // v_z + }; - struct SpeedVBOLayout { - std::array position; // (x,y,z,e) + struct SpeedVBOLayout { + std::array position; // (x,y,z,e) - float bvColor; // B-V color value - float luminance; - float absoluteMagnitude; + float bvColor; // B-V color value + float luminance; + float absoluteMagnitude; - float speed; - }; + float speed; + }; } namespace openspace { RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) - : Renderable(dictionary) - , _pointSpreadFunctionTexturePath("psfTexture", "Point Spread Function Texture") - , _pointSpreadFunctionTexture(nullptr) - , _pointSpreadFunctionTextureIsDirty(true) - , _colorTexturePath("colorTexture", "ColorBV Texture") - , _colorTexture(nullptr) - , _colorTextureIsDirty(true) - , _colorOption("colorOption", "Color Option") - , _dataIsDirty(true) + : Renderable(dictionary) + , _pointSpreadFunctionTexturePath("psfTexture", "Point Spread Function Texture") + , _pointSpreadFunctionTexture(nullptr) + , _pointSpreadFunctionTextureIsDirty(true) + , _colorTexturePath("colorTexture", "ColorBV Texture") + , _colorTexture(nullptr) + , _colorTextureIsDirty(true) + , _colorOption("colorOption", "Color Option") + , _dataIsDirty(true) , _scaleFactor("scaleFactor", "Scale Factor", 1.f, 0.f, 10.f) , _minBillboardSize("minBillboardSize", "Min Billboard Size", 1.f, 1.f, 100.f) - , _program(nullptr) - , _speckFile("") - , _nValuesPerStar(0) - , _vao(0) - , _vbo(0) + , _program(nullptr) + , _speckFile("") + , _nValuesPerStar(0) + , _vao(0) + , _vbo(0) { using ghoul::filesystem::File; - std::string texturePath = ""; - dictionary.getValue(KeyTexture, texturePath); - _pointSpreadFunctionTexturePath = absPath(texturePath); + std::string texturePath = ""; + dictionary.getValue(KeyTexture, texturePath); + _pointSpreadFunctionTexturePath = absPath(texturePath); _psfTextureFile = new File(_pointSpreadFunctionTexturePath); - dictionary.getValue(KeyColorMap, texturePath); - _colorTexturePath = absPath(texturePath); + dictionary.getValue(KeyColorMap, texturePath); + _colorTexturePath = absPath(texturePath); _colorTextureFile = new File(_colorTexturePath); - bool success = dictionary.getValue(KeyFile, _speckFile); - if (!success) { - LERROR("SpeckDataSource did not contain key '" << KeyFile << "'"); - return; - } - _speckFile = absPath(_speckFile); + bool success = dictionary.getValue(KeyFile, _speckFile); + if (!success) { + LERROR("SpeckDataSource did not contain key '" << KeyFile << "'"); + return; + } + _speckFile = absPath(_speckFile); - _colorOption.addOption(ColorOption::Color, "Color"); - _colorOption.addOption(ColorOption::Velocity, "Velocity"); - _colorOption.addOption(ColorOption::Speed, "Speed"); - addProperty(_colorOption); - _colorOption.onChange([&]{ _dataIsDirty = true;}); + _colorOption.addOption(ColorOption::Color, "Color"); + _colorOption.addOption(ColorOption::Velocity, "Velocity"); + _colorOption.addOption(ColorOption::Speed, "Speed"); + addProperty(_colorOption); + _colorOption.onChange([&]{ _dataIsDirty = true;}); - addProperty(_pointSpreadFunctionTexturePath); - _pointSpreadFunctionTexturePath.onChange([&]{ _pointSpreadFunctionTextureIsDirty = true; }); + addProperty(_pointSpreadFunctionTexturePath); + _pointSpreadFunctionTexturePath.onChange([&]{ _pointSpreadFunctionTextureIsDirty = true; }); _psfTextureFile->setCallback([&](const File&) { _pointSpreadFunctionTextureIsDirty = true; }); - addProperty(_colorTexturePath); - _colorTexturePath.onChange([&]{ _colorTextureIsDirty = true; }); + addProperty(_colorTexturePath); + _colorTexturePath.onChange([&]{ _colorTextureIsDirty = true; }); _colorTextureFile->setCallback([&](const File&) { _colorTextureIsDirty = true; }); addProperty(_scaleFactor); @@ -142,34 +142,34 @@ RenderableStars::~RenderableStars() { } bool RenderableStars::isReady() const { - return (_program != nullptr) && (!_fullData.empty()); + return (_program != nullptr) && (!_fullData.empty()); } bool RenderableStars::initialize() { - bool completeSuccess = true; + bool completeSuccess = true; RenderEngine& renderEngine = OsEng.renderEngine(); _program = renderEngine.buildRenderProgram("Star", - "${MODULE_BASE}/shaders/star_vs.glsl", - "${MODULE_BASE}/shaders/star_fs.glsl", - "${MODULE_BASE}/shaders/star_ge.glsl"); + "${MODULE_BASE}/shaders/star_vs.glsl", + "${MODULE_BASE}/shaders/star_fs.glsl", + "${MODULE_BASE}/shaders/star_ge.glsl"); - if (!_program) - return false; - completeSuccess &= loadData(); - completeSuccess &= (_pointSpreadFunctionTexture != nullptr); + if (!_program) + return false; + completeSuccess &= loadData(); + completeSuccess &= (_pointSpreadFunctionTexture != nullptr); - return completeSuccess; + return completeSuccess; } bool RenderableStars::deinitialize() { - glDeleteBuffers(1, &_vbo); - _vbo = 0; - glDeleteVertexArrays(1, &_vao); - _vao = 0; + glDeleteBuffers(1, &_vbo); + _vbo = 0; + glDeleteVertexArrays(1, &_vao); + _vao = 0; - _pointSpreadFunctionTexture = nullptr; - _colorTexture = nullptr; + _pointSpreadFunctionTexture = nullptr; + _colorTexture = nullptr; RenderEngine& renderEngine = OsEng.renderEngine(); if (_program) { @@ -181,324 +181,324 @@ bool RenderableStars::deinitialize() { void RenderableStars::render(const RenderData& data) { glDepthMask(false); - _program->activate(); + _program->activate(); - // @Check overwriting the scaling from the camera; error as parsec->meter conversion - // is done twice? ---abock - glm::vec2 scaling = glm::vec2(1, -19); + // @Check overwriting the scaling from the camera; error as parsec->meter conversion + // is done twice? ---abock + glm::vec2 scaling = glm::vec2(1, -19); - glm::mat4 modelMatrix = glm::mat4(1.0); - glm::mat4 viewMatrix = data.camera.viewMatrix(); - glm::mat4 projectionMatrix = data.camera.projectionMatrix(); + glm::mat4 modelMatrix = glm::mat4(1.0); + glm::mat4 viewMatrix = data.camera.viewMatrix(); + glm::mat4 projectionMatrix = data.camera.projectionMatrix(); using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; _program->setIgnoreUniformLocationError(IgnoreError::Yes); - //_program->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); - //_program->setUniform("ModelTransform", glm::mat4(1.f)); - _program->setUniform("model", modelMatrix); - _program->setUniform("view", viewMatrix); - _program->setUniform("projection", projectionMatrix); + //_program->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); + //_program->setUniform("ModelTransform", glm::mat4(1.f)); + _program->setUniform("model", modelMatrix); + _program->setUniform("view", viewMatrix); + _program->setUniform("projection", projectionMatrix); - _program->setUniform("colorOption", _colorOption); + _program->setUniform("colorOption", _colorOption); _program->setUniform("scaleFactor", _scaleFactor); _program->setUniform("minBillboardSize", _minBillboardSize); - - setPscUniforms(*_program.get(), data.camera, data.position); - _program->setUniform("scaling", scaling); + + setPscUniforms(*_program.get(), data.camera, data.position); + _program->setUniform("scaling", scaling); - ghoul::opengl::TextureUnit psfUnit; - psfUnit.activate(); - if (_pointSpreadFunctionTexture) - _pointSpreadFunctionTexture->bind(); - _program->setUniform("psfTexture", psfUnit); + ghoul::opengl::TextureUnit psfUnit; + psfUnit.activate(); + if (_pointSpreadFunctionTexture) + _pointSpreadFunctionTexture->bind(); + _program->setUniform("psfTexture", psfUnit); - ghoul::opengl::TextureUnit colorUnit; - colorUnit.activate(); - if (_colorTexture) - _colorTexture->bind(); - _program->setUniform("colorTexture", colorUnit); + ghoul::opengl::TextureUnit colorUnit; + colorUnit.activate(); + if (_colorTexture) + _colorTexture->bind(); + _program->setUniform("colorTexture", colorUnit); - glBindVertexArray(_vao); - const GLsizei nStars = static_cast(_fullData.size() / _nValuesPerStar); - glDrawArrays(GL_POINTS, 0, nStars); + glBindVertexArray(_vao); + const GLsizei nStars = static_cast(_fullData.size() / _nValuesPerStar); + glDrawArrays(GL_POINTS, 0, nStars); - glBindVertexArray(0); + glBindVertexArray(0); using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; _program->setIgnoreUniformLocationError(IgnoreError::No); - _program->deactivate(); + _program->deactivate(); - glDepthMask(true); + glDepthMask(true); } void RenderableStars::update(const UpdateData& data) { - if (_dataIsDirty) { - const int value = _colorOption; - LDEBUG("Regenerating data"); + if (_dataIsDirty) { + const int value = _colorOption; + LDEBUG("Regenerating data"); - createDataSlice(ColorOption(value)); + createDataSlice(ColorOption(value)); - int size = static_cast(_slicedData.size()); + int size = static_cast(_slicedData.size()); - if (_vao == 0) { - glGenVertexArrays(1, &_vao); - LDEBUG("Generating Vertex Array id '" << _vao << "'"); - } - if (_vbo == 0) { - glGenBuffers(1, &_vbo); - LDEBUG("Generating Vertex Buffer Object id '" << _vbo << "'"); - } - glBindVertexArray(_vao); - glBindBuffer(GL_ARRAY_BUFFER, _vbo); - glBufferData(GL_ARRAY_BUFFER, - size*sizeof(GLfloat), - &_slicedData[0], - GL_STATIC_DRAW); + if (_vao == 0) { + glGenVertexArrays(1, &_vao); + LDEBUG("Generating Vertex Array id '" << _vao << "'"); + } + if (_vbo == 0) { + glGenBuffers(1, &_vbo); + LDEBUG("Generating Vertex Buffer Object id '" << _vbo << "'"); + } + glBindVertexArray(_vao); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, + size*sizeof(GLfloat), + &_slicedData[0], + GL_STATIC_DRAW); - GLint positionAttrib = _program->attributeLocation("in_position"); - GLint brightnessDataAttrib = _program->attributeLocation("in_brightness"); + GLint positionAttrib = _program->attributeLocation("in_position"); + GLint brightnessDataAttrib = _program->attributeLocation("in_brightness"); - const size_t nStars = _fullData.size() / _nValuesPerStar; - const size_t nValues = _slicedData.size() / nStars; + const size_t nStars = _fullData.size() / _nValuesPerStar; + const size_t nValues = _slicedData.size() / nStars; - GLsizei stride = static_cast(sizeof(GLfloat) * nValues); + GLsizei stride = static_cast(sizeof(GLfloat) * nValues); - glEnableVertexAttribArray(positionAttrib); - glEnableVertexAttribArray(brightnessDataAttrib); - const int colorOption = _colorOption; - switch (colorOption) { - case ColorOption::Color: - glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, stride, - reinterpret_cast(offsetof(ColorVBOLayout, position))); - glVertexAttribPointer(brightnessDataAttrib, 3, GL_FLOAT, GL_FALSE, stride, - reinterpret_cast(offsetof(ColorVBOLayout, bvColor))); - - break; - case ColorOption::Velocity: - { - glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, stride, - reinterpret_cast(offsetof(VelocityVBOLayout, position))); - glVertexAttribPointer(brightnessDataAttrib, 3, GL_FLOAT, GL_FALSE, stride, - reinterpret_cast(offsetof(VelocityVBOLayout, bvColor))); + glEnableVertexAttribArray(positionAttrib); + glEnableVertexAttribArray(brightnessDataAttrib); + const int colorOption = _colorOption; + switch (colorOption) { + case ColorOption::Color: + glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, stride, + reinterpret_cast(offsetof(ColorVBOLayout, position))); + glVertexAttribPointer(brightnessDataAttrib, 3, GL_FLOAT, GL_FALSE, stride, + reinterpret_cast(offsetof(ColorVBOLayout, bvColor))); + + break; + case ColorOption::Velocity: + { + glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, stride, + reinterpret_cast(offsetof(VelocityVBOLayout, position))); + glVertexAttribPointer(brightnessDataAttrib, 3, GL_FLOAT, GL_FALSE, stride, + reinterpret_cast(offsetof(VelocityVBOLayout, bvColor))); - GLint velocityAttrib = _program->attributeLocation("in_velocity"); - glEnableVertexAttribArray(velocityAttrib); - glVertexAttribPointer(velocityAttrib, 3, GL_FLOAT, GL_TRUE, stride, - reinterpret_cast(offsetof(VelocityVBOLayout, vx))); + GLint velocityAttrib = _program->attributeLocation("in_velocity"); + glEnableVertexAttribArray(velocityAttrib); + glVertexAttribPointer(velocityAttrib, 3, GL_FLOAT, GL_TRUE, stride, + reinterpret_cast(offsetof(VelocityVBOLayout, vx))); - break; - } - case ColorOption::Speed: - { - glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, stride, - reinterpret_cast(offsetof(SpeedVBOLayout, position))); - glVertexAttribPointer(brightnessDataAttrib, 3, GL_FLOAT, GL_FALSE, stride, - reinterpret_cast(offsetof(SpeedVBOLayout, bvColor))); + break; + } + case ColorOption::Speed: + { + glVertexAttribPointer(positionAttrib, 4, GL_FLOAT, GL_FALSE, stride, + reinterpret_cast(offsetof(SpeedVBOLayout, position))); + glVertexAttribPointer(brightnessDataAttrib, 3, GL_FLOAT, GL_FALSE, stride, + reinterpret_cast(offsetof(SpeedVBOLayout, bvColor))); - GLint speedAttrib = _program->attributeLocation("in_speed"); - glEnableVertexAttribArray(speedAttrib); - glVertexAttribPointer(speedAttrib, 1, GL_FLOAT, GL_TRUE, stride, - reinterpret_cast(offsetof(SpeedVBOLayout, speed))); + GLint speedAttrib = _program->attributeLocation("in_speed"); + glEnableVertexAttribArray(speedAttrib); + glVertexAttribPointer(speedAttrib, 1, GL_FLOAT, GL_TRUE, stride, + reinterpret_cast(offsetof(SpeedVBOLayout, speed))); - } - } + } + } - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); - _dataIsDirty = false; - } + _dataIsDirty = false; + } - if (_pointSpreadFunctionTextureIsDirty) { - LDEBUG("Reloading Point Spread Function texture"); - _pointSpreadFunctionTexture = nullptr; - if (_pointSpreadFunctionTexturePath.value() != "") { + if (_pointSpreadFunctionTextureIsDirty) { + LDEBUG("Reloading Point Spread Function texture"); + _pointSpreadFunctionTexture = nullptr; + if (_pointSpreadFunctionTexturePath.value() != "") { _pointSpreadFunctionTexture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_pointSpreadFunctionTexturePath))); - if (_pointSpreadFunctionTexture) { - LDEBUG("Loaded texture from '" << absPath(_pointSpreadFunctionTexturePath) << "'"); - _pointSpreadFunctionTexture->uploadTexture(); - } + if (_pointSpreadFunctionTexture) { + LDEBUG("Loaded texture from '" << absPath(_pointSpreadFunctionTexturePath) << "'"); + _pointSpreadFunctionTexture->uploadTexture(); + } delete _psfTextureFile; _psfTextureFile = new ghoul::filesystem::File(_pointSpreadFunctionTexturePath); _psfTextureFile->setCallback([&](const ghoul::filesystem::File&) { _pointSpreadFunctionTextureIsDirty = true; }); - } - _pointSpreadFunctionTextureIsDirty = false; - } + } + _pointSpreadFunctionTextureIsDirty = false; + } - if (_colorTextureIsDirty) { - LDEBUG("Reloading Color Texture"); - _colorTexture = nullptr; - if (_colorTexturePath.value() != "") { + if (_colorTextureIsDirty) { + LDEBUG("Reloading Color Texture"); + _colorTexture = nullptr; + if (_colorTexturePath.value() != "") { _colorTexture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath))); - if (_colorTexture) { - LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); - _colorTexture->uploadTexture(); - } + if (_colorTexture) { + LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); + _colorTexture->uploadTexture(); + } delete _colorTextureFile; _colorTextureFile = new ghoul::filesystem::File(_colorTexturePath); _colorTextureFile->setCallback([&](const ghoul::filesystem::File&) { _colorTextureIsDirty = true; }); - } - _colorTextureIsDirty = false; - } + } + _colorTextureIsDirty = false; + } } bool RenderableStars::loadData() { - std::string _file = _speckFile; - std::string cachedFile = FileSys.cacheManager()->cachedFilename( + std::string _file = _speckFile; + std::string cachedFile = FileSys.cacheManager()->cachedFilename( _file, ghoul::filesystem::CacheManager::Persistent::Yes ); - bool hasCachedFile = FileSys.fileExists(cachedFile); - if (hasCachedFile) { - LINFO("Cached file '" << cachedFile << "' used for Speck file '" << _file << "'"); + bool hasCachedFile = FileSys.fileExists(cachedFile); + if (hasCachedFile) { + LINFO("Cached file '" << cachedFile << "' used for Speck file '" << _file << "'"); - bool success = loadCachedFile(cachedFile); - if (success) - return true; - else - FileSys.cacheManager()->removeCacheFile(_file); - // Intentional fall-through to the 'else' computation to generate the cache - // file for the next run - } - else { - LINFO("Cache for Speck file '" << _file << "' not found"); - } - LINFO("Loading Speck file '" << _file << "'"); + bool success = loadCachedFile(cachedFile); + if (success) + return true; + else + FileSys.cacheManager()->removeCacheFile(_file); + // Intentional fall-through to the 'else' computation to generate the cache + // file for the next run + } + else { + LINFO("Cache for Speck file '" << _file << "' not found"); + } + LINFO("Loading Speck file '" << _file << "'"); - bool success = readSpeckFile(); - if (!success) - return false; + bool success = readSpeckFile(); + if (!success) + return false; - LINFO("Saving cache"); - success = saveCachedFile(cachedFile); + LINFO("Saving cache"); + success = saveCachedFile(cachedFile); - return success; + return success; } bool RenderableStars::readSpeckFile() { - std::string _file = _speckFile; - std::ifstream file(_file); - if (!file.good()) { - LERROR("Failed to open Speck file '" << _file << "'"); - return false; - } + std::string _file = _speckFile; + std::ifstream file(_file); + if (!file.good()) { + LERROR("Failed to open Speck file '" << _file << "'"); + return false; + } - _nValuesPerStar = 0; + _nValuesPerStar = 0; - // The beginning of the speck file has a header that either contains comments - // (signaled by a preceding '#') or information about the structure of the file - // (signaled by the keywords 'datavar', 'texturevar', and 'texture') - std::string line = ""; - while (true) { - std::ifstream::streampos position = file.tellg(); - std::getline(file, line); + // The beginning of the speck file has a header that either contains comments + // (signaled by a preceding '#') or information about the structure of the file + // (signaled by the keywords 'datavar', 'texturevar', and 'texture') + std::string line = ""; + while (true) { + std::ifstream::streampos position = file.tellg(); + std::getline(file, line); - if (line[0] == '#') - continue; + if (line[0] == '#') + continue; - if (line.substr(0, 7) != "datavar" && - line.substr(0, 10) != "texturevar" && - line.substr(0, 7) != "texture") - { - // we read a line that doesn't belong to the header, so we have to jump back - // before the beginning of the current line - file.seekg(position); - break; - } + if (line.substr(0, 7) != "datavar" && + line.substr(0, 10) != "texturevar" && + line.substr(0, 7) != "texture") + { + // we read a line that doesn't belong to the header, so we have to jump back + // before the beginning of the current line + file.seekg(position); + break; + } - if (line.substr(0, 7) == "datavar") { - // datavar lines are structured as follows: - // datavar # description - // where # is the index of the data variable; so if we repeatedly overwrite - // the 'nValues' variable with the latest index, we will end up with the total - // number of values (+3 since X Y Z are not counted in the Speck file index) - std::stringstream str(line); + if (line.substr(0, 7) == "datavar") { + // datavar lines are structured as follows: + // datavar # description + // where # is the index of the data variable; so if we repeatedly overwrite + // the 'nValues' variable with the latest index, we will end up with the total + // number of values (+3 since X Y Z are not counted in the Speck file index) + std::stringstream str(line); - std::string dummy; - str >> dummy; - str >> _nValuesPerStar; - _nValuesPerStar += 1; // We want the number, but the index is 0 based - } - } + std::string dummy; + str >> dummy; + str >> _nValuesPerStar; + _nValuesPerStar += 1; // We want the number, but the index is 0 based + } + } - _nValuesPerStar += 3; // X Y Z are not counted in the Speck file indices + _nValuesPerStar += 3; // X Y Z are not counted in the Speck file indices - do { - std::vector values(_nValuesPerStar); + do { + std::vector values(_nValuesPerStar); - std::getline(file, line); - std::stringstream str(line); + std::getline(file, line); + std::stringstream str(line); - for (int i = 0; i < _nValuesPerStar; ++i) - str >> values[i]; + for (int i = 0; i < _nValuesPerStar; ++i) + str >> values[i]; - _fullData.insert(_fullData.end(), values.begin(), values.end()); - } while (!file.eof()); + _fullData.insert(_fullData.end(), values.begin(), values.end()); + } while (!file.eof()); - return true; + return true; } bool RenderableStars::loadCachedFile(const std::string& file) { - std::ifstream fileStream(file, std::ifstream::binary); - if (fileStream.good()) { - int8_t version = 0; - fileStream.read(reinterpret_cast(&version), sizeof(int8_t)); - if (version != CurrentCacheVersion) { - LINFO("The format of the cached file has changed, deleting old cache"); - fileStream.close(); - FileSys.deleteFile(file); - return false; - } + std::ifstream fileStream(file, std::ifstream::binary); + if (fileStream.good()) { + int8_t version = 0; + fileStream.read(reinterpret_cast(&version), sizeof(int8_t)); + if (version != CurrentCacheVersion) { + LINFO("The format of the cached file has changed, deleting old cache"); + fileStream.close(); + FileSys.deleteFile(file); + return false; + } - int32_t nValues = 0; - fileStream.read(reinterpret_cast(&nValues), sizeof(int32_t)); - fileStream.read(reinterpret_cast(&_nValuesPerStar), sizeof(int32_t)); + int32_t nValues = 0; + fileStream.read(reinterpret_cast(&nValues), sizeof(int32_t)); + fileStream.read(reinterpret_cast(&_nValuesPerStar), sizeof(int32_t)); - _fullData.resize(nValues); - fileStream.read(reinterpret_cast(&_fullData[0]), - nValues * sizeof(_fullData[0])); + _fullData.resize(nValues); + fileStream.read(reinterpret_cast(&_fullData[0]), + nValues * sizeof(_fullData[0])); - bool success = fileStream.good(); - return success; - } - else { - LERROR("Error opening file '" << file << "' for loading cache file"); - return false; - } + bool success = fileStream.good(); + return success; + } + else { + LERROR("Error opening file '" << file << "' for loading cache file"); + return false; + } } bool RenderableStars::saveCachedFile(const std::string& file) const { - std::ofstream fileStream(file, std::ofstream::binary); - if (fileStream.good()) { - fileStream.write(reinterpret_cast(&CurrentCacheVersion), - sizeof(int8_t)); + std::ofstream fileStream(file, std::ofstream::binary); + if (fileStream.good()) { + fileStream.write(reinterpret_cast(&CurrentCacheVersion), + sizeof(int8_t)); - int32_t nValues = static_cast(_fullData.size()); - if (nValues == 0) { - LERROR("Error writing cache: No values were loaded"); - return false; - } - fileStream.write(reinterpret_cast(&nValues), sizeof(int32_t)); + int32_t nValues = static_cast(_fullData.size()); + if (nValues == 0) { + LERROR("Error writing cache: No values were loaded"); + return false; + } + fileStream.write(reinterpret_cast(&nValues), sizeof(int32_t)); - int32_t nValuesPerStar = static_cast(_nValuesPerStar); - fileStream.write(reinterpret_cast(&nValuesPerStar), sizeof(int32_t)); + int32_t nValuesPerStar = static_cast(_nValuesPerStar); + fileStream.write(reinterpret_cast(&nValuesPerStar), sizeof(int32_t)); - size_t nBytes = nValues * sizeof(_fullData[0]); - fileStream.write(reinterpret_cast(&_fullData[0]), nBytes); + size_t nBytes = nValues * sizeof(_fullData[0]); + fileStream.write(reinterpret_cast(&_fullData[0]), nBytes); - bool success = fileStream.good(); - return success; - } - else { - LERROR("Error opening file '" << file << "' for save cache file"); - return false; - } + bool success = fileStream.good(); + return success; + } + else { + LERROR("Error opening file '" << file << "' for save cache file"); + return false; + } } void RenderableStars::createDataSlice(ColorOption option) { - _slicedData.clear(); + _slicedData.clear(); // This is only temporary until the scalegraph is in place ---abock float minDistance = std::numeric_limits::max(); @@ -512,7 +512,7 @@ void RenderableStars::createDataSlice(ColorOption option) { //} } - for (size_t i = 0; i < _fullData.size(); i+=_nValuesPerStar) { + for (size_t i = 0; i < _fullData.size(); i+=_nValuesPerStar) { glm::vec3 p = glm::vec3(_fullData[i + 0], _fullData[i + 1], _fullData[i + 2]); // This is only temporary until the scalegraph is in place. It places all stars @@ -531,24 +531,24 @@ void RenderableStars::createDataSlice(ColorOption option) { // Convert parsecs -> meter psc position = psc(glm::vec4(p * 0.308567756f, 17)); - //position[1] *= parsecsToMetersFactor[0]; - //position[2] *= parsecsToMetersFactor[0]; - //position[3] += parsecsToMetersFactor[1]; + //position[1] *= parsecsToMetersFactor[0]; + //position[2] *= parsecsToMetersFactor[0]; + //position[3] += parsecsToMetersFactor[1]; - switch (option) { - case ColorOption::Color: - { - union { - ColorVBOLayout value; - std::array data; - } layout; + switch (option) { + case ColorOption::Color: + { + union { + ColorVBOLayout value; + std::array data; + } layout; - layout.value.position = { { - position[0], position[1], position[2], position[3] - } }; - - layout.value.bvColor = _fullData[i + 3]; - layout.value.luminance = _fullData[i + 4]; + layout.value.position = { { + position[0], position[1], position[2], position[3] + } }; + + layout.value.bvColor = _fullData[i + 3]; + layout.value.luminance = _fullData[i + 4]; layout.value.absoluteMagnitude = _fullData[i + 5]; #ifdef USING_STELLAR_TEST_GRID @@ -558,59 +558,59 @@ void RenderableStars::createDataSlice(ColorOption option) { #endif _slicedData.insert(_slicedData.end(), - layout.data.begin(), - layout.data.end()); + layout.data.begin(), + layout.data.end()); - break; - } - case ColorOption::Velocity: - { - union { - VelocityVBOLayout value; - std::array data; - } layout; + break; + } + case ColorOption::Velocity: + { + union { + VelocityVBOLayout value; + std::array data; + } layout; - layout.value.position = { { - position[0], position[1], position[2], position[3] - } }; + layout.value.position = { { + position[0], position[1], position[2], position[3] + } }; - layout.value.bvColor = _fullData[i + 3]; - layout.value.luminance = _fullData[i + 4]; - layout.value.absoluteMagnitude = _fullData[i + 5]; + layout.value.bvColor = _fullData[i + 3]; + layout.value.luminance = _fullData[i + 4]; + layout.value.absoluteMagnitude = _fullData[i + 5]; - layout.value.vx = _fullData[i + 12]; - layout.value.vy = _fullData[i + 13]; - layout.value.vz = _fullData[i + 14]; + layout.value.vx = _fullData[i + 12]; + layout.value.vy = _fullData[i + 13]; + layout.value.vz = _fullData[i + 14]; - _slicedData.insert(_slicedData.end(), - layout.data.begin(), - layout.data.end()); - break; - } - case ColorOption::Speed: - { - union { - SpeedVBOLayout value; - std::array data; - } layout; + _slicedData.insert(_slicedData.end(), + layout.data.begin(), + layout.data.end()); + break; + } + case ColorOption::Speed: + { + union { + SpeedVBOLayout value; + std::array data; + } layout; - layout.value.position = { { - position[0], position[1], position[2], position[3] - } }; + layout.value.position = { { + position[0], position[1], position[2], position[3] + } }; - layout.value.bvColor = _fullData[i + 3]; - layout.value.luminance = _fullData[i + 4]; - layout.value.absoluteMagnitude = _fullData[i + 5]; + layout.value.bvColor = _fullData[i + 3]; + layout.value.luminance = _fullData[i + 4]; + layout.value.absoluteMagnitude = _fullData[i + 5]; - layout.value.speed = _fullData[i + 15]; + layout.value.speed = _fullData[i + 15]; - _slicedData.insert(_slicedData.end(), - layout.data.begin(), - layout.data.end()); - break; - } - } - } + _slicedData.insert(_slicedData.end(), + layout.data.begin(), + layout.data.end()); + break; + } + } + } } } // namespace openspace From 72ccfe51e9777c533e7e8988da12c7881f8dac6e Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 15:06:13 +0200 Subject: [PATCH 12/38] Ignore empty lines in Speck file reading (closing #133) --- modules/base/rendering/renderablestars.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/base/rendering/renderablestars.cpp b/modules/base/rendering/renderablestars.cpp index 799f2d3086..87b5ea26c0 100644 --- a/modules/base/rendering/renderablestars.cpp +++ b/modules/base/rendering/renderablestars.cpp @@ -395,7 +395,7 @@ bool RenderableStars::readSpeckFile() { std::ifstream::streampos position = file.tellg(); std::getline(file, line); - if (line[0] == '#') + if (line[0] == '#' || line.empty()) continue; if (line.substr(0, 7) != "datavar" && From 3de5fb3b55efafa36c1d36aecc187e4f9355eeb6 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 15:11:46 +0200 Subject: [PATCH 13/38] Add FloatProperty to RenderableStars to modify transparency (closing #150) --- modules/base/rendering/renderablestars.cpp | 3 ++ modules/base/rendering/renderablestars.h | 61 +++++++++++----------- modules/base/shaders/star_fs.glsl | 2 + 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/modules/base/rendering/renderablestars.cpp b/modules/base/rendering/renderablestars.cpp index 87b5ea26c0..cf3fc50022 100644 --- a/modules/base/rendering/renderablestars.cpp +++ b/modules/base/rendering/renderablestars.cpp @@ -92,6 +92,7 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) , _colorTextureIsDirty(true) , _colorOption("colorOption", "Color Option") , _dataIsDirty(true) + , _alphaValue("alphaValue", "Transparency", 1.f, 0.f, 1.f) , _scaleFactor("scaleFactor", "Scale Factor", 1.f, 0.f, 10.f) , _minBillboardSize("minBillboardSize", "Min Billboard Size", 1.f, 1.f, 100.f) , _program(nullptr) @@ -132,6 +133,7 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) _colorTexturePath.onChange([&]{ _colorTextureIsDirty = true; }); _colorTextureFile->setCallback([&](const File&) { _colorTextureIsDirty = true; }); + addProperty(_alphaValue); addProperty(_scaleFactor); addProperty(_minBillboardSize); } @@ -200,6 +202,7 @@ void RenderableStars::render(const RenderData& data) { _program->setUniform("projection", projectionMatrix); _program->setUniform("colorOption", _colorOption); + _program->setUniform("alphaValue", _alphaValue); _program->setUniform("scaleFactor", _scaleFactor); _program->setUniform("minBillboardSize", _minBillboardSize); diff --git a/modules/base/rendering/renderablestars.h b/modules/base/rendering/renderablestars.h index 68a1e5c8ea..40b9b0fbe6 100644 --- a/modules/base/rendering/renderablestars.h +++ b/modules/base/rendering/renderablestars.h @@ -37,55 +37,56 @@ namespace openspace { class RenderableStars : public Renderable { public: - RenderableStars(const ghoul::Dictionary& dictionary); - ~RenderableStars(); + RenderableStars(const ghoul::Dictionary& dictionary); + ~RenderableStars(); - bool initialize() override; - bool deinitialize() override; + bool initialize() override; + bool deinitialize() override; - bool isReady() const override; + bool isReady() const override; - void render(const RenderData& data) override; - void update(const UpdateData& data) override; + void render(const RenderData& data) override; + void update(const UpdateData& data) override; private: - enum ColorOption { - Color = 0, - Velocity = 1, - Speed = 2 - }; + enum ColorOption { + Color = 0, + Velocity = 1, + Speed = 2 + }; - void createDataSlice(ColorOption option); + void createDataSlice(ColorOption option); - bool loadData(); - bool readSpeckFile(); - bool loadCachedFile(const std::string& file); - bool saveCachedFile(const std::string& file) const; + bool loadData(); + bool readSpeckFile(); + bool loadCachedFile(const std::string& file); + bool saveCachedFile(const std::string& file) const; - properties::StringProperty _pointSpreadFunctionTexturePath; + properties::StringProperty _pointSpreadFunctionTexturePath; std::unique_ptr _pointSpreadFunctionTexture; - bool _pointSpreadFunctionTextureIsDirty; + bool _pointSpreadFunctionTextureIsDirty; - properties::StringProperty _colorTexturePath; + properties::StringProperty _colorTexturePath; std::unique_ptr _colorTexture; - bool _colorTextureIsDirty; + bool _colorTextureIsDirty; - properties::OptionProperty _colorOption; - bool _dataIsDirty; + properties::OptionProperty _colorOption; + bool _dataIsDirty; + properties::FloatProperty _alphaValue; properties::FloatProperty _scaleFactor; properties::FloatProperty _minBillboardSize; - std::unique_ptr _program; + std::unique_ptr _program; - std::string _speckFile; + std::string _speckFile; - std::vector _slicedData; - std::vector _fullData; - int _nValuesPerStar; + std::vector _slicedData; + std::vector _fullData; + int _nValuesPerStar; - GLuint _vao; - GLuint _vbo; + GLuint _vao; + GLuint _vbo; }; } // namespace openspace diff --git a/modules/base/shaders/star_fs.glsl b/modules/base/shaders/star_fs.glsl index 43a9299449..43f77a26b7 100644 --- a/modules/base/shaders/star_fs.glsl +++ b/modules/base/shaders/star_fs.glsl @@ -32,6 +32,7 @@ uniform sampler2D psfTexture; uniform sampler1D colorTexture; uniform float minBillboardSize; +uniform float alphaValue; uniform int colorOption; in vec4 vs_position; @@ -74,6 +75,7 @@ Fragment getFragment() { vec4 textureColor = texture(psfTexture, texCoord); vec4 fullColor = vec4(color.rgb, textureColor.a); + fullColor.a *= alphaValue; vec4 position = vs_position; // This has to be fixed when the scale graph is in place ---emiax From 8d3c667ada2963e365264873ba37d3f7529ffbe4 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 15:13:21 +0200 Subject: [PATCH 14/38] Untabify InteractionHandler files --- .../interaction/interactionhandler.h | 98 ++-- src/interaction/interactionhandler.cpp | 466 +++++++++--------- src/interaction/interactionhandler_lua.inl | 100 ++-- 3 files changed, 332 insertions(+), 332 deletions(-) diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 9a314d2dfe..1b9041700a 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -94,44 +94,44 @@ class InteractionHandler : public properties::PropertyOwner { public: InteractionHandler(); - ~InteractionHandler(); + ~InteractionHandler(); - void setKeyboardController(KeyboardController* controller); - void setMouseController(MouseController* controller); - void addController(Controller* controller); + void setKeyboardController(KeyboardController* controller); + void setMouseController(MouseController* controller); + void addController(Controller* controller); - void lockControls(); - void unlockControls(); + void lockControls(); + void unlockControls(); - void update(double deltaTime); + void update(double deltaTime); - void setFocusNode(SceneGraphNode* node); - const SceneGraphNode* const focusNode() const; - void setCamera(Camera* camera); - const Camera* const camera() const; + void setFocusNode(SceneGraphNode* node); + const SceneGraphNode* const focusNode() const; + void setCamera(Camera* camera); + const Camera* const camera() const; void keyboardCallback(Key key, KeyModifier modifier, KeyAction action); - void mouseButtonCallback(MouseButton button, MouseAction action); - void mousePositionCallback(double x, double y); - void mouseScrollWheelCallback(double pos); + void mouseButtonCallback(MouseButton button, MouseAction action); + void mousePositionCallback(double x, double y); + void mouseScrollWheelCallback(double pos); - double deltaTime() const; + double deltaTime() const; - void orbitDelta(const glm::quat& rotation); + void orbitDelta(const glm::quat& rotation); - void orbit(const float &dx, const float &dy, const float &dz, const float &dist); + void orbit(const float &dx, const float &dy, const float &dz, const float &dist); - //void distance(const float &d); + //void distance(const float &d); - void rotateDelta(const glm::quat& rotation); + void rotateDelta(const glm::quat& rotation); - void distanceDelta(const PowerScaledScalar& distance, size_t iterations = 0); + void distanceDelta(const PowerScaledScalar& distance, size_t iterations = 0); - void lookAt(const glm::quat& rotation); + void lookAt(const glm::quat& rotation); - void setRotation(const glm::quat& rotation); + void setRotation(const glm::quat& rotation); - void resetKeyBindings(); + void resetKeyBindings(); void bindKey(Key key, std::string lua); void setInteractionSensitivity(float sensitivity); @@ -143,51 +143,51 @@ public: void setInvertRotation(bool invert); bool invertRotation() const; - void addKeyframe(const network::datamessagestructures::PositionKeyframe &kf); + void addKeyframe(const network::datamessagestructures::PositionKeyframe &kf); void clearKeyframes(); - /** - * Returns the Lua library that contains all Lua functions available to affect the - * interaction. The functions contained are - * - openspace::luascriptfunctions::setOrigin - * \return The Lua library that contains all Lua functions available to affect the - * interaction - */ - static scripting::ScriptEngine::LuaLibrary luaLibrary(); - + /** + * Returns the Lua library that contains all Lua functions available to affect the + * interaction. The functions contained are + * - openspace::luascriptfunctions::setOrigin + * \return The Lua library that contains all Lua functions available to affect the + * interaction + */ + static scripting::ScriptEngine::LuaLibrary luaLibrary(); + private: - friend class Controller; + friend class Controller; InteractionHandler(const InteractionHandler&) = delete; InteractionHandler& operator=(const InteractionHandler&) = delete; - InteractionHandler(InteractionHandler&&) = delete; - InteractionHandler& operator=(InteractionHandler&&) = delete; + InteractionHandler(InteractionHandler&&) = delete; + InteractionHandler& operator=(InteractionHandler&&) = delete; - Camera* _camera; - SceneGraphNode* _focusNode; + Camera* _camera; + SceneGraphNode* _focusNode; - double _deltaTime; - std::mutex _mutex; + double _deltaTime; + std::mutex _mutex; - bool _validKeyLua; - std::multimap _keyLua; + bool _validKeyLua; + std::multimap _keyLua; float _controllerSensitivity; bool _invertRoll; bool _invertRotation; - KeyboardController* _keyboardController; - MouseController* _mouseController; - std::vector _controllers; + KeyboardController* _keyboardController; + MouseController* _mouseController; + std::vector _controllers; properties::StringProperty _origin; properties::StringProperty _coordinateSystem; - //remote controller - std::vector _keyframes; - double _currentKeyframeTime; - std::mutex _keyframeMutex; + //remote controller + std::vector _keyframes; + double _currentKeyframeTime; + std::mutex _keyframeMutex; }; } // namespace interaction diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 0a032ffa2a..4e68967c79 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -35,19 +35,19 @@ #include namespace { - const std::string _loggerCat = "InteractionHandler"; + const std::string _loggerCat = "InteractionHandler"; openspace::Key stringToKey(std::string s) { - // key only uppercase - std::transform(s.begin(), s.end(), s.begin(), ::toupper); + // key only uppercase + std::transform(s.begin(), s.end(), s.begin(), ::toupper); - // default is unknown + // default is unknown auto it = openspace::KeyMapping.find(s); if (it != openspace::KeyMapping.end()) return it->second; else return openspace::Key::Unknown; - } + } } #include "interactionhandler_lua.inl" @@ -113,18 +113,18 @@ namespace interaction { InteractionHandler::InteractionHandler() : properties::PropertyOwner() - , _camera(nullptr) - , _focusNode(nullptr) + , _camera(nullptr) + , _focusNode(nullptr) , _deltaTime(0.0) , _validKeyLua(false) , _controllerSensitivity(1.f) , _invertRoll(false) , _invertRotation(false) - , _keyboardController(nullptr) - , _mouseController(nullptr) + , _keyboardController(nullptr) + , _mouseController(nullptr) , _origin("origin", "Origin", "") , _coordinateSystem("coordinateSystem", "Coordinate System", "") - , _currentKeyframeTime(-1.0) + , _currentKeyframeTime(-1.0) { setName("Interaction"); @@ -145,38 +145,38 @@ InteractionHandler::InteractionHandler() } InteractionHandler::~InteractionHandler() { - delete _keyboardController; - delete _mouseController; - for (size_t i = 0; i < _controllers.size(); ++i) - delete _controllers[i]; + delete _keyboardController; + delete _mouseController; + for (size_t i = 0; i < _controllers.size(); ++i) + delete _controllers[i]; } void InteractionHandler::setKeyboardController(KeyboardController* controller) { - assert(controller); - delete _keyboardController; - _keyboardController = controller; - _keyboardController->setHandler(this); + assert(controller); + delete _keyboardController; + _keyboardController = controller; + _keyboardController->setHandler(this); } void InteractionHandler::setMouseController(MouseController* controller) { - assert(controller); - delete _mouseController; - _mouseController = controller; - _mouseController->setHandler(this); + assert(controller); + delete _mouseController; + _mouseController = controller; + _mouseController->setHandler(this); } void InteractionHandler::addController(Controller* controller) { - assert(controller); - _controllers.push_back(controller); - controller->setHandler(this); + assert(controller); + _controllers.push_back(controller); + controller->setHandler(this); } void InteractionHandler::lockControls() { - _mutex.lock(); + _mutex.lock(); } void InteractionHandler::unlockControls() { - _mutex.unlock(); + _mutex.unlock(); } //<<<<<<< HEAD @@ -233,16 +233,16 @@ void InteractionHandler::unlockControls() { // unlockControls(); //======= void InteractionHandler::update(double deltaTime) { - _deltaTime = deltaTime; - _mouseController->update(deltaTime); + _deltaTime = deltaTime; + _mouseController->update(deltaTime); bool hasKeys = false; psc pos; glm::quat q; - _keyframeMutex.lock(); + _keyframeMutex.lock(); - if (_keyframes.size() > 4){ //wait until enough samples are buffered + if (_keyframes.size() > 4){ //wait until enough samples are buffered hasKeys = true; openspace::network::datamessagestructures::PositionKeyframe p0, p1, p2, p3; @@ -252,20 +252,20 @@ void InteractionHandler::update(double deltaTime) { p2 = _keyframes[2]; p3 = _keyframes[3]; - //interval check - if (_currentKeyframeTime < p1._timeStamp){ - _currentKeyframeTime = p1._timeStamp; - } + //interval check + if (_currentKeyframeTime < p1._timeStamp){ + _currentKeyframeTime = p1._timeStamp; + } - double t0 = p1._timeStamp; - double t1 = p2._timeStamp; - double fact = (_currentKeyframeTime - t0) / (t1 - t0); + double t0 = p1._timeStamp; + double t1 = p2._timeStamp; + double fact = (_currentKeyframeTime - t0) / (t1 - t0); - //glm::dvec4 v = positionInterpCR.interpolate(fact, _keyframes[0]._position.dvec4(), _keyframes[1]._position.dvec4(), _keyframes[2]._position.dvec4(), _keyframes[3]._position.dvec4()); + //glm::dvec4 v = positionInterpCR.interpolate(fact, _keyframes[0]._position.dvec4(), _keyframes[1]._position.dvec4(), _keyframes[2]._position.dvec4(), _keyframes[3]._position.dvec4()); glm::dvec4 v = ghoul::interpolateLinear(fact, p1._position.dvec4(), p2._position.dvec4()); - + pos = psc(v.x, v.y, v.z, v.w); q = ghoul::interpolateLinear(fact, p1._viewRotationQuat, p2._viewRotationQuat); @@ -282,29 +282,29 @@ void InteractionHandler::update(double deltaTime) { _keyframeMutex.unlock(); if(hasKeys){ - _camera->setPosition(pos); - _camera->setViewRotationMatrix(glm::mat4_cast(q)); + _camera->setPosition(pos); + _camera->setViewRotationMatrix(glm::mat4_cast(q)); } - + - + } void InteractionHandler::setFocusNode(SceneGraphNode* node) { - - if (_focusNode == node){ - return; - } + + if (_focusNode == node){ + return; + } - _focusNode = node; + _focusNode = node; - //orient the camera to the new node - psc focusPos = node->worldPosition(); - psc camToFocus = focusPos - _camera->position(); - glm::vec3 viewDir = glm::normalize(camToFocus.vec3()); - glm::vec3 cameraView = glm::normalize(_camera->viewDirection()); + //orient the camera to the new node + psc focusPos = node->worldPosition(); + psc camToFocus = focusPos - _camera->position(); + glm::vec3 viewDir = glm::normalize(camToFocus.vec3()); + glm::vec3 cameraView = glm::normalize(_camera->viewDirection()); //set new focus position _camera->setFocusPosition(node->worldPosition()); float dot = glm::dot(viewDir, cameraView); @@ -313,25 +313,25 @@ void InteractionHandler::setFocusNode(SceneGraphNode* node) { if (dot < 1.f && dot > -1.f) { //if (glm::length(viewDir - cameraView) < 0.001) { //if (viewDir != cameraView) { - glm::vec3 rotAxis = glm::normalize(glm::cross(viewDir, cameraView)); - float angle = glm::angle(viewDir, cameraView); - glm::quat q = glm::angleAxis(angle, rotAxis); + glm::vec3 rotAxis = glm::normalize(glm::cross(viewDir, cameraView)); + float angle = glm::angle(viewDir, cameraView); + glm::quat q = glm::angleAxis(angle, rotAxis); - //rotate view to target new focus - _camera->rotate(q); + //rotate view to target new focus + _camera->rotate(q); } } const SceneGraphNode* const InteractionHandler::focusNode() const { - return _focusNode; + return _focusNode; } void InteractionHandler::setCamera(Camera* camera) { - assert(camera); - _camera = camera; + assert(camera); + _camera = camera; } const Camera* const InteractionHandler::camera() const { - return _camera; + return _camera; } //void InteractionHandler::keyboardCallback(int key, int action) { @@ -344,71 +344,71 @@ const Camera* const InteractionHandler::camera() const { //} void InteractionHandler::mouseButtonCallback(MouseButton button, MouseAction action) { - if (_mouseController) - _mouseController->button(button, action); + if (_mouseController) + _mouseController->button(button, action); } void InteractionHandler::mousePositionCallback(double x, double y) { - if (_mouseController) - // TODO Remap screen coordinates to [0,1] - _mouseController->move(static_cast(x), static_cast(y)); + if (_mouseController) + // TODO Remap screen coordinates to [0,1] + _mouseController->move(static_cast(x), static_cast(y)); } void InteractionHandler::mouseScrollWheelCallback(double pos) { - if (_mouseController) - _mouseController->scrollWheel(static_cast(pos)); + if (_mouseController) + _mouseController->scrollWheel(static_cast(pos)); } void InteractionHandler::orbit(const float &dx, const float &dy, const float &dz, const float &dist){ - lockControls(); - - glm::vec3 cameraUp = glm::normalize((glm::inverse(_camera->viewRotationMatrix()) * glm::vec4(_camera->lookUpVector(), 0))).xyz(); - glm::vec3 cameraRight = glm::cross(_camera->viewDirection(), cameraUp); + lockControls(); + + glm::vec3 cameraUp = glm::normalize((glm::inverse(_camera->viewRotationMatrix()) * glm::vec4(_camera->lookUpVector(), 0))).xyz(); + glm::vec3 cameraRight = glm::cross(_camera->viewDirection(), cameraUp); - glm::mat4 transform; - transform = glm::rotate(glm::radians(dx * 100.f), cameraUp) * transform; - transform = glm::rotate(glm::radians(dy * 100.f), cameraRight) * transform; - transform = glm::rotate(glm::radians(dz * 100.f), _camera->viewDirection()) * transform; + glm::mat4 transform; + transform = glm::rotate(glm::radians(dx * 100.f), cameraUp) * transform; + transform = glm::rotate(glm::radians(dy * 100.f), cameraRight) * transform; + transform = glm::rotate(glm::radians(dz * 100.f), _camera->viewDirection()) * transform; - - //get "old" focus position - psc focus = _camera->focusPosition(); - - //// get camera position - //psc relative = _camera->position(); + + //get "old" focus position + psc focus = _camera->focusPosition(); + + //// get camera position + //psc relative = _camera->position(); - // get camera position (UNSYNCHRONIZED) - psc relative = _camera->unsynchedPosition(); + // get camera position (UNSYNCHRONIZED) + psc relative = _camera->unsynchedPosition(); - //get relative vector - psc relative_focus_coordinate = relative - focus; - //rotate relative vector - relative_focus_coordinate = glm::inverse(transform) * relative_focus_coordinate.vec4(); - - //get new new position of focus node - psc origin; - if (_focusNode) { - origin = _focusNode->worldPosition(); - } + //get relative vector + psc relative_focus_coordinate = relative - focus; + //rotate relative vector + relative_focus_coordinate = glm::inverse(transform) * relative_focus_coordinate.vec4(); + + //get new new position of focus node + psc origin; + if (_focusNode) { + origin = _focusNode->worldPosition(); + } - //new camera position - relative = origin + relative_focus_coordinate; + //new camera position + relative = origin + relative_focus_coordinate; - float bounds = 2.f * (_focusNode ? _focusNode->boundingSphere().lengthf() : 0.f) / 10.f; + float bounds = 2.f * (_focusNode ? _focusNode->boundingSphere().lengthf() : 0.f) / 10.f; - psc target = relative + relative_focus_coordinate * dist; - //don't fly into objects - if ((target - origin).length() < bounds){ - target = relative; - } + psc target = relative + relative_focus_coordinate * dist; + //don't fly into objects + if ((target - origin).length() < bounds){ + target = relative; + } - unlockControls(); + unlockControls(); _camera->setFocusPosition(origin); - _camera->setPosition(target); - _camera->rotate(glm::quat_cast(transform)); - + _camera->setPosition(target); + _camera->rotate(glm::quat_cast(transform)); + } //void InteractionHandler::distance(const float &d){ @@ -433,35 +433,35 @@ void InteractionHandler::orbit(const float &dx, const float &dy, const float &dz void InteractionHandler::orbitDelta(const glm::quat& rotation) { - lockControls(); + lockControls(); - // the camera position - psc relative = _camera->position(); + // the camera position + psc relative = _camera->position(); - // should be changed to something more dynamic =) - psc origin; - if (_focusNode) { - origin = _focusNode->worldPosition(); - } + // should be changed to something more dynamic =) + psc origin; + if (_focusNode) { + origin = _focusNode->worldPosition(); + } - psc relative_origin_coordinate = relative - origin; - //glm::mat4 rotation_matrix = glm::mat4_cast(glm::inverse(rotation)); - //relative_origin_coordinate = relative_origin_coordinate.vec4() * glm::inverse(rotation); - relative_origin_coordinate = glm::inverse(rotation) * relative_origin_coordinate.vec4(); - relative = relative_origin_coordinate + origin; + psc relative_origin_coordinate = relative - origin; + //glm::mat4 rotation_matrix = glm::mat4_cast(glm::inverse(rotation)); + //relative_origin_coordinate = relative_origin_coordinate.vec4() * glm::inverse(rotation); + relative_origin_coordinate = glm::inverse(rotation) * relative_origin_coordinate.vec4(); + relative = relative_origin_coordinate + origin; glm::mat4 la = glm::lookAt(_camera->position().vec3(), origin.vec3(), glm::rotate(rotation, _camera->lookUpVector())); unlockControls(); - _camera->setPosition(relative); - //camera_->rotate(rotation); - //camera_->setRotation(glm::mat4_cast(rotation)); + _camera->setPosition(relative); + //camera_->rotate(rotation); + //camera_->setRotation(glm::mat4_cast(rotation)); - - _camera->setRotation(la); - //camera_->setLookUpVector(); + + _camera->setRotation(la); + //camera_->setLookUpVector(); - + } //<<<<<<< HEAD @@ -480,46 +480,46 @@ void InteractionHandler::orbitDelta(const glm::quat& rotation) //======= void InteractionHandler::rotateDelta(const glm::quat& rotation) { - _camera->rotate(rotation); + _camera->rotate(rotation); } void InteractionHandler::distanceDelta(const PowerScaledScalar& distance, size_t iterations) { - if (iterations > 5) - return; - //assert(this_); - lockControls(); - - psc relative = _camera->position(); - const psc origin = (_focusNode) ? _focusNode->worldPosition() : psc(); - + if (iterations > 5) + return; + //assert(this_); + lockControls(); + + psc relative = _camera->position(); + const psc origin = (_focusNode) ? _focusNode->worldPosition() : psc(); + unlockControls(); psc relative_origin_coordinate = relative - origin; - const glm::vec3 dir(relative_origin_coordinate.direction()); - glm::vec3 newdir = dir * distance[0]; + const glm::vec3 dir(relative_origin_coordinate.direction()); + glm::vec3 newdir = dir * distance[0]; - relative_origin_coordinate = newdir; - relative_origin_coordinate[3] = distance[1]; - relative = relative + relative_origin_coordinate; + relative_origin_coordinate = newdir; + relative_origin_coordinate[3] = distance[1]; + relative = relative + relative_origin_coordinate; - relative_origin_coordinate = relative - origin; - if (relative_origin_coordinate.vec4().x == 0.f && relative_origin_coordinate.vec4().y == 0.f && relative_origin_coordinate.vec4().z == 0.f) - // TODO: this shouldn't be allowed to happen; a mechanism to prevent the camera to coincide with the origin is necessary (ab) - return; + relative_origin_coordinate = relative - origin; + if (relative_origin_coordinate.vec4().x == 0.f && relative_origin_coordinate.vec4().y == 0.f && relative_origin_coordinate.vec4().z == 0.f) + // TODO: this shouldn't be allowed to happen; a mechanism to prevent the camera to coincide with the origin is necessary (ab) + return; - newdir = relative_origin_coordinate.direction(); + newdir = relative_origin_coordinate.direction(); - // update only if on the same side of the origin - if (glm::angle(newdir, dir) < 90.0f) { - _camera->setPosition(relative); - } - else { - PowerScaledScalar d2 = distance; - d2[0] *= 0.75f; - d2[1] *= 0.85f; - distanceDelta(d2, iterations + 1); - } + // update only if on the same side of the origin + if (glm::angle(newdir, dir) < 90.0f) { + _camera->setPosition(relative); + } + else { + PowerScaledScalar d2 = distance; + d2[0] *= 0.75f; + d2[1] *= 0.85f; + distanceDelta(d2, iterations + 1); + } } void InteractionHandler::lookAt(const glm::quat& rotation) @@ -529,50 +529,50 @@ void InteractionHandler::lookAt(const glm::quat& rotation) void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) { // TODO package in script const float speed = _controllerSensitivity; - const float dt = static_cast(_deltaTime); + const float dt = static_cast(_deltaTime); if (action == KeyAction::Press || action == KeyAction::Repeat) { if ((key == Key::Right) && (modifier == KeyModifier::NoModifier)) { - glm::vec3 euler(0.0, speed * dt*0.4, 0.0); - glm::quat rot = glm::quat(euler); - rotateDelta(rot); - } + glm::vec3 euler(0.0, speed * dt*0.4, 0.0); + glm::quat rot = glm::quat(euler); + rotateDelta(rot); + } if ((key == Key::Left) && (modifier == KeyModifier::NoModifier)) { - glm::vec3 euler(0.0, -speed * dt*0.4, 0.0); - glm::quat rot = glm::quat(euler); - rotateDelta(rot); - } + glm::vec3 euler(0.0, -speed * dt*0.4, 0.0); + glm::quat rot = glm::quat(euler); + rotateDelta(rot); + } if ((key == Key::Down) && (modifier == KeyModifier::NoModifier)) { - glm::vec3 euler(speed * dt*0.4, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotateDelta(rot); - } + glm::vec3 euler(speed * dt*0.4, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + rotateDelta(rot); + } if ((key == Key::Up) && (modifier == KeyModifier::NoModifier)) { - glm::vec3 euler(-speed * dt*0.4, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotateDelta(rot); - } + glm::vec3 euler(-speed * dt*0.4, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + rotateDelta(rot); + } if ((key == Key::KeypadSubtract) && (modifier == KeyModifier::NoModifier)) { - glm::vec2 s = OsEng.renderEngine().camera()->scaling(); - s[1] -= 0.5f; - OsEng.renderEngine().camera()->setScaling(s); - } + glm::vec2 s = OsEng.renderEngine().camera()->scaling(); + s[1] -= 0.5f; + OsEng.renderEngine().camera()->setScaling(s); + } if ((key == Key::KeypadAdd) && (modifier == KeyModifier::NoModifier)) { - glm::vec2 s = OsEng.renderEngine().camera()->scaling(); - s[1] += 0.5f; - OsEng.renderEngine().camera()->setScaling(s); - } + glm::vec2 s = OsEng.renderEngine().camera()->scaling(); + s[1] += 0.5f; + OsEng.renderEngine().camera()->setScaling(s); + } - // iterate over key bindings - _validKeyLua = true; - auto ret = _keyLua.equal_range(key); - for (auto it = ret.first; it != ret.second; ++it) { - //OsEng.scriptEngine()->runScript(it->second); - OsEng.scriptEngine().queueScript(it->second); - if (!_validKeyLua) { - break; - } - } - } + // iterate over key bindings + _validKeyLua = true; + auto ret = _keyLua.equal_range(key); + for (auto it = ret.first; it != ret.second; ++it) { + //OsEng.scriptEngine()->runScript(it->second); + OsEng.scriptEngine().queueScript(it->second); + if (!_validKeyLua) { + break; + } + } + } } // //void InteractionHandler::mouseButtonCallback(int key, int action) { @@ -613,43 +613,43 @@ void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyActi // // void InteractionHandler::resetKeyBindings() { - _keyLua.clear(); - _validKeyLua = false; + _keyLua.clear(); + _validKeyLua = false; } void InteractionHandler::bindKey(Key key, std::string lua) { - _keyLua.insert(std::make_pair(key, lua)); + _keyLua.insert(std::make_pair(key, lua)); } scripting::ScriptEngine::LuaLibrary InteractionHandler::luaLibrary() { - return { - "", - { - { - "clearKeys", - &luascriptfunctions::clearKeys, - "", - "Clear all key bindings" - }, - { - "bindKey", - &luascriptfunctions::bindKey, - "string, string", - "Binds a key by name to a lua string command" - }, - { - "dt", - &luascriptfunctions::dt, - "", - "Get current frame time" - }, - { - "distance", - &luascriptfunctions::distance, - "number", - "Change distance to origin", + return { + "", + { + { + "clearKeys", + &luascriptfunctions::clearKeys, + "", + "Clear all key bindings" + }, + { + "bindKey", + &luascriptfunctions::bindKey, + "string, string", + "Binds a key by name to a lua string command" + }, + { + "dt", + &luascriptfunctions::dt, + "", + "Get current frame time" + }, + { + "distance", + &luascriptfunctions::distance, + "number", + "Change distance to origin", true - }, + }, { "setInteractionSensitivity", &luascriptfunctions::setInteractionSensitivity, @@ -687,18 +687,18 @@ scripting::ScriptEngine::LuaLibrary InteractionHandler::luaLibrary() { "Returns the status of rotation movement inversion" } - } - }; + } + }; } //======= void InteractionHandler::setRotation(const glm::quat& rotation) { - _camera->setRotation(rotation); + _camera->setRotation(rotation); } double InteractionHandler::deltaTime() const { - return _deltaTime; + return _deltaTime; } void InteractionHandler::setInteractionSensitivity(float sensitivity) { @@ -726,15 +726,15 @@ bool InteractionHandler::invertRotation() const { } void InteractionHandler::addKeyframe(const network::datamessagestructures::PositionKeyframe &kf){ - _keyframeMutex.lock(); + _keyframeMutex.lock(); - //save a maximum of 10 samples (1 seconds of buffer) - if (_keyframes.size() >= 10){ - _keyframes.erase(_keyframes.begin()); - } + //save a maximum of 10 samples (1 seconds of buffer) + if (_keyframes.size() >= 10){ + _keyframes.erase(_keyframes.begin()); + } _keyframes.push_back(kf); - _keyframeMutex.unlock(); + _keyframeMutex.unlock(); } void InteractionHandler::clearKeyframes(){ diff --git a/src/interaction/interactionhandler_lua.inl b/src/interaction/interactionhandler_lua.inl index a51dfc011a..eeb7ca99c3 100644 --- a/src/interaction/interactionhandler_lua.inl +++ b/src/interaction/interactionhandler_lua.inl @@ -32,28 +32,28 @@ namespace luascriptfunctions { * Set the origin of the camera */ int setOrigin(lua_State* L) { - using ghoul::lua::luaTypeToString; - const std::string _loggerCat = "lua.setOrigin"; + using ghoul::lua::luaTypeToString; + const std::string _loggerCat = "lua.setOrigin"; - int nArguments = lua_gettop(L); - if (nArguments != 1) - return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + int nArguments = lua_gettop(L); + if (nArguments != 1) + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); - const int type = lua_type(L, -1); - if (type != LUA_TSTRING) - return luaL_error(L, "Expected string, got %i", type); + const int type = lua_type(L, -1); + if (type != LUA_TSTRING) + return luaL_error(L, "Expected string, got %i", type); - std::string s = luaL_checkstring(L, -1); + std::string s = luaL_checkstring(L, -1); - SceneGraphNode* node = sceneGraphNode(s); - if (!node) { - LWARNING("Could not find a node in scenegraph called '" << s <<"'"); - return 0; - } + SceneGraphNode* node = sceneGraphNode(s); + if (!node) { + LWARNING("Could not find a node in scenegraph called '" << s <<"'"); + return 0; + } - OsEng.interactionHandler().setFocusNode(node); + OsEng.interactionHandler().setFocusNode(node); - return 0; + return 0; } /** @@ -62,31 +62,31 @@ int setOrigin(lua_State* L) { * Binds a key to Lua command */ int bindKey(lua_State* L) { - using ghoul::lua::luaTypeToString; - const std::string _loggerCat = "lua.bindKey"; + using ghoul::lua::luaTypeToString; + const std::string _loggerCat = "lua.bindKey"; - int nArguments = lua_gettop(L); - if (nArguments != 2) - return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments); + int nArguments = lua_gettop(L); + if (nArguments != 2) + return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments); - std::string key = luaL_checkstring(L, -2); - std::string command = luaL_checkstring(L, -1); + std::string key = luaL_checkstring(L, -2); + std::string command = luaL_checkstring(L, -1); - if (command.empty()) - return luaL_error(L, "Command string is empty"); + if (command.empty()) + return luaL_error(L, "Command string is empty"); openspace::Key iKey = stringToKey(key); if (iKey == openspace::Key::Unknown) { - LERROR("Could not find key '"<< key <<"'"); - return 0; - } + LERROR("Could not find key '"<< key <<"'"); + return 0; + } - OsEng.interactionHandler().bindKey(iKey, command); + OsEng.interactionHandler().bindKey(iKey, command); - return 0; + return 0; } /** @@ -95,16 +95,16 @@ int bindKey(lua_State* L) { * Clears all key bindings */ int clearKeys(lua_State* L) { - using ghoul::lua::luaTypeToString; - const std::string _loggerCat = "lua.clearKeys"; + using ghoul::lua::luaTypeToString; + const std::string _loggerCat = "lua.clearKeys"; - int nArguments = lua_gettop(L); - if (nArguments != 0) - return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); + int nArguments = lua_gettop(L); + if (nArguments != 0) + return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); - OsEng.interactionHandler().resetKeyBindings(); + OsEng.interactionHandler().resetKeyBindings(); - return 0; + return 0; } /** @@ -113,12 +113,12 @@ int clearKeys(lua_State* L) { * Get current frame time */ int dt(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 0) - return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); + int nArguments = lua_gettop(L); + if (nArguments != 0) + return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); - lua_pushnumber(L,OsEng.interactionHandler().deltaTime()); - return 1; + lua_pushnumber(L,OsEng.interactionHandler().deltaTime()); + return 1; } /** @@ -127,15 +127,15 @@ int dt(lua_State* L) { * Change distance to origin */ int distance(lua_State* L) { - int nArguments = lua_gettop(L); - if (nArguments != 2) - return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments); + int nArguments = lua_gettop(L); + if (nArguments != 2) + return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments); - double d1 = luaL_checknumber(L, -2); - double d2 = luaL_checknumber(L, -1); - PowerScaledScalar dist(static_cast(d1), static_cast(d2)); - OsEng.interactionHandler().distanceDelta(dist); - return 0; + double d1 = luaL_checknumber(L, -2); + double d2 = luaL_checknumber(L, -1); + PowerScaledScalar dist(static_cast(d1), static_cast(d2)); + OsEng.interactionHandler().distanceDelta(dist); + return 0; } /** From 352e7283d6028091d07ad20e7fb86a5ad7380346 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 8 Apr 2016 18:03:09 +0200 Subject: [PATCH 15/38] Enable the usage of modifiers in bindKey calls (closing #158) --- .../interaction/interactionhandler.h | 57 +--- include/openspace/util/keys.h | 282 ++++++++++-------- src/CMakeLists.txt | 1 + src/interaction/interactionhandler.cpp | 170 +---------- src/interaction/interactionhandler_lua.inl | 12 +- src/util/keys.cpp | 99 ++++++ 6 files changed, 271 insertions(+), 350 deletions(-) create mode 100644 src/util/keys.cpp diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 1b9041700a..2661603342 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -22,55 +22,6 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -//<<<<<<< HEAD -//#ifndef INTERACTIONHANDLER_H -//#define INTERACTIONHANDLER_H -// -//#include -//#include -//#include -// -//// std includes -//#include -//#include -//#include -//#include -// -//namespace openspace { -// -//// Forward declare to minimize dependencies -//class Camera; -//class SceneGraphNode; -//class ExternalControl; -// -//class InteractionHandler { -//public: -// InteractionHandler(void); -// InteractionHandler(const InteractionHandler& src); -// InteractionHandler& operator=(const InteractionHandler& rhs); -// virtual ~InteractionHandler(); -// -// void enable(); -// void disable(); -// const bool isEnabled() const; -// -// void connectDevices(); -// void addExternalControl(ExternalControl* controller); -// -// void setCamera(Camera *camera = nullptr); -// void setOrigin(SceneGraphNode* node); -// -// Camera* getCamera() const; -// const psc getOrigin() const; -// void lockControls(); -// void unlockControls(); -// -// void setFocusNode(SceneGraphNode *node); -// -// void orbit(const glm::quat &rotation); -// void rotate(const glm::quat &rotation); -// void distance(const PowerScaledScalar &distance, size_t iterations = 0); -//======= #ifndef __INTERACTIONHANDLER_H__ #define __INTERACTIONHANDLER_H__ @@ -132,7 +83,7 @@ public: void setRotation(const glm::quat& rotation); void resetKeyBindings(); - void bindKey(Key key, std::string lua); + void bindKey(Key key, KeyModifier modifier, std::string lua); void setInteractionSensitivity(float sensitivity); float interactionSensitivity() const; @@ -154,9 +105,8 @@ public: * interaction */ static scripting::ScriptEngine::LuaLibrary luaLibrary(); - -private: +private: friend class Controller; InteractionHandler(const InteractionHandler&) = delete; @@ -171,7 +121,8 @@ private: std::mutex _mutex; bool _validKeyLua; - std::multimap _keyLua; + + std::multimap _keyLua; float _controllerSensitivity; bool _invertRoll; diff --git a/include/openspace/util/keys.h b/include/openspace/util/keys.h index f57c143ead..9490b37732 100644 --- a/include/openspace/util/keys.h +++ b/include/openspace/util/keys.h @@ -62,144 +62,166 @@ namespace openspace { -enum class KeyAction { +enum class KeyAction : int { Release = 0, - Press = 1, - Repeat = 2 + Press = 1, + Repeat = 2 }; -enum class KeyModifier { - NoModifier = 0, - Shift = 0x0001, - Control = 0x0002, - Alt = 0x0004, - Super = 0x0008 +KeyAction operator|(KeyAction lhs, KeyAction rhs); +KeyAction operator|=(KeyAction& lhs, KeyAction rhs); + +enum class KeyModifier : int { + NoModifier = 0, + Shift = 0x0001, + Control = 0x0002, + Alt = 0x0004, + Super = 0x0008 }; +KeyModifier operator|(KeyModifier lhs, KeyModifier rhs); +KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs); + enum class Key { - Unknown = -1, - Space = 32, - Apostrophe = 39, - Comma = 44, - Minus = 45, - Period = 46, - Slash = 47, - Num0 = 48, - Num1 = 49, - Num2 = 50, - Num3 = 51, - Num4 = 52, - Num5 = 53, - Num6 = 54, - Num7 = 55, - Num8 = 56, - Num9 = 57, - SemiColon = 59, - Equal = 61, - A = 65, - B = 66, - C = 67, - D = 68, - E = 69, - F = 70, - G = 71, - H = 72, - I = 73, - J = 74, - K = 75, - L = 76, - M = 77, - N = 78, - O = 79, - P = 80, - Q = 81, - R = 82, - S = 83, - T = 84, - U = 85, - V = 86, - W = 87, - X = 88, - Y = 89, - Z = 90, - LeftBracket = 91, - BackSlash = 92, - RightBracket = 93, - GraveAccent = 96, - World1 = 161, - World2 = 162, - Escape = 256, - Enter = 257, - Tab = 258, - BackSpace = 259, - Insert = 260, - Delete = 261, - Right = 262, - Left = 263, - Down = 264, - Up = 265, - PageUp = 266, - PageDown = 267, - Home = 268, - End = 269, - CapsLock = 280, - ScrollLock = 281, - NumLock = 282, - PrintScreen = 283, - Pause = 284, - F1 = 290, - F2 = 291, - F3 = 292, - F4 = 293, - F5 = 294, - F6 = 295, - F7 = 296, - F8 = 297, - F9 = 298, - F10 = 299, - F11 = 300, - F12 = 301, - F13 = 302, - F14 = 303, - F15 = 304, - F16 = 305, - F17 = 306, - F18 = 307, - F19 = 308, - F20 = 309, - F21 = 310, - F22 = 311, - F23 = 312, - F24 = 313, - F25 = 314, - Keypad0 = 320, - Keypad1 = 321, - Keypad2 = 322, - Keypad3 = 323, - Keypad4 = 324, - Keypad5 = 325, - Keypad6 = 326, - Keypad7 = 327, - Keypad8 = 328, - Keypad9 = 329, - KeypadDecimal = 330, - KeypadDivide = 331, - KeypadMultiply = 332, - KeypadSubtract = 333, - KeypadAdd = 334, - KeypadEnter = 335, - LeftShift = 340, - LeftControl = 341, - LeftAlt = 342, - LeftSuper = 343, - RightShift = 344, - RightControl = 345, - RightAlt = 346, - RightSuper = 347, - Menu = 348, - Last = Menu + Unknown = -1, + Space = 32, + Apostrophe = 39, + Comma = 44, + Minus = 45, + Period = 46, + Slash = 47, + Num0 = 48, + Num1 = 49, + Num2 = 50, + Num3 = 51, + Num4 = 52, + Num5 = 53, + Num6 = 54, + Num7 = 55, + Num8 = 56, + Num9 = 57, + SemiColon = 59, + Equal = 61, + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + LeftBracket = 91, + BackSlash = 92, + RightBracket = 93, + GraveAccent = 96, + World1 = 161, + World2 = 162, + Escape = 256, + Enter = 257, + Tab = 258, + BackSpace = 259, + Insert = 260, + Delete = 261, + Right = 262, + Left = 263, + Down = 264, + Up = 265, + PageUp = 266, + PageDown = 267, + Home = 268, + End = 269, + CapsLock = 280, + ScrollLock = 281, + NumLock = 282, + PrintScreen = 283, + Pause = 284, + F1 = 290, + F2 = 291, + F3 = 292, + F4 = 293, + F5 = 294, + F6 = 295, + F7 = 296, + F8 = 297, + F9 = 298, + F10 = 299, + F11 = 300, + F12 = 301, + F13 = 302, + F14 = 303, + F15 = 304, + F16 = 305, + F17 = 306, + F18 = 307, + F19 = 308, + F20 = 309, + F21 = 310, + F22 = 311, + F23 = 312, + F24 = 313, + F25 = 314, + Keypad0 = 320, + Keypad1 = 321, + Keypad2 = 322, + Keypad3 = 323, + Keypad4 = 324, + Keypad5 = 325, + Keypad6 = 326, + Keypad7 = 327, + Keypad8 = 328, + Keypad9 = 329, + KeypadDecimal = 330, + KeypadDivide = 331, + KeypadMultiply = 332, + KeypadSubtract = 333, + KeypadAdd = 334, + KeypadEnter = 335, + LeftShift = 340, + LeftControl = 341, + LeftAlt = 342, + LeftSuper = 343, + RightShift = 344, + RightControl = 345, + RightAlt = 346, + RightSuper = 347, + Menu = 348, + Last = Menu }; +struct KeyWithModifier { + Key key; + KeyModifier modifier; +}; + +KeyWithModifier stringToKey(std::string str); +bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs); + + +static const std::map KeyModifierMapping = { + { "SHIFT", KeyModifier::Shift }, + { "ALT", KeyModifier::Alt }, + { "CTRL", KeyModifier::Control }, + { "SUPER", KeyModifier::Super } +}; + static const std::map KeyMapping = { { "SPACE", Key::Space }, { "APOSTROPHE", Key::Apostrophe }, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a941baf63..65e59b390a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -75,6 +75,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/util/boxgeometry.cpp ${OPENSPACE_BASE_DIR}/src/util/camera.cpp ${OPENSPACE_BASE_DIR}/src/util/factorymanager.cpp + ${OPENSPACE_BASE_DIR}/src/util/keys.cpp ${OPENSPACE_BASE_DIR}/src/util/openspacemodule.cpp ${OPENSPACE_BASE_DIR}/src/util/powerscaledcoordinate.cpp ${OPENSPACE_BASE_DIR}/src/util/powerscaledscalar.cpp diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 4e68967c79..3865b2eb99 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -36,79 +36,11 @@ namespace { const std::string _loggerCat = "InteractionHandler"; - - openspace::Key stringToKey(std::string s) { - // key only uppercase - std::transform(s.begin(), s.end(), s.begin(), ::toupper); - - // default is unknown - auto it = openspace::KeyMapping.find(s); - if (it != openspace::KeyMapping.end()) - return it->second; - else - return openspace::Key::Unknown; - } } #include "interactionhandler_lua.inl" namespace openspace { - -//InteractionHandler::InteractionHandler() { -// // initiate pointers -// _camera = nullptr; -// _enabled = true; -// _node = nullptr; -// _dt = 0.0; -// _lastTrackballPos = glm::vec3(0.0, 0.0, 0.5); -// _leftMouseButtonDown = false; -// _isMouseBeingPressedAndHeld = false; -//} -// -//InteractionHandler::~InteractionHandler() { -// for (size_t i = 0; i < _controllers.size(); ++i) { -// delete _controllers[i]; -// } -//} -// -////void InteractionHandler::init() { -//// assert( ! this_); -//// this_ = new InteractionHandler(); -////} -//// -////void InteractionHandler::deinit() { -//// assert(this_); -//// delete this_; -//// this_ = nullptr; -////} -//// -////InteractionHandler& InteractionHandler::ref() { -//// assert(this_); -//// return *this_; -////} -// -////bool InteractionHandler::isInitialized() { -//// return this_ != nullptr; -////} -// -//void InteractionHandler::enable() { -// //assert(this_); -// _enabled = true; -//} -// -//void InteractionHandler::disable() { -// //assert(this_); -// _enabled = false; -//} -// -//const bool InteractionHandler::isEnabled() const { -// //assert(this_); -// if (_camera) -// return false; -// return _enabled; -//======= - -//namespace openspace { namespace interaction { InteractionHandler::InteractionHandler() @@ -179,59 +111,6 @@ void InteractionHandler::unlockControls() { _mutex.unlock(); } -//<<<<<<< HEAD -//void InteractionHandler::addExternalControl(ExternalControl* controller) { -// //assert(this_); -// if (controller != nullptr) { -// _controllers.push_back(controller); -// } -//} -// -//void InteractionHandler::setCamera(Camera *camera) { -// //assert(this_); -// _camera = camera; -//} -// -//void InteractionHandler::setOrigin(SceneGraphNode* node) { -// if (node) -// _node = node; -//} -// -//Camera * InteractionHandler::getCamera() const { -// //assert(this_); -// if (_enabled) { -// return _camera; -// } -// return nullptr; -//} -// -//const psc InteractionHandler::getOrigin() const { -// if (_node) -// return _node->worldPosition(); -// return psc(); -//} -// -//void InteractionHandler::lockControls() { -// //assert(this_); -// _cameraGuard.lock(); -//} -// -//void InteractionHandler::unlockControls() { -// //assert(this_); -// _cameraGuard.unlock(); -//} -// -//void InteractionHandler::setFocusNode(SceneGraphNode *node) { -// //assert(this_); -// _node = node; -//} -// -//void InteractionHandler::rotate(const glm::quat &rotation) { -// //assert(this_); -// lockControls(); -// _camera->rotate(rotation); -// unlockControls(); -//======= void InteractionHandler::update(double deltaTime) { _deltaTime = deltaTime; _mouseController->update(deltaTime); @@ -564,7 +443,7 @@ void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyActi // iterate over key bindings _validKeyLua = true; - auto ret = _keyLua.equal_range(key); + auto ret = _keyLua.equal_range({ key, modifier }); for (auto it = ret.first; it != ret.second; ++it) { //OsEng.scriptEngine()->runScript(it->second); OsEng.scriptEngine().queueScript(it->second); @@ -574,51 +453,17 @@ void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyActi } } } -// -//void InteractionHandler::mouseButtonCallback(int key, int action) { -// //if(mouseControl_ != nullptr) { -// // mouseControl_->mouseButtonCallback(key,action); -// //} -// if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS) -// _leftMouseButtonDown = true; -// else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) { -// _leftMouseButtonDown = false; -// _isMouseBeingPressedAndHeld = false; -// } -//} -// -//void InteractionHandler::mousePositionCallback(int x, int y) { -// if (_leftMouseButtonDown) -// trackballRotate(x,y); -// -// //if(mouseControl_ != nullptr) { -// // mouseControl_->mousePosCallback(x,y); -// //} -//} -// -//void InteractionHandler::mouseScrollWheelCallback(int pos) { -// //if(mouseControl_ != nullptr) { -// // mouseControl_->mouseScrollCallback(pos); -// //} -// const float speed = 4.75f; -// const float dt = static_cast(_dt); -// if(pos < 0) { -// PowerScaledScalar dist(speed * dt, 0.0f); -// distance(dist); -// } else if(pos > 0) { -// PowerScaledScalar dist(-speed * dt, 0.0f); -// distance(dist); -// } -//} -// -// + void InteractionHandler::resetKeyBindings() { _keyLua.clear(); _validKeyLua = false; } -void InteractionHandler::bindKey(Key key, std::string lua) { - _keyLua.insert(std::make_pair(key, lua)); +void InteractionHandler::bindKey(Key key, KeyModifier modifier, std::string lua) { + _keyLua.insert({ + {key, modifier}, + lua + }); } scripting::ScriptEngine::LuaLibrary InteractionHandler::luaLibrary() { @@ -691,7 +536,6 @@ scripting::ScriptEngine::LuaLibrary InteractionHandler::luaLibrary() { }; } -//======= void InteractionHandler::setRotation(const glm::quat& rotation) { _camera->setRotation(rotation); diff --git a/src/interaction/interactionhandler_lua.inl b/src/interaction/interactionhandler_lua.inl index eeb7ca99c3..cf133964b2 100644 --- a/src/interaction/interactionhandler_lua.inl +++ b/src/interaction/interactionhandler_lua.inl @@ -76,16 +76,20 @@ int bindKey(lua_State* L) { if (command.empty()) return luaL_error(L, "Command string is empty"); - openspace::Key iKey = stringToKey(key); + openspace::KeyWithModifier iKey = openspace::stringToKey(key); - if (iKey == openspace::Key::Unknown) { + if (iKey.key == openspace::Key::Unknown) { LERROR("Could not find key '"<< key <<"'"); return 0; } - OsEng.interactionHandler().bindKey(iKey, command); - + OsEng.interactionHandler().bindKey( + iKey.key, + iKey.modifier, + command + ); + return 0; } diff --git a/src/util/keys.cpp b/src/util/keys.cpp new file mode 100644 index 0000000000..2384f503cb --- /dev/null +++ b/src/util/keys.cpp @@ -0,0 +1,99 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* Permission is hereby granted, free of charge, to any person obtaining a copy of this * +* software and associated documentation files (the "Software"), to deal in the Software * +* without restriction, including without limitation the rights to use, copy, modify, * +* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +* permit persons to whom the Software is furnished to do so, subject to the following * +* conditions: * +* * +* The above copyright notice and this permission notice shall be included in all copies * +* or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +****************************************************************************************/ + +#include + +#include +#include + +#include +#include + +namespace { + const std::string _loggerCat = "Keys"; +} + +namespace openspace { + +KeyAction operator|(KeyAction lhs, KeyAction rhs) { + return static_cast( + static_cast>(lhs) | + static_cast>(rhs) + ); +} + +KeyAction operator|=(KeyAction& lhs, KeyAction rhs) { + lhs = (lhs | rhs); + return lhs; +} + +KeyModifier operator|(KeyModifier lhs, KeyModifier rhs) { + return static_cast( + static_cast>(lhs) | + static_cast>(rhs) + ); +} + +KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs) { + lhs = (lhs | rhs); + return lhs; +} + +KeyWithModifier stringToKey(std::string str) { + // key only uppercase + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + + std::vector tokens = ghoul::tokenizeString(str, '+'); + + // default is unknown + Key k = Key::Unknown; + auto it = KeyMapping.find(tokens.back()); + if (it != KeyMapping.end()) + k = it->second; + + + KeyModifier m = KeyModifier::NoModifier; + std::for_each( + tokens.begin(), + tokens.end() - 1, + [&m](const std::string& s) { + auto it = KeyModifierMapping.find(s); + if (it != KeyModifierMapping.end()) + m |= it->second; + else + LERROR("Unknown modifier key '" << s << "'"); + } + ); + + return { k, m }; +} + +bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs) { + if (lhs.modifier == rhs.modifier) + return lhs.key < rhs.key; + else + return lhs.modifier < rhs.modifier; +} + +} // namespace openspace From 4ff0205eaefe73cda89b78ef79dc897fe6013895 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Mon, 11 Apr 2016 16:56:44 +0200 Subject: [PATCH 16/38] bring in support for multiresolution volume rendering --- data/scene/enlilnh/enlilnh.mod | 22 + data/scene/enlilnh/transferfunctions/fire.txt | 10 + ext/ghoul | 2 +- .../openspace/rendering/transferfunction.h | 70 ++ modules/multiresvolume/CMakeLists.txt | 68 ++ modules/multiresvolume/include.cmake | 4 + .../multiresvolume/multiresvolumemodule.cpp | 45 ++ modules/multiresvolume/multiresvolumemodule.h | 40 + .../multiresvolume/rendering/atlasmanager.cpp | 263 ++++++ .../multiresvolume/rendering/atlasmanager.h | 103 +++ modules/multiresvolume/rendering/brickcover.h | 68 ++ .../multiresvolume/rendering/brickmanager.cpp | 476 +++++++++++ .../multiresvolume/rendering/brickmanager.h | 111 +++ .../multiresvolume/rendering/brickselection.h | 108 +++ .../multiresvolume/rendering/brickselector.h | 42 + .../rendering/errorhistogrammanager.cpp | 361 +++++++++ .../rendering/errorhistogrammanager.h | 76 ++ .../multiresvolume/rendering/histogram.cpp | 221 +++++ modules/multiresvolume/rendering/histogram.h | 70 ++ .../rendering/histogrammanager.cpp | 192 +++++ .../rendering/histogrammanager.h | 54 ++ .../rendering/localerrorhistogrammanager.cpp | 490 ++++++++++++ .../rendering/localerrorhistogrammanager.h | 80 ++ .../rendering/localtfbrickselector.cpp | 348 ++++++++ .../rendering/localtfbrickselector.h | 78 ++ .../rendering/multiresvolumeraycaster.cpp | 158 ++++ .../rendering/multiresvolumeraycaster.h | 97 +++ .../rendering/renderablemultiresvolume.cpp | 638 +++++++++++++++ .../rendering/renderablemultiresvolume.h | 159 ++++ .../rendering/shenbrickselector.cpp | 134 ++++ .../rendering/shenbrickselector.h | 77 ++ .../rendering/simpletfbrickselector.cpp | 337 ++++++++ .../rendering/simpletfbrickselector.h | 71 ++ .../rendering/tfbrickselector.cpp | 395 +++++++++ .../rendering/tfbrickselector.h | 73 ++ modules/multiresvolume/rendering/tsp.cpp | 753 ++++++++++++++++++ modules/multiresvolume/rendering/tsp.h | 148 ++++ modules/multiresvolume/shaders/boundsFs.glsl | 40 + modules/multiresvolume/shaders/boundsVs.glsl | 47 ++ modules/multiresvolume/shaders/helper.glsl | 31 + modules/multiresvolume/shaders/raycast.glsl | 123 +++ .../rendering/renderabletoyvolume.cpp | 2 +- shaders/abuffer/abufferfragment.glsl | 104 ++- shaders/abuffer/boundsabuffer.frag | 3 +- shaders/abuffer/raycasterdata.glsl | 1 + shaders/abuffer/renderabuffer.frag | 2 + shaders/abuffer/resolveabuffer.frag | 25 +- shaders/blending.glsl | 48 +- shaders/fragment.glsl | 5 +- src/CMakeLists.txt | 2 + src/rendering/framebufferrenderer.cpp | 4 +- src/rendering/transferfunction.cpp | 227 ++++++ 52 files changed, 7057 insertions(+), 49 deletions(-) create mode 100644 data/scene/enlilnh/enlilnh.mod create mode 100644 data/scene/enlilnh/transferfunctions/fire.txt create mode 100644 include/openspace/rendering/transferfunction.h create mode 100644 modules/multiresvolume/CMakeLists.txt create mode 100644 modules/multiresvolume/include.cmake create mode 100644 modules/multiresvolume/multiresvolumemodule.cpp create mode 100644 modules/multiresvolume/multiresvolumemodule.h create mode 100644 modules/multiresvolume/rendering/atlasmanager.cpp create mode 100644 modules/multiresvolume/rendering/atlasmanager.h create mode 100644 modules/multiresvolume/rendering/brickcover.h create mode 100644 modules/multiresvolume/rendering/brickmanager.cpp create mode 100644 modules/multiresvolume/rendering/brickmanager.h create mode 100644 modules/multiresvolume/rendering/brickselection.h create mode 100644 modules/multiresvolume/rendering/brickselector.h create mode 100644 modules/multiresvolume/rendering/errorhistogrammanager.cpp create mode 100644 modules/multiresvolume/rendering/errorhistogrammanager.h create mode 100644 modules/multiresvolume/rendering/histogram.cpp create mode 100644 modules/multiresvolume/rendering/histogram.h create mode 100644 modules/multiresvolume/rendering/histogrammanager.cpp create mode 100644 modules/multiresvolume/rendering/histogrammanager.h create mode 100644 modules/multiresvolume/rendering/localerrorhistogrammanager.cpp create mode 100644 modules/multiresvolume/rendering/localerrorhistogrammanager.h create mode 100644 modules/multiresvolume/rendering/localtfbrickselector.cpp create mode 100644 modules/multiresvolume/rendering/localtfbrickselector.h create mode 100644 modules/multiresvolume/rendering/multiresvolumeraycaster.cpp create mode 100644 modules/multiresvolume/rendering/multiresvolumeraycaster.h create mode 100644 modules/multiresvolume/rendering/renderablemultiresvolume.cpp create mode 100644 modules/multiresvolume/rendering/renderablemultiresvolume.h create mode 100644 modules/multiresvolume/rendering/shenbrickselector.cpp create mode 100644 modules/multiresvolume/rendering/shenbrickselector.h create mode 100644 modules/multiresvolume/rendering/simpletfbrickselector.cpp create mode 100644 modules/multiresvolume/rendering/simpletfbrickselector.h create mode 100644 modules/multiresvolume/rendering/tfbrickselector.cpp create mode 100644 modules/multiresvolume/rendering/tfbrickselector.h create mode 100644 modules/multiresvolume/rendering/tsp.cpp create mode 100644 modules/multiresvolume/rendering/tsp.h create mode 100644 modules/multiresvolume/shaders/boundsFs.glsl create mode 100644 modules/multiresvolume/shaders/boundsVs.glsl create mode 100644 modules/multiresvolume/shaders/helper.glsl create mode 100644 modules/multiresvolume/shaders/raycast.glsl create mode 100644 src/rendering/transferfunction.cpp diff --git a/data/scene/enlilnh/enlilnh.mod b/data/scene/enlilnh/enlilnh.mod new file mode 100644 index 0000000000..cfd8de50de --- /dev/null +++ b/data/scene/enlilnh/enlilnh.mod @@ -0,0 +1,22 @@ +return { + -- Volume module + { + Name = "Enlil New Horizons", + Parent = "Root", + Ephemeris = { + Type = "Static", + Position = { 0.0, 0.0, 0.0, 0} + }, + Renderable = { + Type = "RenderableMultiresVolume", + Translation = {0, 0, 0}, + Rotation = {2.1, 0, 0}, + Scaling = {1.1, 1.1, 1.1}, + ScalingExponent = 12, + Source = "tsp/enlil_nh_128_128_16.tsp", + TransferFunction = "transferfunctions/fire.txt", + BrickSelector = "tf", + }, + GuiName = "/Volumes/ENLIL New Horizons" + } +} diff --git a/data/scene/enlilnh/transferfunctions/fire.txt b/data/scene/enlilnh/transferfunctions/fire.txt new file mode 100644 index 0000000000..0d2d364253 --- /dev/null +++ b/data/scene/enlilnh/transferfunctions/fire.txt @@ -0,0 +1,10 @@ +width 1024 +lower 0.0 +upper 1.0 + +mappingkey 0.05 254 0 0 0 +mappingkey 0.10 254 0 0 110 +mappingkey 0.12 254 220 0 254 +mappingkey 0.15 254 100 0 254 +mappingkey 0.20 180 0 0 254 +mappingkey 0.25 180 0 80 254 diff --git a/ext/ghoul b/ext/ghoul index 849cc67bdc..8a715dd042 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 849cc67bdc2550a43d8174490d39b14ee148b795 +Subproject commit 8a715dd04287864dff4290f6e607e49338f11f2e diff --git a/include/openspace/rendering/transferfunction.h b/include/openspace/rendering/transferfunction.h new file mode 100644 index 0000000000..a6a4d85c77 --- /dev/null +++ b/include/openspace/rendering/transferfunction.h @@ -0,0 +1,70 @@ +/***************************************************************************************** + * * + * 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 __TRANSFERFUNCTION_H__ +#define __TRANSFERFUNCTION_H__ + +#include +#include +#include +#include +#include +#include + +namespace openspace { + + class TransferFunction { + public: + typedef std::function TfChangedCallback; + + TransferFunction(const std::string& filepath, TfChangedCallback tfChangedCallback = TfChangedCallback()); + void setPath(const std::string& filepath); + ghoul::opengl::Texture& getTexture(); + void update(); + glm::vec4 sample(size_t t); + size_t width(); + void setCallback(TfChangedCallback callback); + private: + void setTextureFromTxt(); + void setTextureFromImage(); + void uploadTexture(); + + std::string _filepath; + std::unique_ptr _file = nullptr; + std::unique_ptr _texture = nullptr; + bool _needsUpdate = false; + TfChangedCallback _tfChangedCallback; + }; + + struct MappingKey { + float position{0.0f}; + glm::vec4 color{0.0f,0.0f,0.0f,0.0f}; + MappingKey(float p, const glm::vec4& c): position(p), color(c) {}; + MappingKey(float p): position(p), color(glm::vec4(0.0f)) {}; + bool operator<(const MappingKey& rhs) {return position < rhs.position;}; + }; +} // namespace openspace + +#endif + diff --git a/modules/multiresvolume/CMakeLists.txt b/modules/multiresvolume/CMakeLists.txt new file mode 100644 index 0000000000..a5afd80256 --- /dev/null +++ b/modules/multiresvolume/CMakeLists.txt @@ -0,0 +1,68 @@ +######################################################################################### +# # +# 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(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/atlasmanager.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/brickmanager.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/brickselector.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/brickcover.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/brickselection.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multiresvolumeraycaster.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/shenbrickselector.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/tfbrickselector.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/localtfbrickselector.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/simpletfbrickselector.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemultiresvolume.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/tsp.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/histogram.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/histogrammanager.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/errorhistogrammanager.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/localerrorhistogrammanager.h +) +source_group("Header Files" FILES ${HEADER_FILES}) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/atlasmanager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/brickmanager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multiresvolumeraycaster.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/shenbrickselector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/tfbrickselector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/localtfbrickselector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/simpletfbrickselector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemultiresvolume.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/tsp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/histogram.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/histogrammanager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/errorhistogrammanager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/localerrorhistogrammanager.cpp +) +source_group("Source Files" FILES ${SOURCE_FILES}) + +create_new_module( + "MultiresVolume" + multiresvolume_module + ${HEADER_FILES} ${SOURCE_FILES} +) diff --git a/modules/multiresvolume/include.cmake b/modules/multiresvolume/include.cmake new file mode 100644 index 0000000000..163c5a64bf --- /dev/null +++ b/modules/multiresvolume/include.cmake @@ -0,0 +1,4 @@ +set (DEFAULT_MODULE ON) +set (OPENSPACE_DEPENDENCIES + volume +) \ No newline at end of file diff --git a/modules/multiresvolume/multiresvolumemodule.cpp b/modules/multiresvolume/multiresvolumemodule.cpp new file mode 100644 index 0000000000..7d9baab170 --- /dev/null +++ b/modules/multiresvolume/multiresvolumemodule.cpp @@ -0,0 +1,45 @@ +/***************************************************************************************** + * * + * 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 + +#include +#include + +#include + +#include + +namespace openspace { + +MultiresVolumeModule::MultiresVolumeModule() : OpenSpaceModule("MultiresVolume") {} + +void MultiresVolumeModule::internalInitialize() { + auto fRenderable = FactoryManager::ref().factory(); + ghoul_assert(fRenderable, "No renderable factory existed"); + + fRenderable->registerClass("RenderableMultiresVolume"); +} + +} // namespace openspace diff --git a/modules/multiresvolume/multiresvolumemodule.h b/modules/multiresvolume/multiresvolumemodule.h new file mode 100644 index 0000000000..48d14100ec --- /dev/null +++ b/modules/multiresvolume/multiresvolumemodule.h @@ -0,0 +1,40 @@ +/***************************************************************************************** + * * + * 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 __MULTIRESVOLUMEMODULE_H__ +#define __MULTIRESVOLUMEMODULE_H__ + +#include + +namespace openspace { + +class MultiresVolumeModule : public OpenSpaceModule { +public: + MultiresVolumeModule(); + void internalInitialize() override; +}; + +} // namespace openspace + +#endif // __MULTIRESVOLUMEMODULE_H__ diff --git a/modules/multiresvolume/rendering/atlasmanager.cpp b/modules/multiresvolume/rendering/atlasmanager.cpp new file mode 100644 index 0000000000..65bfbaa4e3 --- /dev/null +++ b/modules/multiresvolume/rendering/atlasmanager.cpp @@ -0,0 +1,263 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 + +#include +#include +#include + +#include +#include +#include +#include + +namespace { + const std::string _loggerCat = "AtlasManager"; +} + +namespace openspace { + +AtlasManager::AtlasManager(TSP* tsp) : _tsp(tsp) {} + +AtlasManager::~AtlasManager() {} + +bool AtlasManager::initialize() { + TSP::Header header = _tsp->header(); + + _nBricksPerDim = header.xNumBricks_; + _nOtLeaves = _nBricksPerDim * _nBricksPerDim * _nBricksPerDim; + _nOtNodes = _tsp->numOTNodes(); + _nOtLevels = log(_nOtLeaves)/log(8) + 1; + _paddedBrickDim = _tsp->paddedBrickDim(); + _nBricksInMap = _nBricksPerDim * _nBricksPerDim * _nBricksPerDim; + _atlasDim = _nBricksPerDim * _paddedBrickDim; + _nBrickVals = _paddedBrickDim*_paddedBrickDim*_paddedBrickDim; + _brickSize = _nBrickVals * sizeof(float); + _volumeSize = _brickSize * _nOtLeaves; + _atlasMap = std::vector(_nOtLeaves, NOT_USED); + _nBricksInAtlas = _nBricksInMap; + + _freeAtlasCoords = std::vector(_nBricksInAtlas, 0); + + for (unsigned int i = 0; i < _nBricksInAtlas; i++) { + _freeAtlasCoords[i] = i; + } + + _textureAtlas = new ghoul::opengl::Texture( + glm::size3_t(_atlasDim, _atlasDim, _atlasDim), + ghoul::opengl::Texture::Format::RGBA, + GL_RGBA, + GL_FLOAT); + _textureAtlas->uploadTexture(); + + glGenBuffers(2, _pboHandle); + + glGenBuffers(1, &_atlasMapBuffer); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, _atlasMapBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLint)*_nBricksInMap, NULL, GL_DYNAMIC_READ); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + + return true; +} + +std::vector AtlasManager::atlasMap() { + return _atlasMap; +} + +unsigned int AtlasManager::atlasMapBuffer() { + return _atlasMapBuffer; +} + +void AtlasManager::updateAtlas(BUFFER_INDEX bufferIndex, std::vector& brickIndices) { + int nBrickIndices = brickIndices.size(); + + _requiredBricks.clear(); + for (int i = 0; i < nBrickIndices; i++) { + _requiredBricks.insert(brickIndices[i]); + } + + for (unsigned int it : _prevRequiredBricks) { + if (!_requiredBricks.count(it)) { + removeFromAtlas(it); + } + } + + // Stats + _nUsedBricks = _requiredBricks.size(); + _nStreamedBricks = 0; + _nDiskReads = 0; + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboHandle[bufferIndex]); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _volumeSize, 0, GL_STREAM_DRAW); + float* mappedBuffer = reinterpret_cast(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY)); + + if (!mappedBuffer) { + LERROR("Failed to map PBO"); + std::cout << glGetError() << std::endl; + return; + } + + for (auto itStart = _requiredBricks.begin(); itStart != _requiredBricks.end();) { + int firstBrick = *itStart; + int lastBrick = firstBrick; + + auto itEnd = itStart; + for (itEnd++; itEnd != _requiredBricks.end() && *itEnd == lastBrick + 1; itEnd++) { + lastBrick = *itEnd; + } + + addToAtlas(firstBrick, lastBrick, mappedBuffer); + + itStart = itEnd; + } + + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + for (int i = 0; i < nBrickIndices; i++) { + _atlasMap[i] = _brickMap[brickIndices[i]]; + } + + std::swap(_prevRequiredBricks, _requiredBricks); + + pboToAtlas(bufferIndex); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, _atlasMapBuffer); + GLint *to = (GLint*)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY); + memcpy(to, _atlasMap.data(), sizeof(GLint)*_atlasMap.size()); + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + +} + +void AtlasManager::addToAtlas(int firstBrickIndex, int lastBrickIndex, float* mappedBuffer) { + while (_brickMap.count(firstBrickIndex) && firstBrickIndex <= lastBrickIndex) firstBrickIndex++; + while (_brickMap.count(lastBrickIndex) && lastBrickIndex >= firstBrickIndex) lastBrickIndex--; + if (lastBrickIndex < firstBrickIndex) return; + + int sequenceLength = lastBrickIndex - firstBrickIndex + 1; + float* sequenceBuffer = new float[sequenceLength*_nBrickVals]; + size_t bufferSize = sequenceLength * _brickSize; + + long long offset = TSP::dataPosition() + static_cast(firstBrickIndex) * static_cast(_brickSize); + _tsp->file().seekg(offset); + _tsp->file().read(reinterpret_cast(sequenceBuffer), bufferSize); + _nDiskReads++; + + for (int brickIndex = firstBrickIndex; brickIndex <= lastBrickIndex; brickIndex++) { + if (!_brickMap.count(brickIndex)) { + unsigned int atlasCoords = _freeAtlasCoords.back(); + _freeAtlasCoords.pop_back(); + int level = _nOtLevels - floor(log((7.0 * (float(brickIndex % _nOtNodes)) + 1.0))/log(8)) - 1; + assert(atlasCoords <= 0x0FFFFFFF); + unsigned int atlasData = (level << 28) + atlasCoords; + _brickMap.insert(std::pair(brickIndex, atlasData)); + _nStreamedBricks++; + fillVolume(&sequenceBuffer[_nBrickVals*(brickIndex - firstBrickIndex)], mappedBuffer, atlasCoords); + } + } + + delete[] sequenceBuffer; +} + +void AtlasManager::removeFromAtlas(int brickIndex) { + unsigned int atlasData = _brickMap[brickIndex]; + unsigned int atlasCoords = atlasData & 0x0FFFFFFF; + _brickMap.erase(brickIndex); + _freeAtlasCoords.push_back(atlasCoords); +} + +void AtlasManager::fillVolume(float* in, float* out, unsigned int linearAtlasCoords) { + int x = linearAtlasCoords % _nBricksPerDim; + int y = (linearAtlasCoords / _nBricksPerDim) % _nBricksPerDim; + int z = linearAtlasCoords / _nBricksPerDim / _nBricksPerDim; + + + unsigned int xMin = x*_paddedBrickDim; + unsigned int yMin = y*_paddedBrickDim; + unsigned int zMin = z*_paddedBrickDim; + unsigned int xMax = xMin + _paddedBrickDim; + unsigned int yMax = yMin + _paddedBrickDim; + unsigned int zMax = zMin + _paddedBrickDim; + + unsigned int from = 0; + for (unsigned int zValCoord = zMin; zValCoorddimensions(); + glBindTexture(GL_TEXTURE_3D, *_textureAtlas); + glTexSubImage3D(GL_TEXTURE_3D, // target + 0, // level + 0, // xoffset + 0, // yoffset + 0, // zoffset + dim[0], // width + dim[1], // height + dim[2], // depth + GL_RED, // format + GL_FLOAT, // type + NULL); // *pixels + glBindTexture(GL_TEXTURE_3D, 0); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); +} + +ghoul::opengl::Texture& AtlasManager::textureAtlas() { + ghoul_assert(_textureAtlas != nullptr, "Texture atlas is nullptr"); + return *_textureAtlas; +} + +unsigned int AtlasManager::getNumDiskReads() { + return _nDiskReads; +} + +unsigned int AtlasManager::getNumUsedBricks() { + return _nUsedBricks; +} + +unsigned int AtlasManager::getNumStreamedBricks() { + return _nStreamedBricks; +} + + +glm::size3_t AtlasManager::textureSize() { + return _textureAtlas->dimensions(); +} + +} diff --git a/modules/multiresvolume/rendering/atlasmanager.h b/modules/multiresvolume/rendering/atlasmanager.h new file mode 100644 index 0000000000..b042c57827 --- /dev/null +++ b/modules/multiresvolume/rendering/atlasmanager.h @@ -0,0 +1,103 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __ATLASMANAGER_H__ +#define __ATLASMANAGER_H__ + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace ghoul { + namespace opengl { + class Texture; + } +} + +namespace openspace { + +class AtlasManager { +public: + enum BUFFER_INDEX { EVEN = 0, ODD = 1 }; + + AtlasManager(TSP* tsp); + ~AtlasManager(); + + void updateAtlas(BUFFER_INDEX bufferIndex, std::vector& brickIndices); + void addToAtlas(int firstBrickIndex, int lastBrickIndex, float* mappedBuffer); + void removeFromAtlas(int brickIndex); + bool initialize(); + std::vector atlasMap(); + unsigned int atlasMapBuffer(); + + void pboToAtlas(BUFFER_INDEX bufferIndex); + ghoul::opengl::Texture& textureAtlas(); + glm::size3_t textureSize(); + + unsigned int getNumDiskReads(); + unsigned int getNumUsedBricks(); + unsigned int getNumStreamedBricks(); +private: + const unsigned int NOT_USED = UINT_MAX; + TSP* _tsp; + unsigned int _pboHandle[2]; + unsigned int _atlasMapBuffer; + + std::vector _atlasMap; + std::map _brickMap; + std::vector _freeAtlasCoords; + std::set _requiredBricks; + std::set _prevRequiredBricks; + + ghoul::opengl::Texture* _textureAtlas; + + // Stats + unsigned int _nUsedBricks; + unsigned int _nStreamedBricks; + unsigned int _nDiskReads; + + unsigned int _nBricksPerDim, + _nOtLeaves, + _nOtNodes, + _nOtLevels, + _brickSize, + _nBrickVals, + _volumeSize, + _paddedBrickDim, + _nBricksInAtlas, + _nBricksInMap, + _atlasDim; + + void fillVolume(float* in, float* out, unsigned int linearAtlasCoords); +}; + +} // namespace openspace + +#endif diff --git a/modules/multiresvolume/rendering/brickcover.h b/modules/multiresvolume/rendering/brickcover.h new file mode 100644 index 0000000000..150f8a2cba --- /dev/null +++ b/modules/multiresvolume/rendering/brickcover.h @@ -0,0 +1,68 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __BRICKCOVER_H__ +#define __BRICKCOVER_H__ + +namespace openspace { + +struct BrickCover { + int lowX, highX, lowY, highY, lowZ, highZ; + + BrickCover() {} + + BrickCover(int numBricks) { + lowX = lowY = lowZ = 0; + highX = highY = highZ = numBricks; + } + + BrickCover split(bool x, bool y, bool z) { + BrickCover child; + if (x) { + child.lowX = lowX + (highX - lowX) / 2; + child.highX = highX; + } else { + child.lowX = lowX; + child.highX = lowX + (highX - lowX) / 2; + } + if (y) { + child.lowY = lowY + (highY - lowY) / 2; + child.highY = highY; + } else { + child.lowY = lowY; + child.highY = lowY + (highY - lowY) / 2; + } + if (z) { + child.lowZ = lowZ + (highZ - lowZ) / 2; + child.highZ = highZ; + } else { + child.lowZ = lowZ; + child.highZ = lowZ + (highZ - lowZ) / 2; + } + return child; + } +}; +} + +#endif // __BRICKCOVER_H__ diff --git a/modules/multiresvolume/rendering/brickmanager.cpp b/modules/multiresvolume/rendering/brickmanager.cpp new file mode 100644 index 0000000000..39f612eeb5 --- /dev/null +++ b/modules/multiresvolume/rendering/brickmanager.cpp @@ -0,0 +1,476 @@ +/***************************************************************************************** + * * + * 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 + +namespace { + const std::string _loggerCat = "BrickManager"; +} + +namespace openspace { + +BrickManager::BrickManager(TSP* tsp) + : _tsp(tsp) + , numBricks_(0) + , brickDim_(0) + , paddedBrickDim_(0) + , atlasDim_(0) + , numBrickVals_(0) + , numBricksFrame_(0) + , numBricksTree_(0) + , brickSize_(0) + , volumeSize_(0) + , numValsTot_(0) + , xCoord_(0) + , yCoord_(0) + , zCoord_(0) + , textureAtlas_(nullptr) + , hasReadHeader_(false) + , atlasInitialized_(false) +{} + +BrickManager::~BrickManager() { + +} + +bool BrickManager::readHeader() { + + if (!_tsp->file().is_open()) + return false; + + _header = _tsp->header(); + + LDEBUG("Grid type: " << _header.gridType_); + LDEBUG("Original num timesteps: " << _header.numOrigTimesteps_); + LDEBUG("Num timesteps: " << _header.numTimesteps_); + LDEBUG("Brick dims: " << _header.xBrickDim_ << " " << _header.yBrickDim_ << " " << _header.zBrickDim_); + LDEBUG("Num bricks: " << _header.xNumBricks_ << " " << _header.yNumBricks_ << " " << _header.zNumBricks_); + LDEBUG(""); + + brickDim_ = _header.xBrickDim_; + numBricks_ = _header.xNumBricks_; + paddedBrickDim_ = brickDim_ + paddingWidth_ * 2; + atlasDim_ = paddedBrickDim_*numBricks_; + + LDEBUG("Padded brick dim: " << paddedBrickDim_); + LDEBUG("Atlas dim: " << atlasDim_); + + numBrickVals_ = paddedBrickDim_*paddedBrickDim_*paddedBrickDim_; + // Number of bricks per frame + numBricksFrame_ = numBricks_*numBricks_*numBricks_; + + // Calculate number of bricks in tree + unsigned int numOTLevels = static_cast(log((int)numBricks_) / log(2) + 1); + unsigned int numOTNodes = static_cast((pow(8, numOTLevels) - 1) / 7); + unsigned int numBSTNodes = static_cast(_header.numTimesteps_ * 2 - 1); + numBricksTree_ = numOTNodes * numBSTNodes; + LDEBUG("Num OT levels: " << numOTLevels); + LDEBUG("Num OT nodes: " << numOTNodes); + LDEBUG("Num BST nodes: " << numBSTNodes); + LDEBUG("Num bricks in tree: " << numBricksTree_); + LDEBUG("Num values per brick: " << numBrickVals_); + + brickSize_ = sizeof(float)*numBrickVals_; + volumeSize_ = brickSize_*numBricksFrame_; + numValsTot_ = numBrickVals_*numBricksFrame_; + + _tsp->file().seekg(0, _tsp->file().end); + long long fileSize = _tsp->file().tellg(); + long long calcFileSize = static_cast(numBricksTree_)* + static_cast(brickSize_) + TSP::dataPosition(); + + + if (fileSize != calcFileSize) { + LERROR("Sizes don't match"); + LERROR("calculated file size: " << calcFileSize); + LERROR("file size: " << fileSize); + return false; + } + + hasReadHeader_ = true; + + // Hold two brick lists + brickLists_.resize(2); + // Make sure the brick list can hold the maximum number of bricks + // Each entry holds tree coordinates + brickLists_[EVEN].resize(numBricksTree_ * 3, -1); + brickLists_[ODD].resize(numBricksTree_ * 3, -1); + + // Allocate space for keeping tracks of bricks in PBO + bricksInPBO_.resize(2); + bricksInPBO_[EVEN].resize(numBricksTree_, -1); + bricksInPBO_[ODD].resize(numBricksTree_, -1); + + // Allocate space for keeping track of the used coordinates in atlas + usedCoords_.resize(2); + usedCoords_[EVEN].resize(numBricksFrame_, false); + usedCoords_[ODD].resize(numBricksFrame_, false); + + return true; +} + +bool BrickManager::initialize() { + if (atlasInitialized_) { + LWARNING("InitAtlas() - already initialized"); + } + + if (!hasReadHeader_) { + LWARNING("InitAtlas() - Has not read header, trying to read"); + return readHeader(); + } + + // Prepare the 3D texture + std::vector dims; + dims.push_back(atlasDim_); + dims.push_back(atlasDim_); + dims.push_back(atlasDim_); + textureAtlas_ = new ghoul::opengl::Texture( + glm::size3_t(atlasDim_, atlasDim_, atlasDim_), + ghoul::opengl::Texture::Format::RGBA, + GL_RGBA, + GL_FLOAT); + textureAtlas_->uploadTexture(); + //textureAtlas_ = Texture3D::New(dims); + + //if (!textureAtlas_->Init()) return false; + + atlasInitialized_ = true; + + + glGenBuffers(2, pboHandle_); + + return true; +} + +bool BrickManager::BuildBrickList(BUFFER_INDEX _bufIdx, + std::vector &_brickRequest) { + + // Keep track of number bricks used and number of bricks cached + // (for benchmarking) + int numBricks = 0; + int numCached = 0; + + // For every non-zero entry in the request list, assign a texture atlas + // coordinate. For zero entries, signal "no brick" using -1. + + for (unsigned int i = 0; i<_brickRequest.size(); ++i) { + + if (_brickRequest[i] > 0) { + + numBricks++; + + //INFO("Checking brick " << i); + + // If the brick is already in the atlas, keep the coordinate + if (bricksInPBO_[_bufIdx][i] != -1) { + + numCached++; + + // Get the corresponding coordinates from index + int x, y, z; + CoordsFromLin(bricksInPBO_[_bufIdx][i], x, y, z); + brickLists_[_bufIdx][3 * i + 0] = x; + brickLists_[_bufIdx][3 * i + 1] = y; + brickLists_[_bufIdx][3 * i + 2] = z; + + // Mark coordinate as used + usedCoords_[_bufIdx][bricksInPBO_[_bufIdx][i]] = true; + + } + else { + + // If coord is already usedi by another brick, + // skip it and try the next one + while (usedCoords_[_bufIdx][LinearCoord(xCoord_, yCoord_, zCoord_)]) { + IncCoord(); + } + + brickLists_[_bufIdx][3 * i + 0] = xCoord_; + brickLists_[_bufIdx][3 * i + 1] = yCoord_; + brickLists_[_bufIdx][3 * i + 2] = zCoord_; + usedCoords_[_bufIdx][LinearCoord(xCoord_, yCoord_, zCoord_)] = true; + + IncCoord(); + } + + + } + else { + + // -1 is for "not used" + brickLists_[_bufIdx][3 * i + 0] = -1; + brickLists_[_bufIdx][3 * i + 1] = -1; + brickLists_[_bufIdx][3 * i + 2] = -1; + + } + + // Reset brick list during iteration + _brickRequest[i] = 0; + + } + + + // Brick list is build, reset coordinate list + for (auto it = usedCoords_[_bufIdx].begin(); + it != usedCoords_[_bufIdx].end(); ++it) { + *it = false; + } + + //INFO("bricks NOT used: " << (float)(numBricksFrame_-numBricks) / (float)(numBricksFrame_)); + //INFO("bricks cached: " << (float)numCached / (float)(numBricksFrame_)); + + return true; +} + +bool BrickManager::FillVolume(float *_in, float *_out, + unsigned int _x, + unsigned int _y, + unsigned int _z) { + + //timer_.start(); + unsigned int xMin = _x*paddedBrickDim_; + unsigned int yMin = _y*paddedBrickDim_; + unsigned int zMin = _z*paddedBrickDim_; + unsigned int xMax = xMin + paddedBrickDim_; + unsigned int yMax = yMin + paddedBrickDim_; + unsigned int zMax = zMin + paddedBrickDim_; + + // Loop over the brick using three loops + unsigned int from = 0; + for (unsigned int zValCoord = zMin; zValCoord( + glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY)); + + if (!mappedBuffer) { + LERROR("Failed to map PBO"); + return false; + } + + // Loop over brick request list + unsigned int brickIndex = 0; + while (brickIndex < brickLists_[_pboIndex].size() / 3) { + + // Find first active brick index in list + while (brickIndex(brickIndex) * + static_cast(brickSize_); + */ + + long offset = TSP::dataPosition() + + static_cast(brickIndex)* + static_cast(brickSize_); + + // Skip reading if all bricks in sequence is already in PBO + if (inPBO != sequence) { + + //timer_.start(); + + /* + std::streamoff off = static_cast(offset); + in_.seekg(off); + if (in_.tellg() == -1) { + ERROR("Failed to get input stream position"); + INFO("offset: " << offset); + INFO("streamoff max: " << std::numeric_limits::max()); + INFO("size_t max: " << std::numeric_limits::max()); + return false; + } + INFO("in.tellg(): " << in_.tellg()); + in_.read(reinterpret_cast(seqBuffer), brickSize_*sequence); + */ + + _tsp->file().seekg(offset); + _tsp->file().read(reinterpret_cast(seqBuffer), bufSize); + + + //timer_.stop(); + //double time = timer_.elapsed().wall / 1.0e9; + //double mb = (brickSize_*sequence) / 1048576.0; + //INFO("Disk read "<( + brickLists_[_pboIndex][3 * (brickIndex + i) + 0]); + unsigned int y = static_cast( + brickLists_[_pboIndex][3 * (brickIndex + i) + 1]); + unsigned int z = static_cast( + brickLists_[_pboIndex][3 * (brickIndex + i) + 2]); + + // Put each brick in the correct buffer place. + // This needs to be done because the values are in brick order, and + // the volume needs to be filled with one big float array. + FillVolume(&seqBuffer[numBrickVals_*i], mappedBuffer, x, y, z); + // Update the atlas list since the brick will be uploaded + //INFO(brickIndex+i); + bricksInPBO_[_pboIndex][brickIndex + i] = LinearCoord(x, y, z); + + } + } + + delete[] seqBuffer; + + } // if in pbo + + // Update the brick index + brickIndex += sequence; + + } + + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + return true; +} + +bool BrickManager::PBOToAtlas(BUFFER_INDEX _pboIndex) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboHandle_[_pboIndex]); + glm::size3_t dim = textureAtlas_->dimensions(); + glBindTexture(GL_TEXTURE_3D, *textureAtlas_); + glTexSubImage3D(GL_TEXTURE_3D, // target + 0, // level + 0, // xoffset + 0, // yoffset + 0, // zoffset + dim[0], // width + dim[1], // height + dim[2], // depth + GL_RED, // format + GL_FLOAT, // type + NULL); // *pixels + glBindTexture(GL_TEXTURE_3D, 0); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + return true; +} + +ghoul::opengl::Texture* BrickManager::textureAtlas() { + return textureAtlas_; +} + +unsigned int BrickManager::pbo(BUFFER_INDEX _pboIndex) { + return pboHandle_[_pboIndex]; +} + +const std::vector& BrickManager::brickList(BUFFER_INDEX index) const { + return brickLists_.at(index); +} + +} diff --git a/modules/multiresvolume/rendering/brickmanager.h b/modules/multiresvolume/rendering/brickmanager.h new file mode 100644 index 0000000000..171d0983b7 --- /dev/null +++ b/modules/multiresvolume/rendering/brickmanager.h @@ -0,0 +1,111 @@ +/***************************************************************************************** + * * + * 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 __BRICKMANAGER_H__ +#define __BRICKMANAGER_H__ + +#include + +#include +#include + +namespace ghoul { + namespace opengl { + class Texture; + } +} + +namespace openspace { + +class BrickManager { +public: + enum BUFFER_INDEX { EVEN = 0, ODD = 1 }; + + BrickManager(TSP* tsp); + ~BrickManager(); + + bool readHeader(); + + bool initialize(); + + bool BuildBrickList(BUFFER_INDEX _bufIdx, std::vector &_brickRequest); + + bool FillVolume(float *_in, float *_out, + unsigned int _x, + unsigned int _y, + unsigned int _z); + bool DiskToPBO(BUFFER_INDEX _pboIndex); + bool PBOToAtlas(BUFFER_INDEX _pboIndex); + + ghoul::opengl::Texture* textureAtlas(); + unsigned int pbo(BUFFER_INDEX _pboIndex); + const std::vector& brickList(BUFFER_INDEX index) const; + +private: + + void IncCoord(); + unsigned int LinearCoord(int _x, int _y, int _z); + void CoordsFromLin(int _idx, int &_x, int &_y, int &_z); + + TSP* _tsp; + TSP::Header _header; + + unsigned int numBricks_; + unsigned int brickDim_; + unsigned int paddedBrickDim_; + unsigned int atlasDim_; + + const unsigned int paddingWidth_ = 1; + + unsigned int numBrickVals_; + unsigned int numBricksFrame_; + unsigned int numBricksTree_; + unsigned int brickSize_; + unsigned int volumeSize_; + unsigned int numValsTot_; + + // Texture coordinates to be assigned + int xCoord_; + int yCoord_; + int zCoord_; + + // Texture where the actual atlas is kept + ghoul::opengl::Texture* textureAtlas_; + + std::vector > brickLists_; + + bool hasReadHeader_; + bool atlasInitialized_; + + // PBOs + unsigned int pboHandle_[2]; + + // Caching, one for each PBO + std::vector > bricksInPBO_; + std::vector > usedCoords_; +}; + +} // namespace openspace + +#endif \ No newline at end of file diff --git a/modules/multiresvolume/rendering/brickselection.h b/modules/multiresvolume/rendering/brickselection.h new file mode 100644 index 0000000000..c329523994 --- /dev/null +++ b/modules/multiresvolume/rendering/brickselection.h @@ -0,0 +1,108 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __BRICKSELECTION_H__ +#define __BRICKSELECTION_H__ + +#include + + +namespace openspace { + +struct BrickSelection { + enum SplitType { + None = 0, + Temporal = 1, + Spatial = 2 + }; + + unsigned int brickIndex; + float splitPoints; + BrickSelection::SplitType splitType; + BrickCover cover; + int lowT; + int highT; + int nSpatialSplits; + int nTemporalSplits; + + BrickSelection() {} + + BrickSelection(int numBricks, int numTimeSteps, SplitType splitType, float splitPoints) { + this->cover = BrickCover(numBricks); + this->lowT = 0; + this->highT = numTimeSteps; + this->brickIndex = 0; + this->splitType = splitType; + this->splitPoints = splitPoints; + this->nSpatialSplits = 0; + this->nTemporalSplits = 0; + } + + BrickSelection splitSpatially(bool x, bool y, bool z, unsigned int childBrickIndex, SplitType childSplitType, float childSplitPoints) { + BrickSelection child; + child.cover = cover.split(x, y, z); + child.brickIndex = childBrickIndex; + child.splitPoints = childSplitPoints; + child.splitType = childSplitType; + child.nSpatialSplits = nSpatialSplits + 1; + child.nTemporalSplits = nTemporalSplits; + child.lowT = lowT; + child.highT = highT; + return child; + } + + BrickSelection splitTemporally(bool t, unsigned int childBrickIndex, SplitType childSplitType, float childSplitPoints) { + BrickSelection child; + child.cover = cover; + child.brickIndex = childBrickIndex; + child.splitPoints = childSplitPoints; + child.splitType = childSplitType; + if (t) { + child.lowT = centerT(); + child.highT = highT; + } else { + child.lowT = lowT; + child.highT = centerT(); + } + child.nSpatialSplits = nSpatialSplits; + child.nTemporalSplits = nTemporalSplits + 1; + + return child; + } + + int centerT() { + return lowT + (highT - lowT) / 2; + } + + bool timestepInRightChild(int timestep) { + return timestep >= centerT(); + } + + static bool compareSplitPoints(const BrickSelection& a, const BrickSelection& b) { + return a.splitPoints < b.splitPoints; + } +}; +} + +#endif // __BRICKSELECTION_H__ diff --git a/modules/multiresvolume/rendering/brickselector.h b/modules/multiresvolume/rendering/brickselector.h new file mode 100644 index 0000000000..1cb8bd33a6 --- /dev/null +++ b/modules/multiresvolume/rendering/brickselector.h @@ -0,0 +1,42 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __BRICKSELECTOR_H__ +#define __BRICKSELECTOR_H__ + +#include + +namespace openspace { + +class BrickSelector { +public: + virtual ~BrickSelector() {}; + virtual bool initialize() { return true; }; + virtual void selectBricks(int timestep, + std::vector& bricks) = 0; +}; + +} // namespace openspace + +#endif // __BRICKSELECTOR_H__ diff --git a/modules/multiresvolume/rendering/errorhistogrammanager.cpp b/modules/multiresvolume/rendering/errorhistogrammanager.cpp new file mode 100644 index 0000000000..10cb91d111 --- /dev/null +++ b/modules/multiresvolume/rendering/errorhistogrammanager.cpp @@ -0,0 +1,361 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 +#include +#include +#include + +#include +#include + +#include + +#include + +namespace { + const std::string _loggerCat = "ErrorHistogramManager"; +} + +namespace openspace { + +ErrorHistogramManager::ErrorHistogramManager(TSP* tsp) : _tsp(tsp) {} + +ErrorHistogramManager::~ErrorHistogramManager() {} + +bool ErrorHistogramManager::buildHistograms(int numBins) { + _numBins = numBins; + + _file = &(_tsp->file()); + if (!_file->is_open()) { + return false; + } + _minBin = 0.0; // Should be calculated from tsp file + _maxBin = 1.0; // Should be calculated from tsp file as (maxValue - minValue) + + unsigned int numOtLevels = _tsp->numOTLevels(); + unsigned int numOtLeaves = pow(8, numOtLevels - 1); + unsigned int numBstLeaves = pow(2, _tsp->numBSTLevels() - 1); + + _numInnerNodes = _tsp->numTotalNodes() - numOtLeaves * numBstLeaves; + _histograms = std::vector(_numInnerNodes); + LINFO("Build " << _numInnerNodes << " histograms with " << numBins << " bins each"); + + // All TSP Leaves + int numOtNodes = _tsp->numOTNodes(); + int otOffset = (pow(8, numOtLevels - 1) - 1) / 7; + + int numBstNodes = _tsp->numBSTNodes(); + int bstOffset = numBstNodes / 2; + + int numberOfLeaves = (numBstNodes - bstOffset) * (numOtNodes - otOffset); + ProgressBar pb(numberOfLeaves); + int processedLeaves = 0; + bool success = true; + for (int bst = bstOffset; bst < numBstNodes; bst++) { + for (int ot = otOffset; ot < numOtNodes; ot++) { + success &= buildFromLeaf(bst, ot); + if (!success) return false; + pb.print(++processedLeaves); + } + } + + return success; +} + +bool ErrorHistogramManager::buildFromLeaf(unsigned int bstOffset, unsigned int octreeOffset) { + // Traverse all ancestors of leaf and add errors to their histograms + + unsigned int brickDim = _tsp->brickDim(); + unsigned int paddedBrickDim = _tsp->paddedBrickDim(); + unsigned int padding = (paddedBrickDim - brickDim) / 2; + + int numOtNodes = _tsp->numOTNodes(); + unsigned int leafIndex = bstOffset * numOtNodes + octreeOffset; + std::vector leafValues = readValues(leafIndex); + int numVoxels = leafValues.size(); + + int bstNode = bstOffset; + bool bstRightOnly = true; + unsigned int bstLevel = 0; + + do { + + glm::vec3 leafOffset(0.0); // Leaf offset in leaf sized voxels + unsigned int octreeLevel = 0; + unsigned int octreeNode = octreeOffset; + bool octreeLastOnly = true; + do { + // Visit ancestor + if (bstNode != bstOffset || octreeNode != octreeOffset) { + // Is actually an ancestor + + std::vector ancestorVoxels; + unsigned int ancestorBrickIndex = bstNode * numOtNodes + octreeNode; + unsigned int innerNodeIndex = brickToInnerNodeIndex(ancestorBrickIndex); + auto it = _voxelCache.find(innerNodeIndex); + if (it == _voxelCache.end()) { + // First visit + _histograms[innerNodeIndex] = Histogram(_minBin, _maxBin, _numBins); + ancestorVoxels = readValues(ancestorBrickIndex); + _voxelCache[innerNodeIndex] = ancestorVoxels; + } else { + ancestorVoxels = it->second; + } + + float voxelScale = pow(2, octreeLevel); + float invVoxelScale = 1.0 / voxelScale; + + // Calculate leaf offset in ancestor sized voxels + glm::vec3 ancestorOffset = (leafOffset * invVoxelScale) + glm::vec3(padding - 0.5); + + for (int z = 0; z < brickDim; z++) { + for (int y = 0; y < brickDim; y++) { + for (int x = 0; x < brickDim; x++) { + glm::vec3 leafSamplePoint = glm::vec3(x, y, z) + glm::vec3(padding); + glm::vec3 ancestorSamplePoint = ancestorOffset + (glm::vec3(x, y, z) + glm::vec3(0.5)) * invVoxelScale; + float leafValue = leafValues[linearCoords(leafSamplePoint)]; + float ancestorValue = interpolate(ancestorSamplePoint, ancestorVoxels); + + _histograms[innerNodeIndex].addRectangle(leafValue, ancestorValue, std::abs(leafValue - ancestorValue)); + } + } + } + + if (bstRightOnly && octreeLastOnly) { + _voxelCache.erase(innerNodeIndex); + } + } + + // Traverse to next octree ancestor + int octreeChild = (octreeNode - 1) % 8; + octreeLastOnly &= octreeChild == 7; + octreeNode = parentOffset(octreeNode, 8); + + int childSize = pow(2, octreeLevel) * brickDim; + leafOffset.x += (octreeChild % 2) * childSize; + leafOffset.y += ((octreeChild / 2) % 2) * childSize; + leafOffset.z += (octreeChild / 4) * childSize; + + octreeLevel++; + } while (octreeNode != -1); + + bstRightOnly &= (bstNode % 2 == 0); + bstNode = parentOffset(bstNode, 2); + + bstLevel++; + } while (bstNode != -1); + + return true; +} + +bool ErrorHistogramManager::loadFromFile(const std::string& filename) { + std::ifstream file(filename, std::ios::in | std::ios::binary); + if (!file.is_open()) { + return false; + } + + file.read(reinterpret_cast(&_numInnerNodes), sizeof(int)); + file.read(reinterpret_cast(&_numBins), sizeof(int)); + file.read(reinterpret_cast(&_minBin), sizeof(float)); + file.read(reinterpret_cast(&_maxBin), sizeof(float)); + + int nFloats = _numInnerNodes * _numBins; + float* histogramData = new float[nFloats]; + file.read(reinterpret_cast(histogramData), sizeof(float) * nFloats); + + _histograms = std::vector(_numInnerNodes); + + for (int i = 0; i < _numInnerNodes; ++i) { + int offset = i*_numBins; + float* data = new float[_numBins]; + memcpy(data, &histogramData[offset], sizeof(float) * _numBins); + _histograms[i] = Histogram(_minBin, _maxBin, _numBins, data); + } + + delete[] histogramData; + // No need to deallocate histogram data, since histograms take ownership. + file.close(); + return true; +} + + +bool ErrorHistogramManager::saveToFile(const std::string& filename) { + std::ofstream file(filename, std::ios::out | std::ios::binary); + if (!file.is_open()) { + return false; + } + + file.write(reinterpret_cast(&_numInnerNodes), sizeof(int)); + file.write(reinterpret_cast(&_numBins), sizeof(int)); + file.write(reinterpret_cast(&_minBin), sizeof(float)); + file.write(reinterpret_cast(&_maxBin), sizeof(float)); + + int nFloats = _numInnerNodes * _numBins; + float* histogramData = new float[nFloats]; + + for (int i = 0; i < _numInnerNodes; ++i) { + int offset = i*_numBins; + memcpy(&histogramData[offset], _histograms[i].data(), sizeof(float) * _numBins); + } + + file.write(reinterpret_cast(histogramData), sizeof(float) * nFloats); + delete[] histogramData; + + file.close(); + return true; +} + +unsigned int ErrorHistogramManager::linearCoords(glm::vec3 coords) const { + return linearCoords(glm::ivec3(coords)); +} + +unsigned int ErrorHistogramManager::linearCoords(int x, int y, int z) const { + return linearCoords(glm::ivec3(x, y, z)); +} + +unsigned int ErrorHistogramManager::linearCoords(glm::ivec3 coords) const { + unsigned int paddedBrickDim = _tsp->paddedBrickDim(); + return coords.z * paddedBrickDim * paddedBrickDim + coords.y * paddedBrickDim + coords.x; +} + +float ErrorHistogramManager::interpolate(glm::vec3 samplePoint, const std::vector& voxels) const { + int lowX = samplePoint.x; + int lowY = samplePoint.y; + int lowZ = samplePoint.z; + + int highX = ceil(samplePoint.x); + int highY = ceil(samplePoint.y); + int highZ = ceil(samplePoint.z); + + float interpolatorX = 1.0 - (samplePoint.x - lowX); + float interpolatorY = 1.0 - (samplePoint.y - lowY); + float interpolatorZ = 1.0 - (samplePoint.z - lowZ); + + float v000 = voxels[linearCoords(lowX, lowY, lowZ)]; + float v001 = voxels[linearCoords(lowX, lowY, highZ)]; + float v010 = voxels[linearCoords(lowX, highY, lowZ)]; + float v011 = voxels[linearCoords(lowX, highY, highZ)]; + float v100 = voxels[linearCoords(highX, lowY, lowZ)]; + float v101 = voxels[linearCoords(highX, lowY, highZ)]; + float v110 = voxels[linearCoords(highX, highY, lowZ)]; + float v111 = voxels[linearCoords(highX, highY, highZ)]; + + float v00 = interpolatorZ * v000 + (1.0 - interpolatorZ) * v001; + float v01 = interpolatorZ * v010 + (1.0 - interpolatorZ) * v011; + float v10 = interpolatorZ * v100 + (1.0 - interpolatorZ) * v101; + float v11 = interpolatorZ * v110 + (1.0 - interpolatorZ) * v111; + + float v0 = interpolatorY * v00 + (1.0 - interpolatorY) * v01; + float v1 = interpolatorY * v10 + (1.0 - interpolatorY) * v11; + + return interpolatorX * v0 + (1.0 - interpolatorX) * v1; + +} + +const Histogram* ErrorHistogramManager::getHistogram(unsigned int brickIndex) const { + unsigned int innerNodeIndex = brickToInnerNodeIndex(brickIndex); + if (innerNodeIndex < _numInnerNodes) { + return &(_histograms[innerNodeIndex]); + } else { + return nullptr; + } +} + +int ErrorHistogramManager::parentOffset(int offset, int base) const { + if (offset == 0) { + return -1; + } + int depth = floor(log(((base - 1) * offset + 1.0)) / log(base)); + int firstInLevel = (pow(base, depth) - 1) / (base - 1); + int inLevelOffset = offset - firstInLevel; + + int parentDepth = depth - 1; + int firstInParentLevel = (pow(base, parentDepth) - 1) / (base - 1); + int parentInLevelOffset = inLevelOffset / base; + + int parentOffset = firstInParentLevel + parentInLevelOffset; + return parentOffset; +} + +std::vector ErrorHistogramManager::readValues(unsigned int brickIndex) const { + unsigned int paddedBrickDim = _tsp->paddedBrickDim(); + unsigned int numBrickVals = paddedBrickDim * paddedBrickDim * paddedBrickDim; + std::vector voxelValues(numBrickVals); + + std::streampos offset = _tsp->dataPosition() + static_cast(brickIndex*numBrickVals*sizeof(float)); + _file->seekg(offset); + + _file->read(reinterpret_cast(&voxelValues[0]), + static_cast(numBrickVals)*sizeof(float)); + + return voxelValues; +} + +unsigned int ErrorHistogramManager::brickToInnerNodeIndex(unsigned int brickIndex) const { + unsigned int numOtNodes = _tsp->numOTNodes(); + unsigned int numBstLevels = _tsp->numBSTLevels(); + + unsigned int numInnerBstNodes = (pow(2, numBstLevels - 1) - 1) * numOtNodes; + if (brickIndex < numInnerBstNodes) return brickIndex; + + unsigned int numOtLeaves = pow(8, _tsp->numOTLevels() - 1); + unsigned int numOtInnerNodes = (numOtNodes - numOtLeaves); + + unsigned int innerBstOffset = brickIndex - numInnerBstNodes; + unsigned int rowIndex = innerBstOffset / numOtNodes; + unsigned int indexInRow = innerBstOffset % numOtNodes; + + if (indexInRow >= numOtInnerNodes) return -1; + + unsigned int offset = rowIndex * numOtInnerNodes; + unsigned int leavesOffset = offset + indexInRow; + + return numInnerBstNodes + leavesOffset; +} + +unsigned int ErrorHistogramManager::innerNodeToBrickIndex(unsigned int innerNodeIndex) const { + if (innerNodeIndex < 0 || innerNodeIndex >= _numInnerNodes) return -1; // Not an inner node + + unsigned int numOtNodes = _tsp->numOTNodes(); + unsigned int numBstLevels = _tsp->numBSTLevels(); + + unsigned int numInnerBstNodes = (pow(2, numBstLevels - 1) - 1) * numOtNodes; + if (innerNodeIndex < numInnerBstNodes) return innerNodeIndex; + + unsigned int numOtLeaves = pow(8, _tsp->numOTLevels() - 1); + unsigned int numOtInnerNodes = (numOtNodes - numOtLeaves); + + unsigned int innerBstOffset = innerNodeIndex - numInnerBstNodes; + unsigned int rowIndex = innerBstOffset / numOtInnerNodes; + unsigned int indexInRow = innerBstOffset % numOtInnerNodes; + + unsigned int offset = rowIndex * numOtNodes; + unsigned int leavesOffset = offset + indexInRow; + + return numInnerBstNodes + leavesOffset; +} + +} // namespace openspace + diff --git a/modules/multiresvolume/rendering/errorhistogrammanager.h b/modules/multiresvolume/rendering/errorhistogrammanager.h new file mode 100644 index 0000000000..672adffc81 --- /dev/null +++ b/modules/multiresvolume/rendering/errorhistogrammanager.h @@ -0,0 +1,76 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __ERRORHISTOGRAMMANAGER_H__ +#define __ERRORHISTOGRAMMANAGER_H__ + +#include +#include +#include +#include + +#include + +namespace openspace { + +class ErrorHistogramManager { +public: + ErrorHistogramManager(TSP* tsp); + ~ErrorHistogramManager(); + + bool buildHistograms(int numBins); + const Histogram* getHistogram(unsigned int brickIndex) const; + + bool loadFromFile(const std::string& filename); + bool saveToFile(const std::string& filename); + +private: + TSP* _tsp; + std::ifstream* _file; + + std::vector _histograms; + unsigned int _numInnerNodes; + float _minBin; + float _maxBin; + int _numBins; + + std::map> _voxelCache; + + bool buildFromLeaf(unsigned int bstOffset, unsigned int octreeOffset); + std::vector readValues(unsigned int brickIndex) const; + + int parentOffset(int offset, int base) const; + + unsigned int brickToInnerNodeIndex(unsigned int brickIndex) const; + unsigned int innerNodeToBrickIndex(unsigned int innerNodeIndex) const; + unsigned int linearCoords(glm::vec3 coords) const; + unsigned int linearCoords(int x, int y, int z) const; + unsigned int linearCoords(glm::ivec3 coords) const; + + float interpolate(glm::vec3 samplePoint, const std::vector& voxels) const; +}; + +} // namespace openspace + +#endif // __ERRORHISTOGRAMMANAGER_H__ diff --git a/modules/multiresvolume/rendering/histogram.cpp b/modules/multiresvolume/rendering/histogram.cpp new file mode 100644 index 0000000000..4f78fab787 --- /dev/null +++ b/modules/multiresvolume/rendering/histogram.cpp @@ -0,0 +1,221 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 + +#include + +#include +#include +namespace { + const std::string _loggerCat = "Histogram"; +} + +namespace openspace { + +Histogram::Histogram() + : _minBin(0) + , _maxBin(0) + , _numBins(-1) + , _data(nullptr) {} + +Histogram::Histogram(float minBin, float maxBin, int numBins) + : _minBin(minBin) + , _maxBin(maxBin) + , _numBins(numBins) + , _data(nullptr) { + + _data = new float[numBins]; + for (int i = 0; i < numBins; ++i) { + _data[i] = 0.0; + } +} + +Histogram::Histogram(float minBin, float maxBin, int numBins, float *data) + : _minBin(minBin) + , _maxBin(maxBin) + , _numBins(numBins) + , _data(data) {} + +Histogram::Histogram(Histogram&& other) { + _minBin = other._minBin; + _maxBin = other._maxBin; + _numBins = other._numBins; + _data = other._data; + other._data = nullptr; +} + +Histogram& Histogram::operator=(Histogram&& other) { + _minBin = other._minBin; + _maxBin = other._maxBin; + _numBins = other._numBins; + _data = other._data; + other._data = nullptr; + return *this; +} + + +Histogram::~Histogram() { + if (_data) { + delete[] _data; + } +} + + +int Histogram::numBins() const { + return _numBins; +} + +float Histogram::minBin() const { + return _minBin; +} + +float Histogram::maxBin() const { + return _maxBin; +} + +bool Histogram::isValid() const { + return _numBins != -1; +} + + +bool Histogram::add(float bin, float value) { + if (bin < _minBin || bin > _maxBin) { + // Out of range + return false; + } + + float normalizedBin = (bin - _minBin) / (_maxBin - _minBin); // [0.0, 1.0] + int binIndex = floor(normalizedBin * _numBins); // [0, _numBins] + if (binIndex == _numBins) binIndex--; // [0, _numBins[ + + _data[binIndex] += value; + return true; +} + +bool Histogram::add(const Histogram& histogram) { + if (_minBin == histogram.minBin() && _maxBin == histogram.maxBin() && _numBins == histogram.numBins()) { + + const float* data = histogram.data(); + for (int i = 0; i < _numBins; i++) { + + _data[i] += data[i]; + + } + return true; + } else { + LERROR("Dimension mismatch"); + return false; + } +} + +bool Histogram::addRectangle(float lowBin, float highBin, float value) { + if (lowBin == highBin) return true; + if (lowBin > highBin) { + std::swap(lowBin, highBin); + } + if (lowBin < _minBin || highBin > _maxBin) { + // Out of range + return false; + } + + float normalizedLowBin = (lowBin - _minBin) / (_maxBin - _minBin); + float normalizedHighBin = (highBin - _minBin) / (_maxBin - _minBin); + + float lowBinIndex = normalizedLowBin * _numBins; + float highBinIndex = normalizedHighBin * _numBins; + + int fillLow = floor(lowBinIndex); + int fillHigh = ceil(highBinIndex); + + for (int i = fillLow; i < fillHigh; i++) { + _data[i] += value; + } + + if (lowBinIndex > fillLow) { + float diff = lowBinIndex - fillLow; + _data[fillLow] -= diff * value; + } + if (highBinIndex < fillHigh) { + float diff = -highBinIndex + fillHigh; + _data[fillHigh - 1] -= diff * value; + } + + return true; +} + + +float Histogram::interpolate(float bin) const { + float normalizedBin = (bin - _minBin) / (_maxBin - _minBin); + float binIndex = normalizedBin * _numBins - 0.5; // Center + + float interpolator = binIndex - floor(binIndex); + int binLow = floor(binIndex); + int binHigh = ceil(binIndex); + + // Clamp bins + if (binLow < 0) binLow = 0; + if (binHigh >= _numBins) binHigh = _numBins - 1; + + return (1.0 - interpolator) * _data[binLow] + interpolator * _data[binHigh]; +} + +float Histogram::sample(int binIndex) const { + assert(binIndex >= 0 && binIndex < _numBins); + return _data[binIndex]; +} + + +const float* Histogram::data() const { + return _data; +} + +std::vector> Histogram::getDecimated(int numBins) const { + // Return a copy of _data decimated as in Ljung 2004 + return std::vector>(); +} + + +void Histogram::normalize() { + float sum = 0.0; + for (int i = 0; i < _numBins; i++) { + sum += _data[i]; + } + for (int i = 0; i < _numBins; i++) { + _data[i] /= sum; + } +} + +void Histogram::print() const { + std::cout << "number of bins: " << _numBins << std::endl + << "range: " << _minBin << " - " << _maxBin << std::endl << std::endl; + for (int i = 0; i < _numBins; i++) { + float low = _minBin + float(i) / _numBins * (_maxBin - _minBin); + float high = low + (_maxBin - _minBin) / float(_numBins); + std::cout << "[" << low << ", " << high << "[" << std::endl + << " " << _data[i] << std::endl; + } +} + +} diff --git a/modules/multiresvolume/rendering/histogram.h b/modules/multiresvolume/rendering/histogram.h new file mode 100644 index 0000000000..ab590d079e --- /dev/null +++ b/modules/multiresvolume/rendering/histogram.h @@ -0,0 +1,70 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __HISTOGRAM_H__ +#define __HISTOGRAM_H__ + +#include +#include + +namespace openspace { +class Histogram { + +public: + Histogram(); + Histogram(float minBin, float maxBin, int numBins); + Histogram(float minBin, float maxBin, int numBins, float *data); + Histogram(Histogram&& other); + ~Histogram(); + + Histogram& operator=(Histogram&& other); + + int numBins() const; + float minBin() const; + float maxBin() const; + bool isValid() const; + + bool add(float bin, float value); + bool add(const Histogram& histogram); + bool addRectangle(float lowBin, float highBin, float value); + + float interpolate(float bin) const; + float sample(int binIndex) const; + const float* data() const; + std::vector> getDecimated(int numBins) const; + + void normalize(); + void print() const; + +private: + int _numBins; + float _minBin; + float _maxBin; + + float* _data; + +}; // class Histogram +} // namespace openspace + +#endif //__HISTOGRAM_H__ diff --git a/modules/multiresvolume/rendering/histogrammanager.cpp b/modules/multiresvolume/rendering/histogrammanager.cpp new file mode 100644 index 0000000000..8a5d8a67b8 --- /dev/null +++ b/modules/multiresvolume/rendering/histogrammanager.cpp @@ -0,0 +1,192 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 +#include +#include +#include + +#include +#include + +namespace { + const std::string _loggerCat = "HistogramManager"; +} + +namespace openspace { + +HistogramManager::HistogramManager() {} + +HistogramManager::~HistogramManager() {} + +bool HistogramManager::buildHistograms(TSP* tsp, int numBins) { + std::cout << "Build histograms with " << numBins << " bins each" << std::endl; + _numBins = numBins; + + std::ifstream& file = tsp->file(); + if (!file.is_open()) { + return false; + } + _minBin = 0.0; // Should be calculated from tsp file + _maxBin = 1.0; // Should be calculated from tsp file + + int numTotalNodes = tsp->numTotalNodes(); + _histograms = std::vector(numTotalNodes); + + bool success = buildHistogram(tsp, 0); + + return success; +} + +Histogram* HistogramManager::getHistogram(unsigned int brickIndex) { + return &_histograms[brickIndex]; +} + +bool HistogramManager::buildHistogram(TSP* tsp, unsigned int brickIndex) { + Histogram histogram(_minBin, _maxBin, _numBins); + bool isBstLeaf = tsp->isBstLeaf(brickIndex); + bool isOctreeLeaf = tsp->isOctreeLeaf(brickIndex); + + if (isBstLeaf && isOctreeLeaf) { + // TSP leaf, read from file and build histogram + std::vector voxelValues = readValues(tsp, brickIndex); + unsigned int numVoxels = voxelValues.size(); + + for (unsigned int v = 0; v < numVoxels; ++v) { + histogram.add(voxelValues[v], 1.0); + } + } else { + // Has children + auto children = std::vector(); + + if (!isBstLeaf) { + // Push BST children + children.push_back(tsp->getBstLeft(brickIndex)); + children.push_back(tsp->getBstRight(brickIndex)); + } + if (!isOctreeLeaf) { + // Push Octree children + unsigned int firstChild = tsp->getFirstOctreeChild(brickIndex); + for (int c = 0; c < 8; c++) { + children.push_back(firstChild + c); + } + } + int numChildren = children.size(); + for (int c = 0; c < numChildren; c++) { + // Visit child + unsigned int childIndex = children[c]; + if (_histograms[childIndex].isValid() || buildHistogram(tsp, childIndex)) { + if (numChildren <= 8 || c < 2) { + // If node has both BST and Octree children, only add BST ones + histogram.add(_histograms[childIndex]); + } + } else { + return false; + } + } + } + + //histogram.normalize(); + _histograms[brickIndex] = std::move(histogram); + + + return true; +} + +std::vector HistogramManager::readValues(TSP* tsp, unsigned int brickIndex) { + unsigned int paddedBrickDim = tsp->paddedBrickDim(); + unsigned int numBrickVals = paddedBrickDim * paddedBrickDim * paddedBrickDim; + std::vector voxelValues(numBrickVals); + + std::streampos offset = tsp->dataPosition() + static_cast(brickIndex*numBrickVals*sizeof(float)); + std::ifstream& file = tsp->file(); + file.seekg(offset); + + file.read(reinterpret_cast(&voxelValues[0]), + static_cast(numBrickVals)*sizeof(float)); + + return voxelValues; +} + +bool HistogramManager::loadFromFile(const std::string& filename) { + std::ifstream file(filename, std::ios::in | std::ios::binary); + if (!file.is_open()) { + return false; + } + + int numHistograms; + file.read(reinterpret_cast(&numHistograms), sizeof(int)); + file.read(reinterpret_cast(&_numBins), sizeof(int)); + file.read(reinterpret_cast(&_minBin), sizeof(float)); + file.read(reinterpret_cast(&_maxBin), sizeof(float)); + + int nFloats = numHistograms * _numBins; + float* histogramData = new float[nFloats]; + file.read(reinterpret_cast(histogramData), sizeof(float) * nFloats); + + _histograms = std::vector(numHistograms); + + for (int i = 0; i < numHistograms; ++i) { + int offset = i*_numBins; + float* data = new float[_numBins]; + memcpy(data, &histogramData[offset], sizeof(float) * _numBins); + _histograms[i] = Histogram(_minBin, _maxBin, _numBins, data); + } + + delete[] histogramData; + // No need to deallocate histogram data, since histograms take ownership. + file.close(); + return true; +} + + +bool HistogramManager::saveToFile(const std::string& filename) { + std::ofstream file(filename, std::ios::out | std::ios::binary); + if (!file.is_open()) { + return false; + } + + int numHistograms = _histograms.size(); + file.write(reinterpret_cast(&numHistograms), sizeof(int)); + file.write(reinterpret_cast(&_numBins), sizeof(int)); + file.write(reinterpret_cast(&_minBin), sizeof(float)); + file.write(reinterpret_cast(&_maxBin), sizeof(float)); + + int nFloats = numHistograms * _numBins; + float* histogramData = new float[nFloats]; + + for (int i = 0; i < numHistograms; ++i) { + int offset = i*_numBins; + memcpy(&histogramData[offset], _histograms[i].data(), sizeof(float) * _numBins); + } + + file.write(reinterpret_cast(histogramData), sizeof(float) * nFloats); + delete[] histogramData; + + file.close(); + return true; +} + +} // namespace openspace + diff --git a/modules/multiresvolume/rendering/histogrammanager.h b/modules/multiresvolume/rendering/histogrammanager.h new file mode 100644 index 0000000000..8c81d578c2 --- /dev/null +++ b/modules/multiresvolume/rendering/histogrammanager.h @@ -0,0 +1,54 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __HISTOGRAMMANAGER_H__ +#define __HISTOGRAMMANAGER_H__ + +#include +#include +#include + +namespace openspace { + +class HistogramManager { +public: + HistogramManager(); + ~HistogramManager(); + bool buildHistograms(TSP* tsp, int numBins); + Histogram* getHistogram(unsigned int brickIndex); + bool loadFromFile(const std::string& filename); + bool saveToFile(const std::string& filename); +private: + std::vector _histograms; + float _minBin; + float _maxBin; + int _numBins; + + bool buildHistogram(TSP* tsp, unsigned int brickIndex); + std::vector readValues(TSP* tsp, unsigned int brickIndex); +}; + +} // namespace openspace + +#endif // __HISTOGRAMMANAGER_H__ diff --git a/modules/multiresvolume/rendering/localerrorhistogrammanager.cpp b/modules/multiresvolume/rendering/localerrorhistogrammanager.cpp new file mode 100644 index 0000000000..67333eb86b --- /dev/null +++ b/modules/multiresvolume/rendering/localerrorhistogrammanager.cpp @@ -0,0 +1,490 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 +#include +#include +#include + +#include +#include + +#include + +#include + +namespace { + const std::string _loggerCat = "LocalErrorHistogramManager"; +} + +namespace openspace { + +LocalErrorHistogramManager::LocalErrorHistogramManager(TSP* tsp) : _tsp(tsp) {} + +LocalErrorHistogramManager::~LocalErrorHistogramManager() {} + +bool LocalErrorHistogramManager::buildHistograms(int numBins) { + LINFO("Build histograms with " << numBins << " bins each"); + _numBins = numBins; + + _file = &(_tsp->file()); + if (!_file->is_open()) { + return false; + } + _minBin = 0.0; // Should be calculated from tsp file + _maxBin = 1.0; // Should be calculated from tsp file as (maxValue - minValue) + + unsigned int numOtLevels = _tsp->numOTLevels(); + unsigned int numOtLeaves = pow(8, numOtLevels - 1); + unsigned int numBstLeaves = pow(2, _tsp->numBSTLevels() - 1); + + _numInnerNodes = _tsp->numTotalNodes() - numOtLeaves * numBstLeaves; + + _spatialHistograms = std::vector(_numInnerNodes); + _temporalHistograms = std::vector(_numInnerNodes); + for (unsigned int i = 0; i < _numInnerNodes; i++) { + _spatialHistograms[i] = Histogram(_minBin, _maxBin, numBins); + _temporalHistograms[i] = Histogram(_minBin, _maxBin, numBins); + } + + // All TSP Leaves + int numOtNodes = _tsp->numOTNodes(); + int otOffset = (pow(8, numOtLevels - 1) - 1) / 7; + + int numBstNodes = _tsp->numBSTNodes(); + int bstOffset = numBstNodes / 2; + + int numberOfLeaves = numOtLeaves * numBstLeaves; + + LINFO("Building spatial histograms"); + ProgressBar pb1(numberOfLeaves); + int processedLeaves = 0; + pb1.print(processedLeaves); + bool success = true; + for (int bst = bstOffset; bst < numBstNodes; bst++) { + for (int ot = otOffset; ot < numOtNodes; ot++) { + success &= buildFromOctreeChild(bst, ot); + if (!success) LERROR("Failed in buildFromOctreeChild"); + if (!success) return false; + pb1.print(processedLeaves++); + } + } + //pb1.stop(); + + + LINFO("Building temporal histograms"); + ProgressBar pb2(numberOfLeaves); + processedLeaves = 0; + pb2.print(processedLeaves); + for (int ot = otOffset; ot < numOtNodes; ot++) { + for (int bst = bstOffset; bst < numBstNodes; bst++) { + success &= buildFromBstChild(bst, ot); + if (!success) LERROR("Failed in buildFromBstChild"); + if (!success) return false; + pb2.print(processedLeaves++); + } + } + //pb2.stop(); + + return success; +} + +bool LocalErrorHistogramManager::buildFromOctreeChild(unsigned int bstOffset, unsigned int octreeOffset) { + // Add errors to octree parent histogram + int numOtNodes = _tsp->numOTNodes(); + unsigned int childIndex = bstOffset * numOtNodes + octreeOffset; + bool isOctreeLeaf = _tsp->isOctreeLeaf(childIndex); + + if (octreeOffset > 0) { + // Not octree root + std::vector childValues; + std::vector parentValues; + + int octreeParent = parentOffset(octreeOffset, 8); + unsigned int parentIndex = bstOffset * numOtNodes + octreeParent; + unsigned int parentInnerNodeIndex = brickToInnerNodeIndex(parentIndex); + + if (isOctreeLeaf) { + childValues = readValues(childIndex); + } else { + unsigned int childInnerNodeIndex = brickToInnerNodeIndex(childIndex); + auto it = _voxelCache.find(childInnerNodeIndex); + if (it != _voxelCache.end()) { + childValues = it->second; + } else { + LERROR("Child " << childIndex << " visited without cache, " << bstOffset << ", " << octreeOffset); + return false; + } + } + + int octreeChildIndex = (octreeOffset - 1) % 8; + if (octreeChildIndex == 0) { + parentValues = readValues(parentIndex); + _voxelCache[parentInnerNodeIndex] = parentValues; + } else { + auto it = _voxelCache.find(parentInnerNodeIndex); + if (it != _voxelCache.end()) { + parentValues = it->second; + } else { + LERROR("Parent " << parentIndex << " visited without cache"); + return false; + } + } + + // Compare values and add errors to parent histogram + unsigned int paddedBrickDim = _tsp->paddedBrickDim(); + unsigned int brickDim = _tsp->brickDim(); + unsigned int padding = (paddedBrickDim - brickDim) / 2; + + glm::vec3 parentOffset = glm::vec3(octreeChildIndex % 2, (octreeChildIndex / 2) % 2, octreeChildIndex / 4) * float(brickDim) / 2.f; + + for (int z = 0; z < brickDim; z++) { + for (int y = 0; y < brickDim; y++) { + for (int x = 0; x < brickDim; x++) { + glm::vec3 childSamplePoint = glm::vec3(x, y, z) + glm::vec3(padding); + glm::vec3 parentSamplePoint = parentOffset + (glm::vec3(x, y, z) + glm::vec3(0.5)) * 0.5f; + float childValue = childValues[linearCoords(childSamplePoint)]; + float parentValue = interpolate(parentSamplePoint, parentValues); + + // Divide by number of child voxels that will be taken into account + float rectangleHeight = std::abs(childValue - parentValue) / 8.0; + _spatialHistograms[parentInnerNodeIndex].addRectangle(childValue, parentValue, rectangleHeight); + } + } + } + + bool isLastOctreeChild = octreeOffset > 0 && octreeChildIndex == 7; + if (isLastOctreeChild) { + buildFromOctreeChild(bstOffset, octreeParent); + } + } + + if (!isOctreeLeaf) { + unsigned int childInnerNodeIndex = brickToInnerNodeIndex(childIndex); + _voxelCache.erase(childInnerNodeIndex); + } + + int bstChildIndex = bstOffset % 2; + bool isLastBstChild = bstOffset > 0 && bstChildIndex == 0; + if (isOctreeLeaf && isLastBstChild) { + int bstParent = parentOffset(bstOffset, 2); + buildFromOctreeChild(bstParent, octreeOffset); + } + + return true; +} + +bool LocalErrorHistogramManager::buildFromBstChild(unsigned int bstOffset, unsigned int octreeOffset) { + // Add errors to bst parent histogram + int numOtNodes = _tsp->numOTNodes(); + unsigned int childIndex = bstOffset * numOtNodes + octreeOffset; + bool isBstLeaf = _tsp->isBstLeaf(childIndex); + + if (bstOffset > 0) { + // Not BST root + std::vector childValues; + std::vector parentValues; + + int bstParent = parentOffset(bstOffset, 2); + unsigned int parentIndex = bstParent * numOtNodes + octreeOffset; + unsigned int parentInnerNodeIndex = brickToInnerNodeIndex(parentIndex); + + if (isBstLeaf) { + childValues = readValues(childIndex); + } else { + unsigned int childInnerNodeIndex = brickToInnerNodeIndex(childIndex); + auto it = _voxelCache.find(childInnerNodeIndex); + if (it != _voxelCache.end()) { + childValues = it->second; + } else { + LERROR("Child " << childIndex << " visited without cache"); + return false; + } + } + + int bstChildIndex = bstOffset % 2; + if (bstChildIndex == 1) { + parentValues = readValues(parentIndex); + _voxelCache[parentInnerNodeIndex] = parentValues; + } else { + auto it = _voxelCache.find(parentInnerNodeIndex); + if (it != _voxelCache.end()) { + parentValues = it->second; + } else { + LERROR("Parent " << parentIndex << " visited without cache"); + return false; + } + } + + // Compare values and add errors to parent histogram + unsigned int paddedBrickDim = _tsp->paddedBrickDim(); + unsigned int brickDim = _tsp->brickDim(); + unsigned int padding = (paddedBrickDim - brickDim) / 2; + + for (int z = 0; z < brickDim; z++) { + for (int y = 0; y < brickDim; y++) { + for (int x = 0; x < brickDim; x++) { + glm::vec3 samplePoint = glm::vec3(x, y, z) + glm::vec3(padding); + unsigned int linearSamplePoint = linearCoords(samplePoint); + float childValue = childValues[linearSamplePoint]; + float parentValue = parentValues[linearSamplePoint]; + + // Divide by number of child voxels that will be taken into account + float rectangleHeight = std::abs(childValue - parentValue) / 2.0; + _temporalHistograms[parentInnerNodeIndex].addRectangle(childValue, parentValue, rectangleHeight); + } + } + } + + bool isLastBstChild = bstOffset > 0 && bstChildIndex == 0; + if (isLastBstChild) { + buildFromBstChild(bstParent, octreeOffset); + } + } + + if (!isBstLeaf) { + unsigned int childInnerNodeIndex = brickToInnerNodeIndex(childIndex); + _voxelCache.erase(childInnerNodeIndex); + } + + int octreeChildIndex = (octreeOffset - 1) % 8; + bool isLastOctreeChild = octreeOffset > 0 && octreeChildIndex == 7; + if (isBstLeaf && isLastOctreeChild) { + int octreeParent = parentOffset(octreeOffset, 8); + buildFromBstChild(bstOffset, octreeParent); + } + + return true; +} + +bool LocalErrorHistogramManager::loadFromFile(const std::string& filename) { + std::ifstream file(filename, std::ios::in | std::ios::binary); + if (!file.is_open()) { + return false; + } + + file.read(reinterpret_cast(&_numInnerNodes), sizeof(int)); + file.read(reinterpret_cast(&_numBins), sizeof(int)); + file.read(reinterpret_cast(&_minBin), sizeof(float)); + file.read(reinterpret_cast(&_maxBin), sizeof(float)); + + int nFloats = _numInnerNodes * _numBins; + float* histogramData = new float[nFloats]; + + file.read(reinterpret_cast(histogramData), sizeof(float) * nFloats); + _spatialHistograms = std::vector(_numInnerNodes); + for (int i = 0; i < _numInnerNodes; ++i) { + int offset = i*_numBins; + float* data = new float[_numBins]; + memcpy(data, &histogramData[offset], sizeof(float) * _numBins); + _spatialHistograms[i] = Histogram(_minBin, _maxBin, _numBins, data); + } + + file.read(reinterpret_cast(histogramData), sizeof(float) * nFloats); + _temporalHistograms = std::vector(_numInnerNodes); + for (int i = 0; i < _numInnerNodes; ++i) { + int offset = i*_numBins; + float* data = new float[_numBins]; + memcpy(data, &histogramData[offset], sizeof(float) * _numBins); + _temporalHistograms[i] = Histogram(_minBin, _maxBin, _numBins, data); + } + + delete[] histogramData; + // No need to deallocate histogram data, since histograms take ownership. + file.close(); + return true; +} + + +bool LocalErrorHistogramManager::saveToFile(const std::string& filename) { + std::ofstream file(filename, std::ios::out | std::ios::binary); + if (!file.is_open()) { + return false; + } + + file.write(reinterpret_cast(&_numInnerNodes), sizeof(int)); + file.write(reinterpret_cast(&_numBins), sizeof(int)); + file.write(reinterpret_cast(&_minBin), sizeof(float)); + file.write(reinterpret_cast(&_maxBin), sizeof(float)); + + int nFloats = _numInnerNodes * _numBins; + float* histogramData = new float[nFloats]; + + for (int i = 0; i < _numInnerNodes; ++i) { + int offset = i*_numBins; + memcpy(&histogramData[offset], _spatialHistograms[i].data(), sizeof(float) * _numBins); + } + file.write(reinterpret_cast(histogramData), sizeof(float) * nFloats); + + for (int i = 0; i < _numInnerNodes; ++i) { + int offset = i*_numBins; + memcpy(&histogramData[offset], _temporalHistograms[i].data(), sizeof(float) * _numBins); + } + file.write(reinterpret_cast(histogramData), sizeof(float) * nFloats); + + delete[] histogramData; + + file.close(); + return true; +} + +unsigned int LocalErrorHistogramManager::linearCoords(glm::vec3 coords) const { + return linearCoords(glm::ivec3(coords)); +} + +unsigned int LocalErrorHistogramManager::linearCoords(int x, int y, int z) const { + return linearCoords(glm::ivec3(x, y, z)); +} + +unsigned int LocalErrorHistogramManager::linearCoords(glm::ivec3 coords) const { + unsigned int paddedBrickDim = _tsp->paddedBrickDim(); + return coords.z * paddedBrickDim * paddedBrickDim + coords.y * paddedBrickDim + coords.x; +} + +float LocalErrorHistogramManager::interpolate(glm::vec3 samplePoint, const std::vector& voxels) const { + int lowX = samplePoint.x; + int lowY = samplePoint.y; + int lowZ = samplePoint.z; + + int highX = ceil(samplePoint.x); + int highY = ceil(samplePoint.y); + int highZ = ceil(samplePoint.z); + + float interpolatorX = 1.0 - (samplePoint.x - lowX); + float interpolatorY = 1.0 - (samplePoint.y - lowY); + float interpolatorZ = 1.0 - (samplePoint.z - lowZ); + + float v000 = voxels[linearCoords(lowX, lowY, lowZ)]; + float v001 = voxels[linearCoords(lowX, lowY, highZ)]; + float v010 = voxels[linearCoords(lowX, highY, lowZ)]; + float v011 = voxels[linearCoords(lowX, highY, highZ)]; + float v100 = voxels[linearCoords(highX, lowY, lowZ)]; + float v101 = voxels[linearCoords(highX, lowY, highZ)]; + float v110 = voxels[linearCoords(highX, highY, lowZ)]; + float v111 = voxels[linearCoords(highX, highY, highZ)]; + + float v00 = interpolatorZ * v000 + (1.0 - interpolatorZ) * v001; + float v01 = interpolatorZ * v010 + (1.0 - interpolatorZ) * v011; + float v10 = interpolatorZ * v100 + (1.0 - interpolatorZ) * v101; + float v11 = interpolatorZ * v110 + (1.0 - interpolatorZ) * v111; + + float v0 = interpolatorY * v00 + (1.0 - interpolatorY) * v01; + float v1 = interpolatorY * v10 + (1.0 - interpolatorY) * v11; + + return interpolatorX * v0 + (1.0 - interpolatorX) * v1; + +} + +const Histogram* LocalErrorHistogramManager::getSpatialHistogram(unsigned int brickIndex) const { + unsigned int innerNodeIndex = brickToInnerNodeIndex(brickIndex); + if (innerNodeIndex < _numInnerNodes) { + return &(_spatialHistograms[innerNodeIndex]); + } else { + return nullptr; + } +} + +const Histogram* LocalErrorHistogramManager::getTemporalHistogram(unsigned int brickIndex) const { + unsigned int innerNodeIndex = brickToInnerNodeIndex(brickIndex); + if (innerNodeIndex < _numInnerNodes) { + return &(_temporalHistograms[innerNodeIndex]); + } else { + return nullptr; + } +} + +int LocalErrorHistogramManager::parentOffset(int offset, int base) const { + if (offset == 0) { + return -1; + } + int depth = floor(log(((base - 1) * offset + 1.0)) / log(base)); + int firstInLevel = (pow(base, depth) - 1) / (base - 1); + int inLevelOffset = offset - firstInLevel; + + int parentDepth = depth - 1; + int firstInParentLevel = (pow(base, parentDepth) - 1) / (base - 1); + int parentInLevelOffset = inLevelOffset / base; + + int parentOffset = firstInParentLevel + parentInLevelOffset; + return parentOffset; +} + +std::vector LocalErrorHistogramManager::readValues(unsigned int brickIndex) const { + unsigned int paddedBrickDim = _tsp->paddedBrickDim(); + unsigned int numBrickVals = paddedBrickDim * paddedBrickDim * paddedBrickDim; + std::vector voxelValues(numBrickVals); + + std::streampos offset = _tsp->dataPosition() + static_cast(brickIndex*numBrickVals*sizeof(float)); + _file->seekg(offset); + + _file->read(reinterpret_cast(&voxelValues[0]), + static_cast(numBrickVals)*sizeof(float)); + + return voxelValues; +} + +unsigned int LocalErrorHistogramManager::brickToInnerNodeIndex(unsigned int brickIndex) const { + unsigned int numOtNodes = _tsp->numOTNodes(); + unsigned int numBstLevels = _tsp->numBSTLevels(); + + unsigned int numInnerBstNodes = (pow(2, numBstLevels - 1) - 1) * numOtNodes; + if (brickIndex < numInnerBstNodes) return brickIndex; + + unsigned int numOtLeaves = pow(8, _tsp->numOTLevels() - 1); + unsigned int numOtInnerNodes = (numOtNodes - numOtLeaves); + + unsigned int innerBstOffset = brickIndex - numInnerBstNodes; + unsigned int rowIndex = innerBstOffset / numOtNodes; + unsigned int indexInRow = innerBstOffset % numOtNodes; + + if (indexInRow >= numOtInnerNodes) return _numInnerNodes; + + unsigned int offset = rowIndex * numOtInnerNodes; + unsigned int leavesOffset = offset + indexInRow; + + return numInnerBstNodes + leavesOffset; +} + +unsigned int LocalErrorHistogramManager::innerNodeToBrickIndex(unsigned int innerNodeIndex) const { + unsigned int numOtNodes = _tsp->numOTNodes(); + unsigned int numBstLevels = _tsp->numBSTLevels(); + + unsigned int numInnerBstNodes = (pow(2, numBstLevels - 1) - 1) * numOtNodes; + if (innerNodeIndex < numInnerBstNodes) return innerNodeIndex; + + unsigned int numOtLeaves = pow(8, _tsp->numOTLevels() - 1); + unsigned int numOtInnerNodes = (numOtNodes - numOtLeaves); + + unsigned int innerBstOffset = innerNodeIndex - numInnerBstNodes; + unsigned int rowIndex = innerBstOffset / numOtInnerNodes; + unsigned int indexInRow = innerBstOffset % numOtInnerNodes; + + unsigned int offset = rowIndex * numOtNodes; + unsigned int leavesOffset = offset + indexInRow; + + return numInnerBstNodes + leavesOffset; +} + +} // namespace openspace + diff --git a/modules/multiresvolume/rendering/localerrorhistogrammanager.h b/modules/multiresvolume/rendering/localerrorhistogrammanager.h new file mode 100644 index 0000000000..000aff8597 --- /dev/null +++ b/modules/multiresvolume/rendering/localerrorhistogrammanager.h @@ -0,0 +1,80 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __LOCALERRORHISTOGRAMMANAGER_H__ +#define __LOCALERRORHISTOGRAMMANAGER_H__ + +#include +#include +#include +#include + +#include + +namespace openspace { + +class LocalErrorHistogramManager { +public: + LocalErrorHistogramManager(TSP* tsp); + ~LocalErrorHistogramManager(); + + bool buildHistograms(int numBins); + const Histogram* getSpatialHistogram(unsigned int brickIndex) const; + const Histogram* getTemporalHistogram(unsigned int brickIndex) const; + + bool loadFromFile(const std::string& filename); + bool saveToFile(const std::string& filename); + +private: + TSP* _tsp; + std::ifstream* _file; + + std::vector _spatialHistograms; + std::vector _temporalHistograms; + unsigned int _numInnerNodes; + float _minBin; + float _maxBin; + int _numBins; + + std::map> _voxelCache; + + bool buildFromOctreeChild(unsigned int bstOffset, unsigned int octreeOffset); + bool buildFromBstChild(unsigned int bstOffset, unsigned int octreeOffset); + + std::vector readValues(unsigned int brickIndex) const; + + int parentOffset(int offset, int base) const; + + unsigned int brickToInnerNodeIndex(unsigned int brickIndex) const; + unsigned int innerNodeToBrickIndex(unsigned int innerNodeIndex) const; + unsigned int linearCoords(glm::vec3 coords) const; + unsigned int linearCoords(int x, int y, int z) const; + unsigned int linearCoords(glm::ivec3 coords) const; + + float interpolate(glm::vec3 samplePoint, const std::vector& voxels) const; +}; + +} // namespace openspace + +#endif // __LOCALERRORHISTOGRAMMANAGER_H__ diff --git a/modules/multiresvolume/rendering/localtfbrickselector.cpp b/modules/multiresvolume/rendering/localtfbrickselector.cpp new file mode 100644 index 0000000000..72e4e3df17 --- /dev/null +++ b/modules/multiresvolume/rendering/localtfbrickselector.cpp @@ -0,0 +1,348 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 +#include +#include +#include +#include +#include +#include + +namespace { + const std::string _loggerCat = "LocalTfBrickSelector"; +} + +namespace openspace { + +LocalTfBrickSelector::LocalTfBrickSelector(TSP* tsp, LocalErrorHistogramManager* hm, TransferFunction* tf, int memoryBudget, int streamingBudget) + : _tsp(tsp) + , _histogramManager(hm) + , _transferFunction(tf) + , _memoryBudget(memoryBudget) + , _streamingBudget(streamingBudget) {} + +LocalTfBrickSelector::~LocalTfBrickSelector() {} + +bool LocalTfBrickSelector::initialize() { + return calculateBrickErrors(); +} + +void LocalTfBrickSelector::setMemoryBudget(int memoryBudget) { + _memoryBudget = memoryBudget; +} + +void LocalTfBrickSelector::setStreamingBudget(int streamingBudget) { + _streamingBudget = streamingBudget; +} + +void LocalTfBrickSelector::selectBricks(int timestep, std::vector& bricks) { + int numTimeSteps = _tsp->header().numTimesteps_; + int numBricksPerDim = _tsp->header().xNumBricks_; + + unsigned int rootNode = 0; + BrickSelection::SplitType splitType; + float rootSplitPoints = splitPoints(rootNode, splitType); + BrickSelection brickSelection = BrickSelection(numBricksPerDim, numTimeSteps, splitType, rootSplitPoints); + + std::vector priorityQueue; + std::vector leafSelections; + std::vector temporalSplitQueue; + std::vector deadEnds; + + if (splitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(brickSelection); + } else { + leafSelections.push_back(brickSelection); + } + + int memoryBudget = _memoryBudget; + int totalStreamingBudget = _streamingBudget * numTimeSteps; + int nBricksInMemory = 1; + int nStreamedBricks = 1; + + while (nBricksInMemory <= memoryBudget - 7 && priorityQueue.size() > 0) { + std::pop_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + BrickSelection bs = priorityQueue.back(); + + // TODO: handle edge case when we can only afford temporal splits or no split (only 1 spot left) + + unsigned int brickIndex = bs.brickIndex; + priorityQueue.pop_back(); + if (bs.splitType == BrickSelection::SplitType::Temporal) { + int timeSpanCenter = bs.centerT(); + unsigned int childBrickIndex; + bool pickRightTimeChild = bs.timestepInRightChild(timestep); + + // On average on the whole time period, splitting this spatial brick in two time steps + // would generate twice as much streaming. Current number of streams of this spatial brick + // is 2^nTemporalSplits over the whole time period. + int newStreams = std::pow(2, bs.nTemporalSplits); + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // Reached dead end (streaming budget would be exceeded) + deadEnds.push_back(bs); + break; + } + nStreamedBricks += newStreams; + + if (pickRightTimeChild) { + childBrickIndex = _tsp->getBstRight(brickIndex); + } else { + childBrickIndex = _tsp->getBstLeft(brickIndex); + } + + BrickSelection::SplitType childSplitType; + float childSplitPoints = splitPoints(childBrickIndex, childSplitType); + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, childSplitType, childSplitPoints); + + if (childSplitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(childSelection); + std::push_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + } else { + leafSelections.push_back(childSelection); + } + } else if (bs.splitType == BrickSelection::SplitType::Spatial) { + nBricksInMemory += 7; // Remove one and add eight. + unsigned int firstChild = _tsp->getFirstOctreeChild(brickIndex); + + // On average on the whole time period, splitting this spatial brick into eight spatial bricks + // would generate eight times as much streaming. Current number of streams of this spatial brick + // is 2^nTemporalStreams over the whole time period. + int newStreams = 7*std::pow(2, bs.nTemporalSplits); + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // Reached dead end (streaming budget would be exceeded) + // However, temporal split might be possible + if (bs.splitType != BrickSelection::SplitType::Temporal) { + bs.splitType = BrickSelection::SplitType::Temporal; + bs.splitPoints = temporalSplitPoints(bs.brickIndex); + } + if (bs.splitPoints > -1) { + temporalSplitQueue.push_back(bs); + } else { + deadEnds.push_back(bs); + } + break; + } + nStreamedBricks += newStreams; + + for (unsigned int i = 0; i < 8; i++) { + unsigned int childBrickIndex = firstChild + i; + + BrickSelection::SplitType childSplitType; + float childSplitPoints = splitPoints(childBrickIndex, childSplitType); + BrickSelection childSelection = bs.splitSpatially(i % 2, (i/2) % 2, i/4, childBrickIndex, childSplitType, childSplitPoints); + + if (childSplitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(childSelection); + std::push_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + } else { + leafSelections.push_back(childSelection); + } + } + } + } + + // Is it possible that we may stream more bricks? + if (nStreamedBricks < totalStreamingBudget) { + while (priorityQueue.size() > 0) { + BrickSelection bs = priorityQueue.back(); + if (bs.splitType != BrickSelection::SplitType::Temporal) { + bs.splitType = BrickSelection::SplitType::Temporal; + bs.splitPoints = temporalSplitPoints(bs.brickIndex); + } + priorityQueue.pop_back(); + if (bs.splitPoints > -1) { + temporalSplitQueue.push_back(bs); + std::push_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + } else { + deadEnds.push_back(bs); + } + } + + while (nStreamedBricks < totalStreamingBudget - 1 && temporalSplitQueue.size() > 0) { + std::pop_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + BrickSelection bs = temporalSplitQueue.back(); + temporalSplitQueue.pop_back(); + + unsigned int brickIndex = bs.brickIndex; + int newStreams = std::pow(2, bs.nTemporalSplits); + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // The current best choice would make us exceed the streaming budget, try next instead. + deadEnds.push_back(bs); + continue; + } + + nStreamedBricks += newStreams; + unsigned int childBrickIndex; + bool pickRightTimeChild = bs.timestepInRightChild(timestep); + + if (pickRightTimeChild) { + childBrickIndex = _tsp->getBstRight(brickIndex); + } else { + childBrickIndex = _tsp->getBstLeft(brickIndex); + } + + float childSplitPoints = temporalSplitPoints(childBrickIndex); + + if (childSplitPoints > -1) { + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, BrickSelection::SplitType::Temporal, childSplitPoints); + temporalSplitQueue.push_back(childSelection); + std::push_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + } else { + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, BrickSelection::SplitType::None, -1); + deadEnds.push_back(childSelection); + } + } + } else { + // Write selected inner nodes to brickSelection vector + for (const BrickSelection& bs : priorityQueue) { + writeSelection(bs, bricks); + } + } + + // Write selected inner nodes to brickSelection vector + for (const BrickSelection& bs : temporalSplitQueue) { + writeSelection(bs, bricks); + } + // Write dead end nodes to brickSelection vector + for (const BrickSelection& bs : deadEnds) { + writeSelection(bs, bricks); + } + // Write selected leaf nodes to brickSelection vector + for (const BrickSelection& bs : leafSelections) { + writeSelection(bs, bricks); + } + + //std::cout << "Bricks in memory: " << nBricksInMemory << "/" << _memoryBudget << "___\t\t" + // << "Streamed bricks: " << nStreamedBricks << "/" << totalStreamingBudget << std::flush << "___\r"; +} + +float LocalTfBrickSelector::temporalSplitPoints(unsigned int brickIndex) { + if (_tsp->isBstLeaf(brickIndex)) { + return -1; + } + return _brickErrors[brickIndex].temporal * 0.5; +} + +float LocalTfBrickSelector::spatialSplitPoints(unsigned int brickIndex) { + if (_tsp->isOctreeLeaf(brickIndex)) { + return -1; + } + return _brickErrors[brickIndex].spatial * 0.125; +} + +float LocalTfBrickSelector::splitPoints(unsigned int brickIndex, BrickSelection::SplitType& splitType) { + float temporalPoints = temporalSplitPoints(brickIndex); + float spatialPoints = spatialSplitPoints(brickIndex); + + float splitPoints; + + if (spatialPoints > 0 && spatialPoints > temporalPoints) { + splitPoints = spatialPoints; + splitType = BrickSelection::SplitType::Spatial; + } else if (temporalPoints > 0) { + splitPoints = temporalPoints; + splitType = BrickSelection::SplitType::Temporal; + } else { + splitPoints = -1; + splitType = BrickSelection::SplitType::None; + } + return splitPoints; +} + + +bool LocalTfBrickSelector::calculateBrickErrors() { + TransferFunction *tf = _transferFunction; + if (!tf) return false; + + size_t tfWidth = tf->width(); + if (tfWidth <= 0) return false; + + std::vector gradients(tfWidth - 1); + for (size_t offset = 0; offset < tfWidth - 1; offset++) { + glm::vec4 prevRgba = tf->sample(offset); + glm::vec4 nextRgba = tf->sample(offset + 1); + + float colorDifference = glm::distance(prevRgba, nextRgba); + float alpha = (prevRgba.w + nextRgba.w) * 0.5; + + gradients[offset] = colorDifference*alpha; + } + + unsigned int nHistograms = _tsp->numTotalNodes(); + _brickErrors = std::vector(nHistograms); + + for (unsigned int brickIndex = 0; brickIndex < nHistograms; brickIndex++) { + if (_tsp->isOctreeLeaf(brickIndex)) { + _brickErrors[brickIndex].spatial = 0.0; + } else { + const Histogram* histogram = _histogramManager->getSpatialHistogram(brickIndex); + float error = 0; + for (int i = 0; i < gradients.size(); i++) { + float x = (i + 0.5) / tfWidth; + float sample = histogram->interpolate(x); + assert(sample >= 0); + assert(gradients[i] >= 0); + error += sample * gradients[i]; + } + _brickErrors[brickIndex].spatial = error; + } + + if (_tsp->isBstLeaf(brickIndex)) { + _brickErrors[brickIndex].temporal = 0.0; + } else { + const Histogram* histogram = _histogramManager->getTemporalHistogram(brickIndex); + float error = 0; + for (int i = 0; i < gradients.size(); i++) { + float x = (i + 0.5) / tfWidth; + float sample = histogram->interpolate(x); + assert(sample >= 0); + assert(gradients[i] >= 0); + error += sample * gradients[i]; + } + _brickErrors[brickIndex].temporal = error; + } + } + + return true; +} + +int LocalTfBrickSelector::linearCoords(int x, int y, int z) { + const TSP::Header &header = _tsp->header(); + return x + (header.xNumBricks_ * y) + (header.xNumBricks_ * header.yNumBricks_ * z); +} + +void LocalTfBrickSelector::writeSelection(BrickSelection brickSelection, std::vector& bricks) { + BrickCover coveredBricks = brickSelection.cover; + for (int z = coveredBricks.lowZ; z < coveredBricks.highZ; z++) { + for (int y = coveredBricks.lowY; y < coveredBricks.highY; y++) { + for (int x = coveredBricks.lowX; x < coveredBricks.highX; x++) { + bricks[linearCoords(x, y, z)] = brickSelection.brickIndex; + } + } + } +} + + +} // namespace openspace diff --git a/modules/multiresvolume/rendering/localtfbrickselector.h b/modules/multiresvolume/rendering/localtfbrickselector.h new file mode 100644 index 0000000000..cac58a9d7e --- /dev/null +++ b/modules/multiresvolume/rendering/localtfbrickselector.h @@ -0,0 +1,78 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __LOCALTFBRICKSELECTOR_H__ +#define __LOCALTFBRICKSELECTOR_H__ + +#include +#include +#include +#include + + +namespace openspace { + +class TSP; +class LocalErrorHistogramManager; +class TransferFunction; + +class LocalTfBrickSelector : public BrickSelector { +public: + struct Error { + float spatial; + float temporal; + }; + + LocalTfBrickSelector(TSP* tsp, LocalErrorHistogramManager* hm, TransferFunction* tf, int memoryBudget, int streamingBudget); + ~LocalTfBrickSelector(); + + virtual bool initialize(); + + void selectBricks(int timestep, std::vector& bricks); + void setMemoryBudget(int memoryBudget); + void setStreamingBudget(int streamingBudget); + bool calculateBrickErrors(); + private: + + TSP* _tsp; + LocalErrorHistogramManager* _histogramManager; + TransferFunction* _transferFunction; + std::vector _brickErrors; + + float spatialSplitPoints(unsigned int brickIndex); + float temporalSplitPoints(unsigned int brickIndex); + float splitPoints(unsigned int brickIndex, BrickSelection::SplitType& splitType); + + int linearCoords(int x, int y, int z); + void writeSelection(BrickSelection coveredBricks, std::vector& bricks); + + int _memoryBudget; + int _streamingBudget; + +}; + +} // namespace openspace + +#endif // __LOCALTFBRICKSELECTOR_H__ + diff --git a/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp b/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp new file mode 100644 index 0000000000..24def3475e --- /dev/null +++ b/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp @@ -0,0 +1,158 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + + +namespace { + const std::string GlslRaycastPath = "${MODULES}/multiresvolume/shaders/raycast.glsl"; + const std::string GlslHelperPath = "${MODULES}/multiresvolume/shaders/helper.glsl"; + const std::string GlslBoundsVsPath = "${MODULES}/multiresvolume/shaders/boundsVs.glsl"; + const std::string GlslBoundsFsPath = "${MODULES}/multiresvolume/shaders/boundsFs.glsl"; +} + +namespace openspace { + +MultiresVolumeRaycaster::MultiresVolumeRaycaster(std::shared_ptr tsp, + std::shared_ptr atlasManager, + std::shared_ptr transferFunction) + : _tsp(tsp) + , _atlasManager(atlasManager) + , _transferFunction(transferFunction) + , _boundingBox(glm::vec3(1.0)) {} + +MultiresVolumeRaycaster::~MultiresVolumeRaycaster() {} + +void MultiresVolumeRaycaster::initialize() { + _boundingBox.initialize(); +} + +void MultiresVolumeRaycaster::deinitialize() { +} + +void MultiresVolumeRaycaster::renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) { + program.setUniform("modelTransform", _modelTransform); + program.setUniform("viewProjection", data.camera.viewProjectionMatrix()); + Renderable::setPscUniforms(program, data.camera, data.position); + + // Cull back face + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + // Render bounding geometry + _boundingBox.render(); +} + +void MultiresVolumeRaycaster::renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) { + // Uniforms + program.setUniform("modelTransform", _modelTransform); + program.setUniform("viewProjection", data.camera.viewProjectionMatrix()); + Renderable::setPscUniforms(program, data.camera, data.position); + + // Cull front face + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + + // Render bounding geometry + _boundingBox.render(); + + // Restore defaults + glCullFace(GL_BACK); +} + +void MultiresVolumeRaycaster::preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { + std::string timestepUniformName = "timestep" + std::to_string(data.id); + std::string stepSizeUniformName = "maxStepSize" + std::to_string(data.id); + + std::string id = std::to_string(data.id); + //program.setUniform("opacity_" + std::to_string(id), visible ? 1.0f : 0.0f); + program.setUniform("stepSizeCoefficient_" + id, _stepSizeCoefficient); + + _tfUnit = std::make_unique(); + _tfUnit->activate(); + _transferFunction->getTexture().bind(); + program.setUniform("transferFunction_" + id, _tfUnit->unitNumber()); + + _atlasUnit = std::make_unique(); + _atlasUnit->activate(); + _atlasManager->textureAtlas().bind(); + program.setUniform("textureAtlas_" + id, _atlasUnit->unitNumber()); + + + _atlasMapBinding = std::make_unique>(); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, _atlasMapBinding->bindingNumber(), _atlasManager->atlasMapBuffer()); + program.setSsboBinding("atlasMapBlock_" + id, _atlasMapBinding->bindingNumber()); + + + program.setUniform("gridType_" + id, static_cast(_tsp->header().gridType_)); + program.setUniform("maxNumBricksPerAxis_" + id, static_cast(_tsp->header().xNumBricks_)); + program.setUniform("paddedBrickDim_" + id, static_cast(_tsp->paddedBrickDim())); + + glm::size3_t size = _atlasManager->textureSize(); + glm::ivec3 atlasSize(size.x, size.y, size.z); + program.setUniform("atlasSize_" + id, atlasSize); +} + +void MultiresVolumeRaycaster::postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { + // For example: release texture units +} + +std::string MultiresVolumeRaycaster::getBoundsVsPath() const { + return GlslBoundsVsPath; +} + +std::string MultiresVolumeRaycaster::getBoundsFsPath() const { + return GlslBoundsFsPath; +} + +std::string MultiresVolumeRaycaster::getRaycastPath() const { + return GlslRaycastPath; +} + +std::string MultiresVolumeRaycaster::getHelperPath() const { + return GlslHelperPath; // no helper file +} + +void MultiresVolumeRaycaster::setModelTransform(glm::mat4 transform) { + _modelTransform = transform; +} + +void MultiresVolumeRaycaster::setStepSizeCoefficient(float stepSizeCoefficient) { + _stepSizeCoefficient = stepSizeCoefficient; +} + +} diff --git a/modules/multiresvolume/rendering/multiresvolumeraycaster.h b/modules/multiresvolume/rendering/multiresvolumeraycaster.h new file mode 100644 index 0000000000..b2241fd0fe --- /dev/null +++ b/modules/multiresvolume/rendering/multiresvolumeraycaster.h @@ -0,0 +1,97 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __MULTIRESVOLUMERAYCASTER_H__ +#define __MULTIRESVOLUMERAYCASTER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +namespace ghoul { + namespace opengl { + class Texture; + class ProgramObject; + } +} + +namespace openspace { + +class RenderData; +class RaycastData; + +class MultiresVolumeRaycaster : public VolumeRaycaster { +public: + + MultiresVolumeRaycaster(std::shared_ptr tsp, + std::shared_ptr atlasManager, + std::shared_ptr transferFunction); + + virtual ~MultiresVolumeRaycaster(); + + void initialize(); + void deinitialize(); + void renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override; + void renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override; + void preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; + void postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; + + std::string getBoundsVsPath() const override; + std::string getBoundsFsPath() const override; + std::string getRaycastPath() const override; + std::string getHelperPath() const override; + + void setModelTransform(glm::mat4 transform); + //void setTime(double time); + void setStepSizeCoefficient(float coefficient); +private: + BoxGeometry _boundingBox; + glm::mat4 _modelTransform; + float _stepSizeCoefficient; + double _time; + + std::shared_ptr _tsp; + std::shared_ptr _atlasManager; + std::shared_ptr _transferFunction; + + std::unique_ptr _tfUnit; + std::unique_ptr _atlasUnit; + std::unique_ptr < ghoul::opengl::BufferBinding> _atlasMapBinding; + + +}; // MultiresVolumeRaycaster + +} // openspace + +#endif // __MULTIRESVOLUMERAYCASTER_H__ diff --git a/modules/multiresvolume/rendering/renderablemultiresvolume.cpp b/modules/multiresvolume/rendering/renderablemultiresvolume.cpp new file mode 100644 index 0000000000..c05bd712be --- /dev/null +++ b/modules/multiresvolume/rendering/renderablemultiresvolume.cpp @@ -0,0 +1,638 @@ +/***************************************************************************************** + * * + * 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 + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + + + +namespace { + const std::string _loggerCat = "RenderableMultiresVolume"; + const std::string KeyDataSource = "Source"; + const std::string KeyHints = "Hints"; + const std::string KeyTransferFunction = "TransferFunction"; + + const std::string KeyVolumeName = "VolumeName"; + const std::string KeyBrickSelector = "BrickSelector"; + const std::string KeyStartTime = "StartTime"; + const std::string KeyEndTime = "EndTime"; + const std::string GlslHelpersPath = "${MODULES}/multiresvolume/shaders/helpers_fs.glsl"; + const std::string GlslHelperPath = "${MODULES}/multiresvolume/shaders/helper.glsl"; + const std::string GlslHeaderPath = "${MODULES}/multiresvolume/shaders/header.glsl"; + bool registeredGlslHelpers = false; +} + +namespace openspace { + +RenderableMultiresVolume::RenderableMultiresVolume (const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _transferFunction(nullptr) + , _timestep(0) + , _atlasMapSize(0) + , _tfBrickSelector(nullptr) + , _simpleTfBrickSelector(nullptr) + , _localTfBrickSelector(nullptr) + , _errorHistogramManager(nullptr) + , _histogramManager(nullptr) + , _localErrorHistogramManager(nullptr) + , _stepSizeCoefficient("stepSizeCoefficient", "Stepsize Coefficient", 1.f, 0.01f, 10.f) + , _currentTime("currentTime", "Current Time", 0, 0, 0) + , _memoryBudget("memoryBudget", "Memory Budget", 0, 0, 0) + , _streamingBudget("streamingBudget", "Streaming Budget", 0, 0, 0) + , _useGlobalTime("useGlobalTime", "Global Time", false) + , _loop("loop", "Loop", false) + , _selectorName("selector", "Brick Selector") + , _gatheringStats(false) + , _statsToFile("printStats", "Print Stats", false) + , _statsToFileName("printStatsFileName", "Stats Filename") + , _scalingExponent("scalingExponent", "Scaling Exponent", 1, -10, 20) + , _scaling("scaling", "Scaling", glm::vec3(1.0, 1.0, 1.0), glm::vec3(0.0), glm::vec3(10.0)) + , _translation("translation", "Translation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0), glm::vec3(10.0)) + , _rotation("rotation", "Euler rotation", glm::vec3(0.0, 0.0, 0.0), glm::vec3(0), glm::vec3(6.28)) +{ + std::string name; + //bool success = dictionary.getValue(constants::scenegraphnode::keyName, name); + //assert(success); + + _filename = ""; + bool success = dictionary.getValue(KeyDataSource, _filename); + if (!success) { + LERROR("Node '" << name << "' did not contain a valid '" << KeyDataSource << "'"); + return; + } + _filename = absPath(_filename); + if (_filename == "") { + return; + } + + float scalingExponent, stepSizeCoefficient; + glm::vec3 scaling, translation, rotation; + + if (dictionary.getValue("ScalingExponent", scalingExponent)) { + _scalingExponent = scalingExponent; + } + if (dictionary.getValue("Scaling", scaling)) { + _scaling = scaling; + } + if (dictionary.getValue("Translation", translation)) { + _translation = translation; + } + if (dictionary.getValue("Rotation", rotation)) { + _rotation = rotation; + } + if (dictionary.getValue("StepSizeCoefficient", stepSizeCoefficient)) { + _stepSizeCoefficient = stepSizeCoefficient; + } + + std::string startTimeString, endTimeString; + bool hasTimeData = true; + hasTimeData &= dictionary.getValue(KeyStartTime, startTimeString); + hasTimeData &= dictionary.getValue(KeyEndTime, endTimeString); + if (hasTimeData) { + _startTime = SpiceManager::ref().ephemerisTimeFromDate(startTimeString); + _endTime = SpiceManager::ref().ephemerisTimeFromDate(endTimeString); + } + if (hasTimeData) { + _loop = false; + } else { + _loop = true; + LWARNING("Node " << name << " does not provide valid time information. Viewing one image per frame."); + } + + + _transferFunction = nullptr; + _transferFunctionPath = ""; + success = dictionary.getValue(KeyTransferFunction, _transferFunctionPath); + if (!success) { + LERROR("Node '" << name << "' did not contain a valid '" << + KeyTransferFunction << "'"); + return; + } + _transferFunctionPath = absPath(_transferFunctionPath); + _transferFunction = std::make_shared(_transferFunctionPath); + + //_pscOffset = psc(glm::vec4(0.0)); + //_boxScaling = glm::vec3(1.0); + + + /*if (dictionary.hasKey(KeyBoxScaling)) { + glm::vec4 scalingVec4(_boxScaling, _w); + success = dictionary.getValue(KeyBoxScaling, scalingVec4); + if (success) { + _boxScaling = scalingVec4.xyz; + _w = scalingVec4.w; + } + else { + success = dictionary.getValue(KeyBoxScaling, _boxScaling); + if (!success) { + LERROR("Node '" << name << "' did not contain a valid '" << + KeyBoxScaling << "'"); + return; + } + } + }*/ + + //setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling)*pow(10,_w))); + + _tsp = std::make_shared(_filename); + _atlasManager = std::make_shared(_tsp.get()); + + _selectorName = "tf"; + std::string brickSelectorType; + if (dictionary.hasKey(KeyBrickSelector)) { + success = dictionary.getValue(KeyBrickSelector, brickSelectorType); + if (success) { + _selectorName = brickSelectorType; + } + } + + std::string selectorName = _selectorName; + if (selectorName == "simple") { + _selector = Selector::SIMPLE; + } else if (selectorName == "local") { + _selector = Selector::LOCAL; + } else { + _selector = Selector::TF; + } + + addProperty(_selectorName); + _selectorName.onChange([&] { + Selector s; + std::string newSelectorName = _selectorName; + if (newSelectorName == "simple") { + s = Selector::SIMPLE; + } else if (newSelectorName == "local") { + s = Selector::LOCAL; + } else if (newSelectorName == "tf") { + s = Selector::TF; + } else { + return; + } + setSelectorType(s); + }); + + addProperty(_stepSizeCoefficient); + addProperty(_useGlobalTime); + addProperty(_loop); + addProperty(_statsToFile); + addProperty(_statsToFileName); + addProperty(_scaling); + addProperty(_scalingExponent); + addProperty(_translation); + addProperty(_rotation); + + + //_brickSelector = new ShenBrickSelector(_tsp, -1, -1); +} + +RenderableMultiresVolume::~RenderableMultiresVolume() { + //OsEng.renderEngine()->aBuffer()->removeVolume(this); + + if (_tfBrickSelector) + delete _tfBrickSelector; + if (_simpleTfBrickSelector) + delete _simpleTfBrickSelector; + if (_localTfBrickSelector) + delete _localTfBrickSelector; + + if (_errorHistogramManager) + delete _errorHistogramManager; + if (_histogramManager) + delete _histogramManager; + if (_localErrorHistogramManager) + delete _localErrorHistogramManager; +} + +bool RenderableMultiresVolume::setSelectorType(Selector selector) { + _selector = selector; + switch (_selector) { + case Selector::TF: + if (!_tfBrickSelector) { + TfBrickSelector* tbs; + _errorHistogramManager = new ErrorHistogramManager(_tsp.get()); + _tfBrickSelector = tbs = new TfBrickSelector(_tsp.get(), _errorHistogramManager, _transferFunction.get(), _memoryBudget, _streamingBudget); + _transferFunction->setCallback([tbs](const TransferFunction &tf) { + tbs->calculateBrickErrors(); + }); + if (initializeSelector()) { + tbs->calculateBrickErrors(); + return true; + } + } + break; + + case Selector::SIMPLE: + if (!_simpleTfBrickSelector) { + SimpleTfBrickSelector *stbs; + _histogramManager = new HistogramManager(); + _simpleTfBrickSelector = stbs = new SimpleTfBrickSelector(_tsp.get(), _histogramManager, _transferFunction.get(), _memoryBudget, _streamingBudget); + _transferFunction->setCallback([stbs](const TransferFunction &tf) { + stbs->calculateBrickImportances(); + }); + if (initializeSelector()) { + stbs->calculateBrickImportances(); + return true; + } + } + break; + + case Selector::LOCAL: + if (!_localTfBrickSelector) { + LocalTfBrickSelector* ltbs; + _localErrorHistogramManager = new LocalErrorHistogramManager(_tsp.get()); + _localTfBrickSelector = ltbs = new LocalTfBrickSelector(_tsp.get(), _localErrorHistogramManager, _transferFunction.get(), _memoryBudget, _streamingBudget); + _transferFunction->setCallback([ltbs](const TransferFunction &tf) { + ltbs->calculateBrickErrors(); + }); + if (initializeSelector()) { + ltbs->calculateBrickErrors(); + return true; + } + } + break; + } + return false; +} + +bool RenderableMultiresVolume::initialize() { + + bool success = _tsp && _tsp->load(); + + unsigned int maxNumBricks = _tsp->header().xNumBricks_ * _tsp->header().yNumBricks_ * _tsp->header().zNumBricks_; + + unsigned int maxInitialBudget = 2048; + int initialBudget = std::min(maxInitialBudget, maxNumBricks); + + _currentTime = properties::IntProperty("currentTime", "Current Time", 0, 0, _tsp->header().numTimesteps_ - 1); + _memoryBudget = properties::IntProperty("memoryBudget", "Memory Budget", initialBudget, 0, maxNumBricks); + _streamingBudget = properties::IntProperty("streamingBudget", "Streaming Budget", initialBudget, 0, maxNumBricks); + addProperty(_currentTime); + addProperty(_memoryBudget); + addProperty(_streamingBudget); + + if (success) { + _brickIndices.resize(maxNumBricks, 0); + success &= setSelectorType(_selector); + } + + success &= _atlasManager && _atlasManager->initialize(); + + _transferFunction->update(); + + success &= isReady(); + + _raycaster = std::make_unique(_tsp, _atlasManager, _transferFunction); + _raycaster->initialize(); + + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + + std::function onChange = [&](bool enabled) { + if (enabled) { + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + } + else { + OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get()); + } + }; + + + + return success; +} + +bool RenderableMultiresVolume::deinitialize() { + _tsp = nullptr; + _transferFunction = nullptr; + return true; +} + +bool RenderableMultiresVolume::isReady() const { + return true; +} + + +bool RenderableMultiresVolume::initializeSelector() { + int nHistograms = 50; + bool success = true; + + switch (_selector) { + case Selector::TF: + if (_errorHistogramManager) { + std::stringstream cacheName; + ghoul::filesystem::File f = _filename; + cacheName << f.baseName() << "_" << nHistograms << "_errorHistograms"; + std::string cacheFilename; + cacheFilename = FileSys.cacheManager()->cachedFilename( + cacheName.str(), "", ghoul::filesystem::CacheManager::Persistent::Yes); + std::ifstream cacheFile(cacheFilename, std::ios::in | std::ios::binary); + if (cacheFile.is_open()) { + // Read histograms from cache. + cacheFile.close(); + LINFO("Loading histograms from " << cacheFilename); + success &= _errorHistogramManager->loadFromFile(cacheFilename); + } else { + // Build histograms from tsp file. + LWARNING("Failed to open " << cacheFilename); + if (success &= _errorHistogramManager->buildHistograms(nHistograms)) { + LINFO("Writing cache to " << cacheFilename); + _errorHistogramManager->saveToFile(cacheFilename); + } + } + success &= _tfBrickSelector && _tfBrickSelector->initialize(); + } + break; + + case Selector::SIMPLE: + if (_histogramManager) { + std::stringstream cacheName; + ghoul::filesystem::File f = _filename; + cacheName << f.baseName() << "_" << nHistograms << "_histograms"; + std::string cacheFilename; + cacheFilename = FileSys.cacheManager()->cachedFilename( + cacheName.str(), "", ghoul::filesystem::CacheManager::Persistent::Yes); + std::ifstream cacheFile(cacheFilename, std::ios::in | std::ios::binary); + if (cacheFile.is_open()) { + // Read histograms from cache. + cacheFile.close(); + LINFO("Loading histograms from " << cacheFilename); + success &= _histogramManager->loadFromFile(cacheFilename); + } else { + // Build histograms from tsp file. + LWARNING("Failed to open " << cacheFilename); + if (success &= _histogramManager->buildHistograms(_tsp.get(), nHistograms)) { + LINFO("Writing cache to " << cacheFilename); + _histogramManager->saveToFile(cacheFilename); + } + } + success &= _simpleTfBrickSelector && _simpleTfBrickSelector->initialize(); + } + break; + + case Selector::LOCAL: + if (_localErrorHistogramManager) { + std::stringstream cacheName; + ghoul::filesystem::File f = _filename; + cacheName << f.baseName() << "_" << nHistograms << "_localErrorHistograms"; + std::string cacheFilename; + cacheFilename = FileSys.cacheManager()->cachedFilename( + cacheName.str(), "", ghoul::filesystem::CacheManager::Persistent::Yes); + std::ifstream cacheFile(cacheFilename, std::ios::in | std::ios::binary); + if (cacheFile.is_open()) { + // Read histograms from cache. + cacheFile.close(); + LINFO("Loading histograms from " << cacheFilename); + success &= _localErrorHistogramManager->loadFromFile(cacheFilename); + } else { + // Build histograms from tsp file. + LWARNING("Failed to open " << cacheFilename); + if (success &= _localErrorHistogramManager->buildHistograms(nHistograms)) { + LINFO("Writing cache to " << cacheFilename); + _localErrorHistogramManager->saveToFile(cacheFilename); + } + } + success &= _localTfBrickSelector && _localTfBrickSelector->initialize(); + } + break; + } + + return success; +} +/* +void RenderableMultiresVolume::preResolve(ghoul::opengl::ProgramObject* program) { + RenderableVolume::preResolve(program); + + + std::stringstream ss; + ss << "opacity_" << getId(); + program->setUniform(ss.str(), visible ? 1.0f : 0.0f); + + ss.str(std::string()); + ss << "stepSizeCoefficient_" << getId(); + program->setUniform(ss.str(), _stepSizeCoefficient); + + ss.str(std::string()); + ss << "transferFunction_" << getId(); + program->setUniform(ss.str(), getTextureUnit(_transferFunction->getTexture())); + + ss.str(std::string()); + ss << "textureAtlas_" << getId(); + program->setUniform(ss.str(), getTextureUnit(_atlasManager->textureAtlas())); + + ss.str(std::string()); + ss << "atlasMapBlock_" << getId(); + program->setSsboBinding(ss.str(), getSsboBinding(_atlasManager->atlasMapBuffer())); + + ss.str(std::string()); + ss << "gridType_" << getId(); + program->setUniform(ss.str(), static_cast(_tsp->header().gridType_)); + + ss.str(std::string()); + ss << "maxNumBricksPerAxis_" << getId(); + program->setUniform(ss.str(), static_cast(_tsp->header().xNumBricks_)); + + ss.str(std::string()); + ss << "paddedBrickDim_" << getId(); + program->setUniform(ss.str(), static_cast(_tsp->paddedBrickDim())); + + ss.str(std::string()); + ss << "atlasSize_" << getId(); + glm::size3_t size = _atlasManager->textureSize(); + glm::ivec3 atlasSize(size.x, size.y, size.z); + program->setUniform(ss.str(), atlasSize); + + _timestep++; +} +*/ +/* +std::vector RenderableMultiresVolume::getTextures() { + std::vector textures{_transferFunction->getTexture(), _atlasManager->textureAtlas()}; + return textures; +} + +std::vector RenderableMultiresVolume::getBuffers() { + std::vector buffers{_atlasManager->atlasMapBuffer()}; + return buffers; +}*/ + +void RenderableMultiresVolume::update(const UpdateData& data) { + _timestep++; + _time = data.time; + + if (_gatheringStats) { + std::chrono::system_clock::time_point frameEnd = std::chrono::system_clock::now(); + std::chrono::duration frameDuration = frameEnd - _frameStart; + + // Make sure that the directory exists + ghoul::filesystem::File file(_statsFileName); + ghoul::filesystem::Directory directory(file.directoryName()); + FileSys.createDirectory(directory, ghoul::filesystem::FileSystem::Recursive::Yes); + + std::ofstream ofs(_statsFileName, std::ofstream::out); + + ofs << frameDuration.count() << " " + << _selectionDuration.count() << " " + << _uploadDuration.count() << " " + << _nUsedBricks << " " + << _nStreamedBricks << " " + << _nDiskReads; + + ofs.close(); + + _gatheringStats = false; + } + if (_statsToFile) { + // Start frame timer + _frameStart = std::chrono::system_clock::now(); + _statsFileName = _statsToFileName; + + _gatheringStats = true; + _statsToFile = false; + } + + + int numTimesteps = _tsp->header().numTimesteps_; + int currentTimestep; + bool visible = true; + if (_loop) { + currentTimestep = _timestep % numTimesteps; + } + else if (_useGlobalTime) { + double t = (_time - _startTime) / (_endTime - _startTime); + currentTimestep = t * numTimesteps; + visible = currentTimestep >= 0 && currentTimestep < numTimesteps; + } + else { + currentTimestep = _currentTime; + } + + if (visible) { + + std::chrono::system_clock::time_point selectionStart; + if (_gatheringStats) { + selectionStart = std::chrono::system_clock::now(); + } + + switch (_selector) { + case Selector::TF: + if (_tfBrickSelector) { + _tfBrickSelector->setMemoryBudget(_memoryBudget); + _tfBrickSelector->setStreamingBudget(_streamingBudget); + _tfBrickSelector->selectBricks(currentTimestep, _brickIndices); + } + break; + case Selector::SIMPLE: + if (_simpleTfBrickSelector) { + _simpleTfBrickSelector->setMemoryBudget(_memoryBudget); + _simpleTfBrickSelector->setStreamingBudget(_streamingBudget); + _simpleTfBrickSelector->selectBricks(currentTimestep, _brickIndices); + } + break; + case Selector::LOCAL: + if (_localTfBrickSelector) { + _localTfBrickSelector->setMemoryBudget(_memoryBudget); + _localTfBrickSelector->setStreamingBudget(_streamingBudget); + _localTfBrickSelector->selectBricks(currentTimestep, _brickIndices); + } + break; + } + + std::chrono::system_clock::time_point uploadStart; + if (_gatheringStats) { + std::chrono::system_clock::time_point selectionEnd = std::chrono::system_clock::now(); + _selectionDuration = selectionEnd - selectionStart; + uploadStart = selectionEnd; + } + + _atlasManager->updateAtlas(AtlasManager::EVEN, _brickIndices); + + if (_gatheringStats) { + std::chrono::system_clock::time_point uploadEnd = std::chrono::system_clock::now(); + _uploadDuration = uploadEnd - uploadStart; + _nDiskReads = _atlasManager->getNumDiskReads(); + _nUsedBricks = _atlasManager->getNumUsedBricks(); + _nStreamedBricks = _atlasManager->getNumStreamedBricks(); + } + } + + if (_raycaster) { + + glm::mat4 transform = glm::translate(glm::mat4(1.0), static_cast(_translation) * std::pow(10.0f, static_cast(_scalingExponent))); + glm::vec3 eulerRotation = static_cast(_rotation); + transform = glm::rotate(transform, eulerRotation.x, glm::vec3(1, 0, 0)); + transform = glm::rotate(transform, eulerRotation.y, glm::vec3(0, 1, 0)); + transform = glm::rotate(transform, eulerRotation.z, glm::vec3(0, 0, 1)); + transform = glm::scale(transform, static_cast(_scaling) * std::pow(10.0f, static_cast(_scalingExponent))); + + + _raycaster->setStepSizeCoefficient(_stepSizeCoefficient); + _raycaster->setModelTransform(transform); + //_raycaster->setTime(data.time); + } + +} + +void RenderableMultiresVolume::render(const RenderData& data, RendererTasks& tasks) { + RaycasterTask task{ _raycaster.get(), data }; + tasks.raycasterTasks.push_back(task); +} + +} // namespace openspace diff --git a/modules/multiresvolume/rendering/renderablemultiresvolume.h b/modules/multiresvolume/rendering/renderablemultiresvolume.h new file mode 100644 index 0000000000..bf8f23939e --- /dev/null +++ b/modules/multiresvolume/rendering/renderablemultiresvolume.h @@ -0,0 +1,159 @@ +/***************************************************************************************** + * * + * 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 __RENDERABLEMULTIRESVOLUME_H__ +#define __RENDERABLEMULTIRESVOLUME_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Forward declare to minimize dependencies +namespace ghoul { + namespace filesystem { + class File; + } + namespace opengl { + class ProgramObject; + class Texture; + } +} + +namespace openspace { +// Forward declare +class TSP; +class AtlasManager; +class BrickSelector; +class TfBrickSelector; +class SimpleTfBrickSelector; +class LocalTfBrickSelector; +class HistogramManager; +class ErrorHistogramManager; +class LocalErrorHistogramManager; + +class RenderableMultiresVolume : public Renderable { + + + + +public: + RenderableMultiresVolume(const ghoul::Dictionary& dictionary); + ~RenderableMultiresVolume(); + + enum Selector {TF, SIMPLE, LOCAL}; + + bool setSelectorType(Selector selector); + bool initializeSelector(); + + bool initialize() override; + bool deinitialize() override; + + bool isReady() const override; + + virtual void update(const UpdateData& data) override; + virtual void RenderableMultiresVolume::render(const RenderData& data, RendererTasks& tasks); + //virtual void preResolve(ghoul::opengl::ProgramObject* program) override; + //virtual std::string getHeaderPath() override; + //virtual std::string getHelperPath() override; + //virtual std::vector getTextures() override; + //virtual std::vector getBuffers() override; + +private: + double _time; + double _startTime; + double _endTime; + + properties::BoolProperty _useGlobalTime; + properties::BoolProperty _loop; + properties::IntProperty _currentTime; // used to vary time, if not using global time nor looping + properties::IntProperty _memoryBudget; + properties::IntProperty _streamingBudget; + properties::FloatProperty _stepSizeCoefficient; + properties::StringProperty _selectorName; + properties::BoolProperty _statsToFile; + properties::StringProperty _statsToFileName; + + // Stats timers + std::string _statsFileName; + bool _gatheringStats; + std::chrono::system_clock::time_point _frameStart; + std::chrono::duration _selectionDuration; + std::chrono::duration _uploadDuration; + unsigned int _nDiskReads; + unsigned int _nUsedBricks; + unsigned int _nStreamedBricks; + + int _timestep; + + std::string _filename; + + std::string _transferFunctionName; + std::string _volumeName; + + std::string _transferFunctionPath; + + std::shared_ptr _transferFunction; + + float _spatialTolerance; + float _temporalTolerance; + + std::shared_ptr _tsp; + std::vector _brickIndices; + int _atlasMapSize; + + std::shared_ptr _atlasManager; + + std::unique_ptr _raycaster; + + TfBrickSelector* _tfBrickSelector; + SimpleTfBrickSelector* _simpleTfBrickSelector; + LocalTfBrickSelector* _localTfBrickSelector; + + Selector _selector; + + HistogramManager* _histogramManager; + ErrorHistogramManager* _errorHistogramManager; + LocalErrorHistogramManager* _localErrorHistogramManager; + + float _w; + PowerScaledCoordinate _pscOffset; + + properties::IntProperty _scalingExponent; + properties::Vec3Property _translation; + properties::Vec3Property _rotation; + properties::Vec3Property _scaling; + +}; + +} // namespace openspace + +#endif // __RENDERABLEMULTIRESVOLUME_H__ diff --git a/modules/multiresvolume/rendering/shenbrickselector.cpp b/modules/multiresvolume/rendering/shenbrickselector.cpp new file mode 100644 index 0000000000..8f6e726887 --- /dev/null +++ b/modules/multiresvolume/rendering/shenbrickselector.cpp @@ -0,0 +1,134 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 + +namespace { + const std::string _loggerCat = "ShenBrickSelector"; +} + +namespace openspace { + +ShenBrickSelector::ShenBrickSelector(TSP* tsp, float spatialTolerance, float temporalTolerance) + : _tsp(tsp) + , _spatialTolerance(spatialTolerance) + , _temporalTolerance(temporalTolerance) {} + +ShenBrickSelector::~ShenBrickSelector() { + +} + +void ShenBrickSelector::setSpatialTolerance(float spatialTolerance) { + _spatialTolerance = spatialTolerance; +} + +void ShenBrickSelector::setTemporalTolerance(float temporalTolerance) { + _temporalTolerance = temporalTolerance; +} + +void ShenBrickSelector::selectBricks(int timestep, std::vector& bricks) { + int numTimeSteps = _tsp->header().numTimesteps_; + BrickCover coveredBricks(_tsp->header().xNumBricks_); + selectBricks(timestep, 0, 0, 0, numTimeSteps, coveredBricks, bricks); +} + +/** + * Traverse the Octree in the BST root + */ +void ShenBrickSelector::traverseOT(int timestep, unsigned int brickIndex, BrickCover coveredBricks, std::vector& bricks) { + unsigned int firstChild = _tsp->getFirstOctreeChild(brickIndex); + int numTimeSteps = _tsp->header().numTimesteps_; + for (unsigned int i = 0; i < 8; i++) { + unsigned int child = firstChild + i; + BrickCover cover = coveredBricks.split(i % 2, (i/2) % 2, (i/4)); + selectBricks(timestep, child, child, 0, numTimeSteps, cover, bricks); + } +} + +void ShenBrickSelector::traverseBST(int timestep, + unsigned int brickIndex, + unsigned int bstRootBrickIndex, + int timeSpanStart, + int timeSpanEnd, + BrickCover coveredBricks, + std::vector& bricks) { + + + int timeSpanCenter = timeSpanStart + (timeSpanEnd - timeSpanStart) / 2; + unsigned int bstChild; + if (timestep <= timeSpanCenter) { + bstChild = _tsp->getBstLeft(brickIndex); + timeSpanEnd = timeSpanCenter; + } else { + bstChild = _tsp->getBstRight(brickIndex); + timeSpanStart = timeSpanCenter; + } + selectBricks(timestep, bstChild, bstRootBrickIndex, timeSpanStart, timeSpanEnd, coveredBricks, bricks); +} + +void ShenBrickSelector::selectBricks(int timestep, + unsigned int brickIndex, + unsigned int bstRootBrickIndex, + int timeSpanStart, + int timeSpanEnd, + BrickCover coveredBricks, + std::vector& bricks) { + + if (_tsp->getTemporalError(brickIndex) <= _temporalTolerance) { + if (_tsp->isOctreeLeaf(bstRootBrickIndex)) { + selectCover(coveredBricks, brickIndex, bricks); + } else if (_tsp->getSpatialError(brickIndex) <= _spatialTolerance) { + selectCover(coveredBricks, brickIndex, bricks); + } else if (_tsp->isBstLeaf(brickIndex)) { + traverseOT(timestep, bstRootBrickIndex, coveredBricks, bricks); + } else { + traverseBST(timestep, brickIndex, bstRootBrickIndex, timeSpanStart, timeSpanEnd, coveredBricks, bricks); + } + } else if (_tsp->isBstLeaf(brickIndex)) { + if (_tsp->isOctreeLeaf(bstRootBrickIndex)) { + selectCover(coveredBricks, brickIndex, bricks); + } else { + traverseOT(timestep, bstRootBrickIndex, coveredBricks, bricks); + } + } else { + traverseBST(timestep, brickIndex, bstRootBrickIndex, timeSpanStart, timeSpanEnd, coveredBricks, bricks); + } +} + +int ShenBrickSelector::linearCoords(int x, int y, int z) { + const TSP::Header &header = _tsp->header(); + return x + (header.xNumBricks_ * y) + (header.xNumBricks_ * header.yNumBricks_ * z); +} + +void ShenBrickSelector::selectCover(BrickCover coveredBricks, unsigned int brickIndex, std::vector& bricks) { + for (int z = coveredBricks.lowZ; z < coveredBricks.highZ; z++) { + for (int y = coveredBricks.lowY; y < coveredBricks.highY; y++) { + for (int x = coveredBricks.lowX; x < coveredBricks.highX; x++) { + bricks[linearCoords(x, y, z)] = brickIndex; + } + } + } +} + +} // namespace openspace diff --git a/modules/multiresvolume/rendering/shenbrickselector.h b/modules/multiresvolume/rendering/shenbrickselector.h new file mode 100644 index 0000000000..99bcb252f7 --- /dev/null +++ b/modules/multiresvolume/rendering/shenbrickselector.h @@ -0,0 +1,77 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __SHENBRICKSELECTOR_H__ +#define __SHENBRICKSELECTOR_H__ + +#include +#include +#include +#include + +namespace openspace { + + +class ShenBrickSelector : public BrickSelector { +public: + ShenBrickSelector(TSP* tsp, float spatialTolerance, float temporalTolerance); + ~ShenBrickSelector(); + void setSpatialTolerance(float spatialTolerance); + void setTemporalTolerance(float temporalTolerance); + void selectBricks(int timestep, + std::vector& bricks); +private: + TSP* _tsp; + float _spatialTolerance; + float _temporalTolerance; + + void traverseOT(int timestep, + unsigned int brickIndex, + BrickCover coveredBricks, + std::vector& bricks); + + void traverseBST(int timestep, + unsigned int brickIndex, + unsigned int bstRootBrickIndex, + int timeSpanStart, + int timeSpanEnd, + BrickCover coveredBricks, + std::vector& bricks); + + void selectBricks(int timestep, + unsigned int brickIndex, + unsigned int bstRootBrickIndex, + int timeSpanStart, + int timeSpanEnd, + BrickCover coveredBricks, + std::vector& bricks); + + int linearCoords(int x, int y, int z); + + void selectCover(BrickCover coveredBricks, unsigned int brickIndex, std::vector& bricks); +}; + +} // namespace openspace + +#endif // __SHENBRICKSELECTOR_H__ diff --git a/modules/multiresvolume/rendering/simpletfbrickselector.cpp b/modules/multiresvolume/rendering/simpletfbrickselector.cpp new file mode 100644 index 0000000000..bea62f22a9 --- /dev/null +++ b/modules/multiresvolume/rendering/simpletfbrickselector.cpp @@ -0,0 +1,337 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 +#include +#include +#include +#include +#include +#include +#include + +namespace { + const std::string _loggerCat = "SimpleTfBrickSelector"; +} + +namespace openspace { + + SimpleTfBrickSelector::SimpleTfBrickSelector(TSP* tsp, HistogramManager* hm, TransferFunction* tf, int memoryBudget, int streamingBudget) + : _tsp(tsp) + , _histogramManager(hm) + , _transferFunction(tf) + , _memoryBudget(memoryBudget) + , _streamingBudget(streamingBudget) {} + +SimpleTfBrickSelector::~SimpleTfBrickSelector() {} + +bool SimpleTfBrickSelector::initialize() { + return true; +} + +void SimpleTfBrickSelector::setMemoryBudget(int memoryBudget) { + _memoryBudget = memoryBudget; +} + +void SimpleTfBrickSelector::setStreamingBudget(int streamingBudget) { + _streamingBudget = streamingBudget; +} + +void SimpleTfBrickSelector::selectBricks(int timestep, std::vector& bricks) { + int numTimeSteps = _tsp->header().numTimesteps_; + int numBricksPerDim = _tsp->header().xNumBricks_; + + unsigned int rootNode = 0; + BrickSelection::SplitType splitType; + float rootSplitPoints = splitPoints(rootNode, splitType); + + BrickSelection brickSelection = BrickSelection(numBricksPerDim, numTimeSteps, splitType, rootSplitPoints); + + std::vector priorityQueue; + std::vector leafSelections; + std::vector temporalSplitQueue; + std::vector deadEnds; + + if (splitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(brickSelection); + } else { + leafSelections.push_back(brickSelection); + } + + int memoryBudget = _memoryBudget; + int totalStreamingBudget = _streamingBudget * numTimeSteps; + int nBricksInMemory = 1; + int nStreamedBricks = 1; + + while (nBricksInMemory <= memoryBudget - 7 && priorityQueue.size() > 0) { + std::pop_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + BrickSelection bs = priorityQueue.back(); + + // TODO: handle edge case when we can only afford temporal splits or no split (only 1 spot left) + + unsigned int brickIndex = bs.brickIndex; + priorityQueue.pop_back(); + if (bs.splitType == BrickSelection::SplitType::Temporal) { + unsigned int childBrickIndex; + bool pickRightTimeChild = bs.timestepInRightChild(timestep); + + // On average on the whole time period, splitting this spatial brick in two time steps + // would generate twice as much streaming. Current number of streams of this spatial brick + // is 2^nTemporalSplits over the whole time period. + int newStreams = std::pow(2, bs.nTemporalSplits); + + // Refining this one more step would require the double amount of streams + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // Reached dead end (streaming budget would be exceeded) + deadEnds.push_back(bs); + break; + } + nStreamedBricks += newStreams; + + if (pickRightTimeChild) { + childBrickIndex = _tsp->getBstRight(brickIndex); + } else { + childBrickIndex = _tsp->getBstLeft(brickIndex); + } + + BrickSelection::SplitType childSplitType; + float childSplitPoints = splitPoints(childBrickIndex, childSplitType); + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, childSplitType, childSplitPoints); + + if (childSplitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(childSelection); + std::push_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + } else { + leafSelections.push_back(childSelection); + } + } else if (bs.splitType == BrickSelection::SplitType::Spatial) { + nBricksInMemory += 7; // Remove one and add eight. + unsigned int firstChild = _tsp->getFirstOctreeChild(brickIndex); + + // On average on the whole time period, splitting this spatial brick into eight spatial bricks + // would generate eight times as much streaming. Current number of streams of this spatial brick + // is 2^nTemporalStreams over the whole time period. + int newStreams = 7*std::pow(2, bs.nTemporalSplits); + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // Reached dead end (streaming budget would be exceeded) + // However, temporal split might be possible + if (bs.splitType != BrickSelection::SplitType::Temporal) { + bs.splitType = BrickSelection::SplitType::Temporal; + bs.splitPoints = temporalSplitPoints(bs.brickIndex); + } + if (bs.splitPoints > -1) { + temporalSplitQueue.push_back(bs); + } else { + deadEnds.push_back(bs); + } + break; + } + nStreamedBricks += newStreams; + + for (unsigned int i = 0; i < 8; i++) { + unsigned int childBrickIndex = firstChild + i; + + BrickSelection::SplitType childSplitType; + float childSplitPoints = splitPoints(childBrickIndex, childSplitType); + BrickSelection childSelection = bs.splitSpatially(i % 2, (i/2) % 2, i/4, childBrickIndex, childSplitType, childSplitPoints); + + if (childSplitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(childSelection); + std::push_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + } else { + leafSelections.push_back(childSelection); + } + } + } + } + + if (nStreamedBricks < totalStreamingBudget) { + while (priorityQueue.size() > 0) { + BrickSelection bs = priorityQueue.back(); + if (bs.splitType != BrickSelection::SplitType::Temporal) { + bs.splitType = BrickSelection::SplitType::Temporal; + bs.splitPoints = temporalSplitPoints(bs.brickIndex); + } + priorityQueue.pop_back(); + if (bs.splitPoints > -1) { + temporalSplitQueue.push_back(bs); + std::push_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + } else { + deadEnds.push_back(bs); + } + } + + // Keep splitting until it's not possible anymore + while (nStreamedBricks < totalStreamingBudget - 1 && temporalSplitQueue.size() > 0) { + std::pop_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + BrickSelection bs = temporalSplitQueue.back(); + temporalSplitQueue.pop_back(); + + unsigned int brickIndex = bs.brickIndex; + int newStreams = std::pow(2, bs.nTemporalSplits); + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // The current best choice would make us exceed the streaming budget, try next instead. + deadEnds.push_back(bs); + continue; + } + + nStreamedBricks += newStreams; + unsigned int childBrickIndex; + bool pickRightTimeChild = bs.timestepInRightChild(timestep); + + if (pickRightTimeChild) { + childBrickIndex = _tsp->getBstRight(brickIndex); + } else { + childBrickIndex = _tsp->getBstLeft(brickIndex); + } + + float childSplitPoints = temporalSplitPoints(childBrickIndex); + + if (childSplitPoints > -1) { + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, BrickSelection::SplitType::Temporal, childSplitPoints); + temporalSplitQueue.push_back(childSelection); + std::push_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + } else { + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, BrickSelection::SplitType::None, -1); + deadEnds.push_back(childSelection); + } + } + } else { + // Write selected inner nodes to brickSelection vector + for (const BrickSelection& bs : priorityQueue) { + writeSelection(bs, bricks); + } + } + + // Write selected inner nodes to brickSelection vector + for (const BrickSelection& bs : temporalSplitQueue) { + writeSelection(bs, bricks); + } + for (const BrickSelection& bs : deadEnds) { + writeSelection(bs, bricks); + } + // Write selected leaf nodes to brickSelection vector + for (const BrickSelection& bs : leafSelections) { + writeSelection(bs, bricks); + } + + //std::cout << "Bricks in memory: " << nBricksInMemory << "/" << _memoryBudget << "___\t\t" + // << "Streamed bricks: " << nStreamedBricks << "/" << totalStreamingBudget << std::flush << "___\r"; +} + +float SimpleTfBrickSelector::temporalSplitPoints(unsigned int brickIndex) { + if (_tsp->isBstLeaf(brickIndex)) { + return -1; + } + return _brickImportances[brickIndex] * 0.5; +} + +float SimpleTfBrickSelector::spatialSplitPoints(unsigned int brickIndex) { + if (_tsp->isOctreeLeaf(brickIndex)) { + return -1; + } + return _brickImportances[brickIndex] * 0.125; +} + +float SimpleTfBrickSelector::splitPoints(unsigned int brickIndex, BrickSelection::SplitType& splitType) { + float temporalPoints = temporalSplitPoints(brickIndex); + float spatialPoints = spatialSplitPoints(brickIndex); + float splitPoints; + + if (spatialPoints > 0 && spatialPoints > temporalPoints) { + splitPoints = spatialPoints; + splitType = BrickSelection::SplitType::Spatial; + } else if (temporalPoints > 0) { + splitPoints = temporalPoints; + splitType = BrickSelection::SplitType::Temporal; + } else { + splitPoints = -1; + splitType = BrickSelection::SplitType::None; + } + + return splitPoints; +} + + +bool SimpleTfBrickSelector::calculateBrickImportances() { + TransferFunction *tf = _transferFunction; + if (!tf) return false; + + float tfWidth = tf->width(); + if (tfWidth <= 0) return false; + + /* std::vector gradients(tfWidth - 1); + for (size_t offset = 0; offset < tfWidth - 1; offset++) { + glm::vec4 prevRgba = tf->sample(offset); + glm::vec4 nextRgba = tf->sample(offset + 1); + + float colorDifference = glm::distance(prevRgba, nextRgba); + float alpha = (prevRgba.w + nextRgba.w) * 0.5; + + gradients[offset] = colorDifference*alpha; + }*/ + + unsigned int nHistograms = _tsp->numTotalNodes(); + _brickImportances = std::vector(nHistograms); + + for (unsigned int brickIndex = 0; brickIndex < nHistograms; brickIndex++) { + const Histogram* histogram = _histogramManager->getHistogram(brickIndex); + if (!histogram->isValid()) { + return false; + } + + float dotProduct = 0; + for (int i = 0; i < tf->width(); i++) { + float x = float(i) / tfWidth; + float sample = histogram->interpolate(x); + + assert(sample >= 0); + dotProduct += sample * tf->sample(i).w; + } + _brickImportances[brickIndex] = dotProduct; + } + + LINFO("Updated brick importances"); + + return true; +} + +int SimpleTfBrickSelector::linearCoords(int x, int y, int z) { + const TSP::Header &header = _tsp->header(); + return x + (header.xNumBricks_ * y) + (header.xNumBricks_ * header.yNumBricks_ * z); +} + +void SimpleTfBrickSelector::writeSelection(BrickSelection brickSelection, std::vector& bricks) { + BrickCover coveredBricks = brickSelection.cover; + for (int z = coveredBricks.lowZ; z < coveredBricks.highZ; z++) { + for (int y = coveredBricks.lowY; y < coveredBricks.highY; y++) { + for (int x = coveredBricks.lowX; x < coveredBricks.highX; x++) { + bricks[linearCoords(x, y, z)] = brickSelection.brickIndex; + } + } + } +} + + +} // namespace openspace diff --git a/modules/multiresvolume/rendering/simpletfbrickselector.h b/modules/multiresvolume/rendering/simpletfbrickselector.h new file mode 100644 index 0000000000..0dadfa90d6 --- /dev/null +++ b/modules/multiresvolume/rendering/simpletfbrickselector.h @@ -0,0 +1,71 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __SIMPLETFBRICKSELECTOR_H__ +#define __SIMPLETFBRICKSELECTOR_H__ + +#include +#include +#include +#include + + +namespace openspace { + +class TSP; +class HistogramManager; +class TransferFunction; + +class SimpleTfBrickSelector : public BrickSelector { +public: + SimpleTfBrickSelector(TSP* tsp, HistogramManager* hm, TransferFunction* tf, int memoryBudget, int streamingBudget); + ~SimpleTfBrickSelector(); + + virtual bool initialize(); + + void selectBricks(int timestep, std::vector& bricks); + void setMemoryBudget(int memoryBudget); + void setStreamingBudget(int streamingBudget); + bool calculateBrickImportances(); + private: + + TSP* _tsp; + HistogramManager* _histogramManager; + TransferFunction* _transferFunction; + std::vector _brickImportances; + float spatialSplitPoints(unsigned int brickIndex); + float temporalSplitPoints(unsigned int brickIndex); + float splitPoints(unsigned int brickIndex, BrickSelection::SplitType& splitType); + + int linearCoords(int x, int y, int z); + void writeSelection(BrickSelection coveredBricks, std::vector& bricks); + + int _memoryBudget; + int _streamingBudget; +}; + +} // namespace openspace + +#endif // __SIMPLETFBRICKSELECTOR_H__ + diff --git a/modules/multiresvolume/rendering/tfbrickselector.cpp b/modules/multiresvolume/rendering/tfbrickselector.cpp new file mode 100644 index 0000000000..dfc53f4cb9 --- /dev/null +++ b/modules/multiresvolume/rendering/tfbrickselector.cpp @@ -0,0 +1,395 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 +#include +#include +#include +#include +#include +#include + +namespace { + const std::string _loggerCat = "TfBrickSelector"; +} + +namespace openspace { + +TfBrickSelector::TfBrickSelector(TSP* tsp, ErrorHistogramManager* hm, TransferFunction* tf, int memoryBudget, int streamingBudget) + : _tsp(tsp) + , _histogramManager(hm) + , _transferFunction(tf) + , _memoryBudget(memoryBudget) + , _streamingBudget(streamingBudget) {} + +TfBrickSelector::~TfBrickSelector() {} + +bool TfBrickSelector::initialize() { + return calculateBrickErrors(); +} + +void TfBrickSelector::setMemoryBudget(int memoryBudget) { + _memoryBudget = memoryBudget; +} + +void TfBrickSelector::setStreamingBudget(int streamingBudget) { + _streamingBudget = streamingBudget; +} + +void TfBrickSelector::selectBricks(int timestep, std::vector& bricks) { + int numTimeSteps = _tsp->header().numTimesteps_; + int numBricksPerDim = _tsp->header().xNumBricks_; + + unsigned int rootNode = 0; + BrickSelection::SplitType splitType; + float rootSplitPoints = splitPoints(rootNode, splitType); + + + BrickSelection brickSelection = BrickSelection(numBricksPerDim, numTimeSteps, splitType, rootSplitPoints); + + std::vector priorityQueue; + std::vector leafSelections; + std::vector temporalSplitQueue; + std::vector deadEnds; + + if (splitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(brickSelection); + } else { + leafSelections.push_back(brickSelection); + } + + int memoryBudget = _memoryBudget; + int totalStreamingBudget = _streamingBudget * numTimeSteps; + int nBricksInMemory = 1; + int nStreamedBricks = 1; + + // First loop: While neither the memory nor the streaming budget is reached, + // try to optimize for visual quality vs memory. + + while (nBricksInMemory <= memoryBudget - 7 && priorityQueue.size() > 0) { + + std::pop_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + + BrickSelection bs = priorityQueue.back(); + unsigned int brickIndex = bs.brickIndex; + priorityQueue.pop_back(); + + // TODO: handle edge case when we can only afford temporal splits or no split (only 1 spot left) + if (bs.splitType == BrickSelection::SplitType::Temporal) { + unsigned int childBrickIndex; + bool pickRightTimeChild = bs.timestepInRightChild(timestep); + // assert(!pickRightTimeChild && "picked right child"); + + // On average on the whole time period, splitting this spatial brick in two time steps + // would generate twice as much streaming. Current number of streams of this spatial brick + // is 2^nTemporalSplits over the whole time period. + + int newStreams = std::pow(2, bs.nTemporalSplits); + //std::cout << "preparing for " << newStreams << " new streams" << std::endl; + + // Refining this one more step would require the double amount of streams + if (nStreamedBricks + newStreams > totalStreamingBudget) { + //std::cout << "Reached streaming budget when splitting temporally! Breaking" << std::endl; + // Reached dead end (streaming budget would be exceeded) + deadEnds.push_back(bs); + break; + } + nStreamedBricks += newStreams; + + if (pickRightTimeChild) { + childBrickIndex = _tsp->getBstRight(brickIndex); + } else { + childBrickIndex = _tsp->getBstLeft(brickIndex); + } + + BrickSelection::SplitType childSplitType; + float childSplitPoints = splitPoints(childBrickIndex, childSplitType); + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, childSplitType, childSplitPoints); + if (childSplitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(childSelection); + std::push_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + } else { + leafSelections.push_back(childSelection); + } + } else if (bs.splitType == BrickSelection::SplitType::Spatial) { + nBricksInMemory += 7; // Remove one and add eight. + unsigned int firstChild = _tsp->getFirstOctreeChild(brickIndex); + + // On average on the whole time period, splitting this spatial brick into eight spatial bricks + // would generate eight times as much streaming. Current number of streams of this spatial brick + // is 2^nTemporalStreams over the whole time period. + int newStreams = 7*std::pow(2, bs.nTemporalSplits); + + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // Reached dead end (streaming budget would be exceeded) + // However, temporal split might be possible + //std::cout << "Reached streaming budget when splitting spatially! Breaking" << std::endl; + if (bs.splitType != BrickSelection::SplitType::Temporal) { + bs.splitType = BrickSelection::SplitType::Temporal; + bs.splitPoints = temporalSplitPoints(bs.brickIndex); + } + if (bs.splitPoints > -1) { + temporalSplitQueue.push_back(bs); + } else { + deadEnds.push_back(bs); + } + break; + } + nStreamedBricks += newStreams; + + for (unsigned int i = 0; i < 8; i++) { + unsigned int childBrickIndex = firstChild + i; + + BrickSelection::SplitType childSplitType; + float childSplitPoints = splitPoints(childBrickIndex, childSplitType); + //std::cout << "Splitting spatially." << std::endl; + BrickSelection childSelection = bs.splitSpatially(i % 2, (i/2) % 2, i/4, childBrickIndex, childSplitType, childSplitPoints); + + if (childSplitType != BrickSelection::SplitType::None) { + priorityQueue.push_back(childSelection); + std::push_heap(priorityQueue.begin(), priorityQueue.end(), BrickSelection::compareSplitPoints); + } else { + leafSelections.push_back(childSelection); + } + } + } + } + + if (nBricksInMemory <= memoryBudget - 7) { + //std::cout << "memory budget not reached. " << nBricksInMemory << " out of " << memoryBudget << std::endl; + } + + // Is it possible that we may stream more bricks? + if (nStreamedBricks < totalStreamingBudget - 1) { + //std::cout << "streaming budget not reached. " << nStreamedBricks << " out of " << totalStreamingBudget << std::endl; + //std::cout << "there are " << priorityQueue.size() << " elements left in priority queue." << std::endl; + + while (priorityQueue.size() > 0) { + BrickSelection bs = priorityQueue.back(); + if (bs.splitType != BrickSelection::SplitType::Temporal) { + bs.splitType = BrickSelection::SplitType::Temporal; + bs.splitPoints = temporalSplitPoints(bs.brickIndex); + } + priorityQueue.pop_back(); + if (bs.splitPoints > -1) { + temporalSplitQueue.push_back(bs); + std::push_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + } else { + deadEnds.push_back(bs); + } + } + + // Keep splitting until it's not possible anymore + while (nStreamedBricks < totalStreamingBudget - 1 && temporalSplitQueue.size() > 0) { + std::pop_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + BrickSelection bs = temporalSplitQueue.back(); + temporalSplitQueue.pop_back(); + + unsigned int brickIndex = bs.brickIndex; + int newStreams = std::pow(2, bs.nTemporalSplits); + if (nStreamedBricks + newStreams > totalStreamingBudget) { + // The current best choice would make us exceed the streaming budget, try next instead. + deadEnds.push_back(bs); + //std::cout << "Dead end trying to split " << brickIndex << ". Streamed would be " << (nStreamedBricks + newStreams) << std::endl; + continue; + } + + nStreamedBricks += newStreams; + unsigned int childBrickIndex; + bool pickRightTimeChild = bs.timestepInRightChild(timestep); + + if (pickRightTimeChild) { + childBrickIndex = _tsp->getBstRight(brickIndex); + } else { + childBrickIndex = _tsp->getBstLeft(brickIndex); + } + + float childSplitPoints = temporalSplitPoints(childBrickIndex); + + if (childSplitPoints > -1) { + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, BrickSelection::SplitType::Temporal, childSplitPoints); + temporalSplitQueue.push_back(childSelection); + std::push_heap(temporalSplitQueue.begin(), temporalSplitQueue.end(), BrickSelection::compareSplitPoints); + } else { + BrickSelection childSelection = bs.splitTemporally(pickRightTimeChild, childBrickIndex, BrickSelection::SplitType::None, -1); + deadEnds.push_back(childSelection); + } + } + } else { + // Write selected inner nodes to brickSelection vector + //std::cout << "priority queue: " << priorityQueue.size() << std::endl; + for (const BrickSelection& bs : priorityQueue) { + writeSelection(bs, bricks); + } + } + + //std::cout << "temporal split queue: " << temporalSplitQueue.size() << std::endl; + // Write selected inner nodes to brickSelection vector + for (const BrickSelection& bs : temporalSplitQueue) { + writeSelection(bs, bricks); + } + //std::cout << "dead ends: " << deadEnds.size() << std::endl; + for (const BrickSelection& bs : deadEnds) { + writeSelection(bs, bricks); + } + // Write selected leaf nodes to brickSelection vector + //std::cout << "leaf selections: " << leafSelections.size() << std::endl; + for (const BrickSelection& bs : leafSelections) { + writeSelection(bs, bricks); + } + + //std::cout << "Bricks in memory: " << nBricksInMemory << "/" << _memoryBudget << "___\t\t" + // << "Streamed bricks: " << nStreamedBricks << "/" << totalStreamingBudget << std::flush << "___\r"; +} + +float TfBrickSelector::temporalSplitPoints(unsigned int brickIndex) { + if (_tsp->isBstLeaf(brickIndex)) { + return -1; + } + + unsigned int leftChild = _tsp->getBstLeft(brickIndex); + unsigned int rightChild = _tsp->getBstRight(brickIndex); + + float currentError = _brickErrors[brickIndex]; + float splitError = _brickErrors[leftChild] + _brickErrors[rightChild]; + + /*if (currentError + 0.001 < splitError) { + std::cout << "Warning! (TEMPORAL SPLIT) Current error " << currentError << " is smaller than split error " << splitError << "." << std::endl; + }*/ + float diff = currentError - splitError; + if (diff < 0.0) { + //std::cout << "local temporal split minimum for brick " << brickIndex << std::endl; + diff = -diff; + } + return diff * 0.5; +} + +float TfBrickSelector::spatialSplitPoints(unsigned int brickIndex) { + if (_tsp->isOctreeLeaf(brickIndex)) { + return -1; + } + + + float currentError = _brickErrors[brickIndex]; + float splitError = 0; + + unsigned int firstChild = _tsp->getFirstOctreeChild(brickIndex); + for (unsigned int i = 0; i < 8; i++) { + unsigned int child = firstChild + i; + splitError += _brickErrors[child]; + } + + /*if (currentError + 0.001 < splitError) { + std::cout << "Warning! (SPATIAL SPLIT) Current error " << currentError << " is smaller than split error " << splitError << "." << std::endl; + }*/ + + float diff = currentError - splitError; + if (diff < 0.0) { + //std::cout << "local spatial split minimum for brick " << brickIndex << std::endl; + diff = -diff; + } + + return diff * 0.125; +} + +float TfBrickSelector::splitPoints(unsigned int brickIndex, BrickSelection::SplitType& splitType) { + float temporalPoints = temporalSplitPoints(brickIndex); + float spatialPoints = spatialSplitPoints(brickIndex); + float splitPoints; + + if (spatialPoints > 0 && spatialPoints > temporalPoints) { + splitPoints = spatialPoints; + splitType = BrickSelection::SplitType::Spatial; + } else if (temporalPoints > 0) { + splitPoints = temporalPoints; + splitType = BrickSelection::SplitType::Temporal; + } else { + splitPoints = -1; + splitType = BrickSelection::SplitType::None; + } + return splitPoints; +} + + +bool TfBrickSelector::calculateBrickErrors() { + TransferFunction *tf = _transferFunction; + if (!tf) return false; + + size_t tfWidth = tf->width(); + if (tfWidth <= 0) return false; + + std::vector gradients(tfWidth - 1); + for (size_t offset = 0; offset < tfWidth - 1; offset++) { + glm::vec4 prevRgba = tf->sample(offset); + glm::vec4 nextRgba = tf->sample(offset + 1); + + float colorDifference = glm::distance(prevRgba, nextRgba); + float alpha = (prevRgba.w + nextRgba.w) * 0.5; + + gradients[offset] = colorDifference*alpha; + } + + + + unsigned int nHistograms = _tsp->numTotalNodes(); + _brickErrors = std::vector(nHistograms); + + for (unsigned int brickIndex = 0; brickIndex < nHistograms; brickIndex++) { + if (_tsp->isBstLeaf(brickIndex) && _tsp->isOctreeLeaf(brickIndex)) { + _brickErrors[brickIndex] = 0; + } else { + const Histogram* histogram = _histogramManager->getHistogram(brickIndex); + float error = 0; + for (int i = 0; i < gradients.size(); i++) { + float x = (i + 0.5) / tfWidth; + float sample = histogram->interpolate(x); + assert(sample >= 0); + assert(gradients[i] >= 0); + error += sample * gradients[i]; + } + _brickErrors[brickIndex] = error; + } + } + + return true; +} + +int TfBrickSelector::linearCoords(int x, int y, int z) { + const TSP::Header &header = _tsp->header(); + return x + (header.xNumBricks_ * y) + (header.xNumBricks_ * header.yNumBricks_ * z); +} + +void TfBrickSelector::writeSelection(BrickSelection brickSelection, std::vector& bricks) { + BrickCover coveredBricks = brickSelection.cover; + for (int z = coveredBricks.lowZ; z < coveredBricks.highZ; z++) { + for (int y = coveredBricks.lowY; y < coveredBricks.highY; y++) { + for (int x = coveredBricks.lowX; x < coveredBricks.highX; x++) { + bricks[linearCoords(x, y, z)] = brickSelection.brickIndex; + } + } + } +} + + +} // namespace openspace diff --git a/modules/multiresvolume/rendering/tfbrickselector.h b/modules/multiresvolume/rendering/tfbrickselector.h new file mode 100644 index 0000000000..2a48004406 --- /dev/null +++ b/modules/multiresvolume/rendering/tfbrickselector.h @@ -0,0 +1,73 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 __TFBRICKSELECTOR_H__ +#define __TFBRICKSELECTOR_H__ + +#include +#include +#include +#include + + +namespace openspace { + +class TSP; +class ErrorHistogramManager; +class TransferFunction; + +class TfBrickSelector : public BrickSelector { +public: + TfBrickSelector(TSP* tsp, ErrorHistogramManager* hm, TransferFunction* tf, int memoryBudget, int streamingBudget); + + ~TfBrickSelector(); + + virtual bool initialize(); + + void selectBricks(int timestep, std::vector& bricks); + void setMemoryBudget(int memoryBudget); + void setStreamingBudget(int streamingBudget); + bool calculateBrickErrors(); + private: + + TSP* _tsp; + ErrorHistogramManager* _histogramManager; + TransferFunction* _transferFunction; + std::vector _brickErrors; + float spatialSplitPoints(unsigned int brickIndex); + float temporalSplitPoints(unsigned int brickIndex); + float splitPoints(unsigned int brickIndex, BrickSelection::SplitType& splitType); + + int linearCoords(int x, int y, int z); + void writeSelection(BrickSelection coveredBricks, std::vector& bricks); + + int _memoryBudget; + int _streamingBudget; + +}; + +} // namespace openspace + +#endif // __TFBRICKSELECTOR_H__ + diff --git a/modules/multiresvolume/rendering/tsp.cpp b/modules/multiresvolume/rendering/tsp.cpp new file mode 100644 index 0000000000..0aa18704dd --- /dev/null +++ b/modules/multiresvolume/rendering/tsp.cpp @@ -0,0 +1,753 @@ +/***************************************************************************************** + * * + * 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 + +// ghoul +#include +#include +#include + +// std +#include +#include + +namespace { + const std::string _loggerCat = "TSP"; +} + +namespace openspace { + +TSP::TSP(const std::string& filename) + : _filename(filename) + , _dataSSBO(0) + , paddedBrickDim_(0) + , numTotalNodes_(0) + , numBSTLevels_(0) + , numBSTNodes_(0) + , numOTLevels_(0) + , numOTNodes_(0) + , minSpatialError_(0.0f) + , maxSpatialError_(0.0f) + , medianSpatialError_(0.0f) + , minTemporalError_(0.0f) + , maxTemporalError_(0.0f) + , medianTemporalError_(0.0f) +{ + _file.open(_filename, std::ios::in | std::ios::binary); +} + +TSP::~TSP() { + if (_file.is_open()) + _file.close(); +} + +bool TSP::load() { + if (!readHeader()) { + LERROR("Could not read header"); + return false; + } + + if (readCache()) { + //if (false) { + LINFO("Using cache"); + } + else { + if (!construct()) { + LERROR("Could not construct"); + return false; + } + + if (false) { + if (!calculateSpatialError()) { + LERROR("Could not calculate spatial error"); + return false; + } + if (!calculateTemporalError()) { + LERROR("Could not calculate temporal error"); + return false; + } + if (!writeCache()) { + LERROR("Could not write cache"); + return false; + } + } + } + initalizeSSO(); + + return true; +} + +bool TSP::readHeader() { + + if (!_file.good()) + return false; + + _file.seekg(_file.beg); + + _file.read(reinterpret_cast(&_header), sizeof(Header)); + /* + file.read(reinterpret_cast(&gridType_), sizeof(unsigned int)); + file.read(reinterpret_cast(&numOrigTimesteps_), sizeof(unsigned int)); + file.read(reinterpret_cast(&numTimesteps_), sizeof(unsigned int)); + file.read(reinterpret_cast(&xBrickDim_), sizeof(unsigned int)); + file.read(reinterpret_cast(&yBrickDim_), sizeof(unsigned int)); + file.read(reinterpret_cast(&zBrickDim_), sizeof(unsigned int)); + file.read(reinterpret_cast(&xNumBricks_), sizeof(unsigned int)); + file.read(reinterpret_cast(&yNumBricks_), sizeof(unsigned int)); + file.read(reinterpret_cast(&zNumBricks_), sizeof(unsigned int)); + */ + + LDEBUG("Grid type: " << _header.gridType_); + LDEBUG("Brick dimensions: " << _header.xBrickDim_ << " " << _header.yBrickDim_ << " " << _header.zBrickDim_); + LDEBUG("Num bricks: " << _header.xNumBricks_ << " " << _header.yNumBricks_ << " " << _header.zNumBricks_); + + paddedBrickDim_ = _header.xBrickDim_ + 2 * paddingWidth_; + // TODO support dimensions of different size + numOTLevels_ = static_cast(log((int)_header.xNumBricks_) / log(2) + 1); + numOTNodes_ = static_cast((pow(8, numOTLevels_) - 1) / 7); + numBSTLevels_ = static_cast(log((int)_header.numTimesteps_) / log(2) + 1); + numBSTNodes_ = static_cast(_header.numTimesteps_ * 2 - 1); + numTotalNodes_ = numOTNodes_ * numBSTNodes_; + + LDEBUG("Num OT levels: " << numOTLevels_); + LDEBUG("Num OT nodes: " << numOTNodes_); + LDEBUG("Num BST levels: " << numBSTLevels_); + LDEBUG("Num BST nodes: " << numBSTNodes_); + LDEBUG("NUm total nodes: " << numTotalNodes_); + + // Allocate space for TSP structure + data_.resize(numTotalNodes_*NUM_DATA); + LDEBUG("data size: " << data_.size()); + + return true; +} + +bool TSP::construct() { + + LDEBUG("Constructing TSP tree"); + + // Loop over the OTs (one per BST node) + for (unsigned int OT = 0; OT(log(OT + 1) / log(2)); + + // Traverse OT + unsigned int OTChild = 1; + unsigned int OTLevel = 0; + while (OTLevel < numOTLevels_) { + + unsigned int OTNodesInLevel = static_cast(pow(8, OTLevel)); + for (unsigned int i = 0; i(numBSTLevels_ - 1 - BSTLevel); + data_[OTNode*NUM_DATA + SPATIAL_ERR] = static_cast(numOTLevels_ - 1 - OTLevel); + + if (BSTLevel == 0) { + // Calculate OT child index (-1 if node is leaf) + int OTChildIndex = + (OTChild < numOTNodes_) ? static_cast(OT*numOTNodes_ + OTChild) : -1; + data_[OTNode*NUM_DATA + CHILD_INDEX] = OTChildIndex; + } + else { + // Calculate BST child index (-1 if node is BST leaf) + + // First BST node of current level + int firstNode = + static_cast((2 * pow(2, BSTLevel - 1) - 1)*numOTNodes_); + // First BST node of next level + int firstChild = + static_cast((2 * pow(2, BSTLevel) - 1)*numOTNodes_); + // Difference between first nodes between levels + int levelGap = firstChild - firstNode; + // How many nodes away from the first node are we? + int offset = (OTNode - firstNode) / numOTNodes_; + + // Use level gap and offset to calculate child index + int BSTChildIndex = + (BSTLevel < numBSTLevels_ - 1) ? + static_cast(OTNode + levelGap + (offset*numOTNodes_)) : -1; + + data_[OTNode*NUM_DATA + CHILD_INDEX] = BSTChildIndex; + } + + OTNode++; + OTChild += 8; + + } + + OTLevel++; + } + } + return true; +} + +bool TSP::initalizeSSO() { + + if (!_dataSSBO) + glGenBuffers(1, &_dataSSBO); + + const size_t size = sizeof(GLint)*data_.size(); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, _dataSSBO); + //glBufferData(GL_SHADER_STORAGE_BUFFER, size, data_.data(), GL_DYNAMIC_READ); + glBufferData(GL_SHADER_STORAGE_BUFFER, size, data_.data(), GL_STATIC_DRAW); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + glFinish(); + return true; +} + +const TSP::Header& TSP::header() const { + return _header; +} + +long long TSP::dataPosition() { + return sizeof(Header); +} + +std::ifstream& TSP::file() { + return _file; +} + +unsigned int TSP::numTotalNodes() const { + return numTotalNodes_; +} + +unsigned int TSP::numValuesPerNode() const { + return NUM_DATA; +} + +unsigned int TSP::numBSTNodes() const { + return numBSTNodes_; +} + +unsigned int TSP::numBSTLevels() const { + return numBSTLevels_; +} + +unsigned int TSP::numOTNodes() const { + return numOTNodes_; +} + +unsigned int TSP::numOTLevels() const { + return numOTLevels_; +} + +unsigned int TSP::brickDim() const { + return _header.xBrickDim_; +} + +unsigned int TSP::paddedBrickDim() const { + return paddedBrickDim_; +} + +unsigned int TSP::numBricksPerAxis() const { + return _header.xNumBricks_; +} + +GLuint TSP::ssbo() const { + return _dataSSBO; +} + +bool TSP::calculateSpatialError() { + unsigned int numBrickVals = paddedBrickDim_*paddedBrickDim_*paddedBrickDim_; + + if (!_file.is_open()) + return false; + + std::vector buffer(numBrickVals); + std::vector averages(numTotalNodes_); + std::vector stdDevs(numTotalNodes_); + + // First pass: Calculate average color for each brick + LDEBUG("Calculating spatial error, first pass"); + for (unsigned int brick = 0; brick(brick*numBrickVals*sizeof(float)); + _file.seekg(offset); + + _file.read(reinterpret_cast(&buffer[0]), + static_cast(numBrickVals)*sizeof(float)); + + double average = 0.0; + for (auto it = buffer.begin(); it != buffer.end(); ++it) { + average += *it; + } + + averages[brick] = average / static_cast(numBrickVals); + } + + // Spatial SNR stats + float minError = 1e20f; + float maxError = 0.f; + std::vector medianArray(numTotalNodes_); + + // Second pass: For each brick, compare the covered leaf voxels with + // the brick average + LDEBUG("Calculating spatial error, second pass"); + for (unsigned int brick = 0; brick coveredLeafBricks = + CoveredLeafBricks(brick); + + // If the brick is already a leaf, assign a negative error. + // Ad hoc "hack" to distinguish leafs from other nodes that happens + // to get a zero error due to rounding errors or other reasons. + if (coveredLeafBricks.size() == 1) { + stdDev = -0.1f; + } + else { + + // Calculate "standard deviation" corresponding to leaves + for (auto lb = coveredLeafBricks.begin(); + lb != coveredLeafBricks.end(); ++lb) { + + // Read brick + std::streampos offset = dataPosition() + static_cast((*lb)*numBrickVals*sizeof(float)); + _file.seekg(offset); + + _file.read(reinterpret_cast(&buffer[0]), + static_cast(numBrickVals)*sizeof(float)); + + // Add to sum + for (auto v = buffer.begin(); v != buffer.end(); ++v) { + stdDev += pow(*v - brickAvg, 2.f); + } + + + } + + // Finish calculation + if (sizeof(float) != sizeof(int)) { + LERROR("Float and int sizes don't match, can't reintepret"); + return false; + } + + stdDev /= static_cast(coveredLeafBricks.size()*numBrickVals); + stdDev = sqrt(stdDev); + + } // if not leaf + + if (stdDev < minError) { + minError = stdDev; + } + else if (stdDev > maxError) { + maxError = stdDev; + } + + stdDevs[brick] = stdDev; + medianArray[brick] = stdDev; + + } + + std::sort(medianArray.begin(), medianArray.end()); + //float medError = medianArray[medianArray.size()/2]; + + /* + LDEBUG("\nMin spatial std dev: " << minError); + LDEBUG("Max spatial std dev: " << maxError); + LDEBUG("Median spatial std dev: " << medError); + LDEBUG(""); + */ + + // "Normalize" errors + float minNorm = 1e20f; + float maxNorm = 0.f; + for (unsigned int i = 0; i 0.f) { + stdDevs[i] = pow(stdDevs[i], 0.5f); + } + //data_[i*NUM_DATA + SPATIAL_ERR] = *reinterpret_cast(&stdDevs[i]); + data_[i*NUM_DATA + SPATIAL_ERR] = glm::floatBitsToInt(stdDevs[i]); + if (stdDevs[i] < minNorm) { + minNorm = stdDevs[i]; + } + else if (stdDevs[i] > maxNorm) { + maxNorm = stdDevs[i]; + } + } + + std::sort(stdDevs.begin(), stdDevs.end()); + float medNorm = stdDevs[stdDevs.size() / 2]; + + minSpatialError_ = minNorm; + maxSpatialError_ = maxNorm; + medianSpatialError_ = medNorm; + + LDEBUG("Min normalized spatial std dev: " << minNorm); + LDEBUG("Max normalized spatial std dev: " << maxNorm); + LDEBUG("Median normalized spatial std dev: " << medNorm); + + return true; +} + +bool TSP::calculateTemporalError() { + + if (!_file.is_open()) + return false; + + LDEBUG("Calculating temporal error"); + + // Statistics + //float minErr = 1e20f; + //float maxErr = 0.f; + std::vector meanArray(numTotalNodes_); + + // Save errors + std::vector errors(numTotalNodes_); + + // Calculate temporal error for one brick at a time + for (unsigned int brick = 0; brick voxelAverages(numBrickVals); + std::vector voxelStdDevs(numBrickVals); + + // Read the whole brick to fill the averages + std::streampos offset = dataPosition() + static_cast(brick*numBrickVals*sizeof(float)); + _file.seekg(offset); + + _file.read(reinterpret_cast(&voxelAverages[0]), + static_cast(numBrickVals)*sizeof(float)); + + // Build a list of the BST leaf bricks (within the same octree level) that + // this brick covers + std::list coveredBricks = CoveredBSTLeafBricks(brick); + + // If the brick is at the lowest BST level, automatically set the error + // to -0.1 (enables using -1 as a marker for "no error accepted"); + // Somewhat ad hoc to get around the fact that the error could be + // 0.0 higher up in the tree + if (coveredBricks.size() == 1) { + errors[brick] = -0.1f; + } else { + // Calculate standard deviation per voxel, average over brick + float avgStdDev = 0.f; + for (unsigned int voxel = 0; voxel((*leaf*numBrickVals + voxel)*sizeof(float)); + _file.seekg(offset); + + float sample; + _file.read(reinterpret_cast(&sample), sizeof(float)); + + stdDev += pow(sample - voxelAverages[voxel], 2.f); + } + stdDev /= static_cast(coveredBricks.size()); + stdDev = sqrt(stdDev); + + avgStdDev += stdDev; + } // for voxel + + avgStdDev /= static_cast(numBrickVals); + meanArray[brick] = avgStdDev; + errors[brick] = avgStdDev; + + } + + /* + if (avgStdDev < minErr) { + minErr = avgStdDev; + } else if (avgStdDev > maxErr) { + maxErr = avgStdDev; + } + */ + + } // for all bricks + + std::sort(meanArray.begin(), meanArray.end()); + //float medErr = meanArray[meanArray.size()/2]; + + /* + LDEBUG("\nMin temporal error: " << minErr); + LDEBUG("Max temporal error: " << maxErr); + LDEBUG("Median temporal error: " << medErr); + */ + + // Adjust errors using user-provided exponents + float minNorm = 1e20f; + float maxNorm = 0.f; + for (unsigned int i = 0; i 0.f) { + errors[i] = pow(errors[i], 0.25f); + } + //data_[i*NUM_DATA + TEMPORAL_ERR] = *reinterpret_cast(&errors[i]); + data_[i*NUM_DATA + TEMPORAL_ERR] = glm::floatBitsToInt(errors[i]); + if (errors[i] < minNorm) { + minNorm = errors[i]; + } + else if (errors[i] > maxNorm) { + maxNorm = errors[i]; + } + } + + std::sort(errors.begin(), errors.end()); + float medNorm = errors[errors.size() / 2]; + + minTemporalError_ = minNorm; + maxTemporalError_ = maxNorm; + medianTemporalError_ = medNorm; + + LDEBUG("Min normalized temporal std dev: " << minNorm); + LDEBUG("Max normalized temporal std dev: " << maxNorm); + LDEBUG("Median normalized temporal std dev: " << medNorm); + + return true; +} + + +bool TSP::readCache() { + + if (!FileSys.cacheManager()) + return false; + + ghoul::filesystem::File f = _filename; + std::string cacheFilename = FileSys.cacheManager()->cachedFilename( + f.baseName(), "", ghoul::filesystem::CacheManager::Persistent::Yes); + + std::ifstream file(cacheFilename, std::ios::in | std::ios::binary); + if (!file.is_open()) { + LWARNING("Failed to open " << cacheFilename); + return false; + } + + + file.read(reinterpret_cast(&minSpatialError_), sizeof(float)); + file.read(reinterpret_cast(&maxSpatialError_), sizeof(float)); + file.read(reinterpret_cast(&medianSpatialError_), sizeof(float)); + file.read(reinterpret_cast(&minTemporalError_), sizeof(float)); + file.read(reinterpret_cast(&maxTemporalError_), sizeof(float)); + file.read(reinterpret_cast(&medianTemporalError_), sizeof(float)); + size_t dataSize = static_cast(numTotalNodes_*NUM_DATA)*sizeof(int); + file.read(reinterpret_cast(&data_[0]), dataSize); + file.close(); + + LDEBUG("Cached errors:"); + LDEBUG("Min spatial error: " << minSpatialError_); + LDEBUG("Max spatial error: " << maxSpatialError_); + LDEBUG("Median spatial error: " << medianSpatialError_); + LDEBUG("Min temporal error: " << minTemporalError_); + LDEBUG("Max temporal error: " << maxTemporalError_); + LDEBUG("Median temporal error: " << medianTemporalError_); + + return true; +} + +bool TSP::writeCache() { + + if (!FileSys.cacheManager()) + return false; + + ghoul::filesystem::File f = _filename; + std::string cacheFilename = FileSys.cacheManager()->cachedFilename( + f.baseName(), "", ghoul::filesystem::CacheManager::Persistent::Yes); + + std::ofstream file(cacheFilename, std::ios::out | std::ios::binary); + if (!file.is_open()) { + LWARNING("Failed to open " << cacheFilename); + return false; + } + LINFO("Writing cache to " << cacheFilename); + + + file.write(reinterpret_cast(&minSpatialError_), sizeof(float)); + file.write(reinterpret_cast(&maxSpatialError_), sizeof(float)); + file.write(reinterpret_cast(&medianSpatialError_), sizeof(float)); + file.write(reinterpret_cast(&minTemporalError_), sizeof(float)); + file.write(reinterpret_cast(&maxTemporalError_), sizeof(float)); + file.write(reinterpret_cast(&medianTemporalError_), sizeof(float)); + file.write(reinterpret_cast(&data_[0]), data_.size()*sizeof(float)); + + file.close(); + + /* + LDEBUG("\nData:"); + for (unsigned i=0; i(&data_[i*NUM_DATA + SPATIAL_ERR])); + LDEBUG("Temporal err " << *reinterpret_cast(&data_[i*NUM_DATA + TEMPORAL_ERR])); + } + */ + + return true; +} + +float TSP::getSpatialError(unsigned int _brickIndex) { + return reinterpret_cast(data_[_brickIndex*NUM_DATA + SPATIAL_ERR]); +} + +float TSP::getTemporalError(unsigned int _brickIndex) { + return reinterpret_cast(data_[_brickIndex*NUM_DATA + TEMPORAL_ERR]); +} + +unsigned int TSP::getFirstOctreeChild(unsigned int _brickIndex) { + unsigned int otNode = _brickIndex % numOTNodes_; + unsigned int bstOffset = _brickIndex - otNode; + + unsigned int depth = log(7 * otNode + 1) / log(8); + unsigned int firstInLevel = (pow(8, depth) - 1) / 7; + unsigned int levelOffset = otNode - firstInLevel; + unsigned int firstInChildLevel = (pow(8, depth + 1) - 1) / 7; + unsigned int childIndex = firstInChildLevel + 8*levelOffset; + + return bstOffset + childIndex; +} + +unsigned int TSP::getBstLeft(unsigned int _brickIndex) { + unsigned int bstNode = _brickIndex / numOTNodes_; + unsigned int otOffset = _brickIndex % numOTNodes_; + unsigned int depth = log(bstNode + 1) / log(2); + unsigned int firstInLevel = pow(2, depth) - 1; + unsigned int levelOffset = bstNode - firstInLevel; + unsigned int firstInChildLevel = pow(2, depth + 1) - 1; + unsigned int childIndex = firstInChildLevel + 2*levelOffset; + return otOffset + childIndex * numOTNodes_; +} + +unsigned int TSP::getBstRight(unsigned int _brickIndex) { + return getBstLeft(_brickIndex) + numOTNodes_; +} + +bool TSP::isBstLeaf(unsigned int _brickIndex) { + unsigned int bstNode = _brickIndex / numOTNodes_; + return bstNode >= numBSTNodes_ / 2; +} + +bool TSP::isOctreeLeaf(unsigned int _brickIndex) { + unsigned int otNode = _brickIndex % numOTNodes_; + unsigned int depth = log(7 * otNode + 1) / log(8); + return depth == numOTLevels_ - 1; +} + + +std::list TSP::CoveredLeafBricks(unsigned int _brickIndex) { + std::list out; + + // Find what octree skeleton node the index belongs to + unsigned int OTNode = _brickIndex % numOTNodes_; + + // Find what BST node the index corresponds to using int division + unsigned int BSTNode = _brickIndex / numOTNodes_; + // Calculate BST offset (to translate to root octree) + unsigned int BSTOffset = BSTNode * numOTNodes_; + + // Traverse root octree structure to leaves + // When visiting the leaves, translate back to correct BST level and save + std::queue queue; + queue.push(OTNode); + do { + + // Get front of queue and pop it + unsigned int toVisit = queue.front(); + queue.pop(); + + // See if the node has children + int child = data_[toVisit*NUM_DATA + CHILD_INDEX]; + if (child == -1) { + // Translate back and save + out.push_back(toVisit + BSTOffset); + } + else { + // Queue the eight children + for (int i = 0; i<8; ++i) { + queue.push(child + i); + } + } + + } while (!queue.empty()); + + return out; +} + +std::list TSP::CoveredBSTLeafBricks(unsigned int _brickIndex) { + std::list out; + + // Traverse the BST children until we are at root + std::queue queue; + queue.push(_brickIndex); + do { + + unsigned int toVisit = queue.front(); + queue.pop(); + + bool BSTRoot = toVisit < numOTNodes_; + if (BSTRoot) { + if (numBSTLevels_ == 1) { + out.push_back(toVisit); + } + else { + queue.push(toVisit + numOTNodes_); + queue.push(toVisit + numOTNodes_ * 2); + } + } + else { + int child = data_[toVisit*NUM_DATA + CHILD_INDEX]; + if (child == -1) { + // Save leaf brick to list + out.push_back(toVisit); + } + else { + // Queue children + queue.push(child); + queue.push(child + numOTNodes_); + } + } + + } while (!queue.empty()); + + return out; +} + +} diff --git a/modules/multiresvolume/rendering/tsp.h b/modules/multiresvolume/rendering/tsp.h new file mode 100644 index 0000000000..6e419e7b6a --- /dev/null +++ b/modules/multiresvolume/rendering/tsp.h @@ -0,0 +1,148 @@ +/***************************************************************************************** + * * + * 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 __TSP_H__ +#define __TSP_H__ + +// std includes +#include +#include +#include +#include +#include + +// ghoul includes +#include + +namespace openspace { +class TSP { +public: + + struct Header { + unsigned int gridType_; + unsigned int numOrigTimesteps_; + unsigned int numTimesteps_; + unsigned int xBrickDim_; + unsigned int yBrickDim_; + unsigned int zBrickDim_; + unsigned int xNumBricks_; + unsigned int yNumBricks_; + unsigned int zNumBricks_; + + }; + + enum NodeData { + BRICK_INDEX = 0, + CHILD_INDEX, + SPATIAL_ERR, + TEMPORAL_ERR, + NUM_DATA + }; + + TSP(const std::string& filename); + ~TSP(); + + // load performs readHeader, readCache, writeCache and construct + // in the correct sequence + bool load(); + + bool readHeader(); + bool readCache(); + bool writeCache(); + bool construct(); + bool initalizeSSO(); + + const Header& header() const; + static long long dataPosition(); + std::ifstream& file(); + unsigned int numTotalNodes() const; + unsigned int numValuesPerNode() const; + unsigned int numBSTNodes() const; + unsigned int numBSTLevels() const; + unsigned int numOTNodes() const; + unsigned int numOTLevels() const; + unsigned int brickDim() const; + unsigned int paddedBrickDim() const; + unsigned int numBricksPerAxis() const; + GLuint ssbo() const; + + bool calculateSpatialError(); + bool calculateTemporalError(); + + float getSpatialError(unsigned int _brickIndex); + float getTemporalError(unsigned int _brickIndex); + unsigned int getFirstOctreeChild(unsigned int _brickIndex); + + unsigned int getBstLeft(unsigned int _brickIndex); + unsigned int getBstRight(unsigned int _brickIndex); + + bool isBstLeaf(unsigned int _brickIndex); + bool isOctreeLeaf(unsigned int _brickIndex); + +private: + // Returns a list of the octree leaf nodes that a given input + // brick covers. If the input is already a leaf, the list will + // only contain that one index. + std::list CoveredLeafBricks(unsigned int _brickIndex); + + // Returns a list of the BST leaf nodes that a given input brick + // covers (at the same spatial subdivision level). + std::list CoveredBSTLeafBricks(unsigned int _brickIndex); + + // Return a list of eight children brick incices given a brick index + std::list ChildBricks(unsigned int _brickIndex); + + std::string _filename; + std::ifstream _file; + std::streampos _dataOffset; + + // Holds the actual structure + std::vector data_; + GLuint _dataSSBO; + + // Data from file + Header _header; + + // Additional metadata + unsigned int paddedBrickDim_; + unsigned int numTotalNodes_; + unsigned int numBSTLevels_; + unsigned int numBSTNodes_; + unsigned int numOTLevels_; + unsigned int numOTNodes_; + + const unsigned int paddingWidth_ = 1; + + // Error stats + float minSpatialError_; + float maxSpatialError_; + float medianSpatialError_; + float minTemporalError_; + float maxTemporalError_; + float medianTemporalError_; + +}; // class TSP +} // namespace openspace + +#endif diff --git a/modules/multiresvolume/shaders/boundsFs.glsl b/modules/multiresvolume/shaders/boundsFs.glsl new file mode 100644 index 0000000000..34b184df57 --- /dev/null +++ b/modules/multiresvolume/shaders/boundsFs.glsl @@ -0,0 +1,40 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +in vec3 vPosition; +in vec4 worldPosition; + +#include "PowerScaling/powerScaling_fs.hglsl" +#include "fragment.glsl" + +Fragment getFragment() { + vec4 fragColor = vec4(vPosition+0.5, 1.0); + vec4 position = worldPosition; + float depth = pscDepth(position); + + Fragment frag; + frag.color = fragColor; + frag.depth = depth; + return frag; +} diff --git a/modules/multiresvolume/shaders/boundsVs.glsl b/modules/multiresvolume/shaders/boundsVs.glsl new file mode 100644 index 0000000000..fc328f30df --- /dev/null +++ b/modules/multiresvolume/shaders/boundsVs.glsl @@ -0,0 +1,47 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(location = 0) in vec4 vertPosition; + +uniform mat4 viewProjection; +uniform mat4 modelTransform; + +out vec3 vPosition; +out vec4 worldPosition; + +#include "PowerScaling/powerScaling_vs.hglsl" + +void main() { + vPosition = vertPosition.xyz; + worldPosition = modelTransform*vertPosition; + + vec4 position = pscTransform(worldPosition, mat4(1.0)); + + // project the position to view space + gl_Position = viewProjection * position; + + gl_Position.z = 1.0; +} diff --git a/modules/multiresvolume/shaders/helper.glsl b/modules/multiresvolume/shaders/helper.glsl new file mode 100644 index 0000000000..87d997a500 --- /dev/null +++ b/modules/multiresvolume/shaders/helper.glsl @@ -0,0 +1,31 @@ +#define MULTIRES_PI 3.14159265358979323846 /* pi */ +#define MULTIRES_SQRT1_3 0.57735026919 /* 1/sqrt(3) */ +#define MULTIRES_OPACITY_THRESHOLD 0.01 +vec3 multires_cartesianToSpherical(vec3 _cartesian) { + // Put cartesian in [-1..1] range first + vec3 cartesian = vec3(-1.0,-1.0,-1.0) + _cartesian * 2.0f; + + float r = length(cartesian); + float theta, phi; + + if (r == 0.0) { + theta = phi = 0.0; + } else { + theta = acos(cartesian.z/r) / MULTIRES_PI; + phi = (MULTIRES_PI + atan(cartesian.y, cartesian.x)) / (2.0*MULTIRES_PI ); + } + r *= MULTIRES_SQRT1_3; + return vec3(r, theta, phi); +} + +int multires_intCoord(ivec3 vec3Coords, ivec3 spaceDim) { + return vec3Coords.x + spaceDim.x*vec3Coords.y + spaceDim.x*spaceDim.y*vec3Coords.z; +} + +vec3 multires_vec3Coords(uint intCoord, ivec3 spaceDim) { + vec3 coords = vec3(0.0); + coords.x = mod(intCoord, spaceDim.x); + coords.y = mod(intCoord / spaceDim.x, spaceDim.y); + coords.z = intCoord / spaceDim.x / spaceDim.y; + return coords; +} diff --git a/modules/multiresvolume/shaders/raycast.glsl b/modules/multiresvolume/shaders/raycast.glsl new file mode 100644 index 0000000000..50265a24de --- /dev/null +++ b/modules/multiresvolume/shaders/raycast.glsl @@ -0,0 +1,123 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + + +uniform float opacity_#{id}; +uniform sampler1D transferFunction_#{id}; +uniform sampler3D textureAtlas_#{id}; +uniform int gridType_#{id}; +uniform uint maxNumBricksPerAxis_#{id}; +uniform uint paddedBrickDim_#{id}; +uniform ivec3 nBricksInAtlas_#{id}; +uniform ivec3 atlasSize_#{id}; +uniform float stepSizeCoefficient_#{id} = 1.0; + +layout (shared) buffer atlasMapBlock_#{id} { + uint atlasMap_#{id}[]; +}; + +void atlasMapDataFunction_#{id}(ivec3 brickCoords, inout uint atlasIntCoord, inout uint level) { + int linearBrickCoord = multires_intCoord(brickCoords, ivec3(maxNumBricksPerAxis_#{id})); + uint mapData = atlasMap_#{id}[linearBrickCoord]; + level = mapData >> 28; + atlasIntCoord = mapData & 0x0FFFFFFF; +} + +vec3 atlasCoordsFunction_#{id}(vec3 position) { + uint maxNumBricksPerAxis = maxNumBricksPerAxis_#{id}; + uint paddedBrickDim = paddedBrickDim_#{id}; + + ivec3 brickCoords = ivec3(position * maxNumBricksPerAxis); + uint atlasIntCoord, level; + atlasMapDataFunction_#{id}(brickCoords, atlasIntCoord, level); + + float levelDim = float(maxNumBricksPerAxis) / pow(2.0, level); + vec3 inBrickCoords = mod(position*levelDim, 1.0); + + float scale = float(paddedBrickDim) - 2.0; + vec3 paddedInBrickCoords = (1.0 + inBrickCoords * scale) / paddedBrickDim; + + ivec3 numBricksInAtlas = ivec3(vec3(atlasSize_#{id}) / paddedBrickDim); + vec3 atlasOffset = multires_vec3Coords(atlasIntCoord, numBricksInAtlas); + return (atlasOffset + paddedInBrickCoords) / vec3(numBricksInAtlas); +} + +float stepSize#{id}(vec3 samplePos, vec3 dir){ + return 0.01; + if (true /*opacity_#{id} >= MULTIRES_OPACITY_THRESHOLD*/) { + return stepSizeCoefficient_#{id}/float(maxNumBricksPerAxis_#{id})/float(paddedBrickDim_#{id}); + } else { + // return a number that is garantueed to be bigger than the whole volume + return 2.0; + } +} + +vec4 sample#{id}(vec3 samplePos, vec3 dir, vec4 foregroundColor, inout float maxStepSize) { + //return vec4(1.0, 1.0, 1.0, 1.0); + + if (true /*opacity_#{id} >= MULTIRES_OPACITY_THRESHOLD*/) { + if (gridType_#{id} == 1) { + samplePos = multires_cartesianToSpherical(samplePos); + } + vec3 sampleCoords = atlasCoordsFunction_#{id}(samplePos); + //return vec4(sampleCoords, 1.0); + //sampleCoords = vec3(1.0,0.0, 0.0); + float intensity = texture(textureAtlas_#{id}, sampleCoords).x; + //intensity = sampleCoords; + + //return vec4(vec3(intensity), 1.0); + vec4 contribution = texture(transferFunction_#{id}, intensity); + + //contribution = vec4(sampleCoords, 1.0); + //vec4 contribution = vec4(vec3(intensity), 1.0); + //contribution.a *= 0.3; + //contribution = vec4(1.0, 1.0, 1.0, intensity * 1000000.0); + //contribution = vec4(1.0, 1.0, 1.0, 1.0); + maxStepSize = stepSizeCoefficient_#{id}/float(maxNumBricksPerAxis_#{id})/float(paddedBrickDim_#{id}); + //contribution.a *= opacity_#{id}; + + //maxStepSize = 0.01; + return contribution; + } else { + maxStepSize = 2.0; + return vec4(0.0); + } +} + + + +/*uniform vec4 color#{id}; +uniform float time#{id}; +uniform float maxStepSize#{id} = 0.02; + +vec4 sample#{id}(vec3 samplePos, vec3 dir, vec4 foregroundColor, inout float maxStepSize) { + maxStepSize = 0.01; + return vec4(1.0, 0.0, 0.0, 0.9999999); +} + +float stepSize#{id}(vec3 samplePos, vec3 dir) { + return 0.01; +} +*/ + diff --git a/modules/toyvolume/rendering/renderabletoyvolume.cpp b/modules/toyvolume/rendering/renderabletoyvolume.cpp index 59c93d426f..0ce1f7b70a 100644 --- a/modules/toyvolume/rendering/renderabletoyvolume.cpp +++ b/modules/toyvolume/rendering/renderabletoyvolume.cpp @@ -77,7 +77,7 @@ namespace openspace { RenderableToyVolume::~RenderableToyVolume() {} bool RenderableToyVolume::initialize() { - _raycaster = std::make_unique(ToyVolumeRaycaster(_color)); + _raycaster = std::make_unique(_color); _raycaster->initialize(); OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); diff --git a/shaders/abuffer/abufferfragment.glsl b/shaders/abuffer/abufferfragment.glsl index eb4eef87c7..e986da537e 100644 --- a/shaders/abuffer/abufferfragment.glsl +++ b/shaders/abuffer/abufferfragment.glsl @@ -26,29 +26,31 @@ #define _ABUFFERFRAGMENT_GLSL_ struct ABufferFragment { - uint rgba; - uint depth; - uint data; - uint composition; + uint channel0; + uint channel1; + uint channel2; + uint channel3; }; +// An abuffer frame // Values stored in abuffer: -// -------RGBA-------- -// r 8 bits -// g 8 bits -// b 8 bits -// a 8 bits -// -------DEPTH------- -// depth 32 bits -// -------DATA-------- +// -----CHANNEL 0----- // type 8 bits (signed char) 0: geometry, >0: volume entry, <0: volume exit -// msaa 8 bits -// reserved 16 bits -// ----COMPOSITION---- -// reserved 4 bits (may be suitable for blend modes) -// next 28 bits -// ------------------- -// in total: 16 + 4 = 20 reserved bits for future use. +// msaa 8 bits +// --- if geometry --- | ---- if volume ---- +// reserved 16 bits | x 16 bits +// -----CHANNEL 1----- +// r 8 bits | y 16 bits +// g 8 bits | +// b 8 bits | z 16 bits +// a 8 bits | +// -----CHANNEL 2----- +// depth 32 bits +// -----CHANNEL 3----- +// blend 4 bits (0 = normal, 1 = additive, 2-7 reserved) +// next 28 bits +// ------------------- + const uint mask_1 = uint(1); const uint mask_8 = uint(255); @@ -58,14 +60,17 @@ const uint mask_28 = uint(268435455); const uint mask_31 = uint(2147483647); const uint mask_32 = uint(4294967295); +const uint mask_red = mask_16; +const uint shift_red = 0; + const uint mask_type = mask_32 - mask_24; const uint shift_type = 24; const uint mask_msaa = mask_24 - mask_16; const uint shift_msaa = 16; -const uint mask_blend = mask_32 - mask_31; -const uint shift_blend = 31; +const uint mask_blend = mask_32 - mask_28; +const uint shift_blend = 28; const uint mask_next = mask_28; const uint shift_next = 0; @@ -82,22 +87,37 @@ uint bitextract(in uint pack, uint mask, uint shift) { * Color */ void _color_(inout ABufferFragment frag, vec4 color) { - frag.rgba = packUnorm4x8(color); + frag.channel1 = packUnorm4x8(color); } vec4 _color_(ABufferFragment frag) { - return unpackUnorm4x8(frag.rgba); + return unpackUnorm4x8(frag.channel1); +} + +/** + * Position + */ +void _position_(inout ABufferFragment frag, vec3 pos) { + uint red = uint(round(clamp(pos.x, 0.0, 1.0) * 65535.0)); + bitinsert(frag.channel0, red, mask_red, shift_red); + frag.channel1 = packUnorm2x16(pos.yz); +} + +vec3 _position_(ABufferFragment frag) { + float x = float(bitextract(frag.channel0, mask_red, shift_red)) / 65535.0; + vec2 yz = unpackUnorm2x16(frag.channel1); + return vec3(x, yz); } /** * Depth */ void _depth_(inout ABufferFragment frag, float depth) { - frag.depth = floatBitsToUint(depth); + frag.channel2 = floatBitsToUint(depth); } float _depth_(ABufferFragment frag) { - return uintBitsToFloat(frag.depth); + return uintBitsToFloat(frag.channel2); } /** @@ -110,11 +130,11 @@ void _type_(inout ABufferFragment frag, int type) { } else { val = type; } - bitinsert(frag.data, val, mask_type, shift_type); + bitinsert(frag.channel0, val, mask_type, shift_type); } int _type_(ABufferFragment frag) { - uint val = bitextract(frag.data, mask_type, shift_type); + uint val = bitextract(frag.channel0, mask_type, shift_type); if (val > 127) { return 128 - int(val); } else { @@ -127,11 +147,11 @@ int _type_(ABufferFragment frag) { */ void _msaa_(inout ABufferFragment frag, int type) { uint val = uint(type); - bitinsert(frag.data, val, mask_msaa, shift_msaa); + bitinsert(frag.channel0, val, mask_msaa, shift_msaa); } int _msaa_(ABufferFragment frag) { - uint val = bitextract(frag.data, mask_msaa, shift_msaa); + uint val = bitextract(frag.channel0, mask_msaa, shift_msaa); return int(val); } @@ -139,11 +159,23 @@ int _msaa_(ABufferFragment frag) { * Next */ void _next_(inout ABufferFragment frag, uint val) { - bitinsert(frag.composition, val, mask_next, shift_next); + bitinsert(frag.channel3, val, mask_next, shift_next); } uint _next_(ABufferFragment frag) { - uint val = bitextract(frag.composition, mask_next, shift_next); + uint val = bitextract(frag.channel3, mask_next, shift_next); + return val; +} + +/** + * Blend + */ +void _blend_(inout ABufferFragment frag, uint val) { + bitinsert(frag.channel3, val, mask_blend, shift_blend); +} + +uint _blend_(ABufferFragment frag) { + uint val = bitextract(frag.channel3, mask_blend, shift_blend); return val; } @@ -151,14 +183,14 @@ uint _next_(ABufferFragment frag) { * Raw data */ void _raw_(inout ABufferFragment frag, uvec4 raw) { - frag.rgba = raw.x; - frag.depth = raw.y; - frag.data = raw.z; - frag.composition = raw.w; + frag.channel0 = raw.x; + frag.channel1 = raw.y; + frag.channel2 = raw.z; + frag.channel3 = raw.w; } uvec4 _raw_(inout ABufferFragment frag) { - return uvec4(frag.rgba, frag.depth, frag.data, frag.composition); + return uvec4(frag.channel0, frag.channel1, frag.channel2, frag.channel3); } #endif diff --git a/shaders/abuffer/boundsabuffer.frag b/shaders/abuffer/boundsabuffer.frag index 0253e74da1..d5718c2913 100644 --- a/shaders/abuffer/boundsabuffer.frag +++ b/shaders/abuffer/boundsabuffer.frag @@ -41,8 +41,9 @@ void main() { uint prevHead = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), newHead); ABufferFragment aBufferFrag; - _color_(aBufferFrag, frag.color); + _position_(aBufferFrag, frag.color.rgb); _depth_(aBufferFrag, frag.depth); + _blend_(aBufferFrag, frag.blend); int fragmentType = #{fragmentType}; diff --git a/shaders/abuffer/raycasterdata.glsl b/shaders/abuffer/raycasterdata.glsl index 5176f5342a..5f0b945365 100644 --- a/shaders/abuffer/raycasterdata.glsl +++ b/shaders/abuffer/raycasterdata.glsl @@ -30,6 +30,7 @@ struct RaycasterData { vec3 direction; float scale; float previousJitterDistance; + uint blend; } #endif diff --git a/shaders/abuffer/renderabuffer.frag b/shaders/abuffer/renderabuffer.frag index db12828a6c..6c05208a3b 100644 --- a/shaders/abuffer/renderabuffer.frag +++ b/shaders/abuffer/renderabuffer.frag @@ -43,6 +43,8 @@ void main() { ABufferFragment aBufferFrag; _color_(aBufferFrag, frag.color); _depth_(aBufferFrag, frag.depth); + _blend_(aBufferFrag, frag.blend); + _type_(aBufferFrag, 0); // 0 = geometry type _msaa_(aBufferFrag, gl_SampleMaskIn[0]); _next_(aBufferFrag, prevHead); diff --git a/shaders/abuffer/resolveabuffer.frag b/shaders/abuffer/resolveabuffer.frag index bda831088c..93329d3b65 100644 --- a/shaders/abuffer/resolveabuffer.frag +++ b/shaders/abuffer/resolveabuffer.frag @@ -39,7 +39,7 @@ uniform int nAaSamples; #define RAYCASTING_ENABLED #{raycastingEnabled} #define N_RAYCASTERS #{nRaycasters} #define ALPHA_LIMIT 0.99 -#define RAYCAST_MAX_STEPS 1000 +#define RAYCAST_MAX_STEPS 10000 #define INT_MAX 2147483647 ///////////////////////// @@ -132,19 +132,21 @@ void retrieveRaycasterData(uint nFrags) { } for (int i = 0; i < nFrags; i++) { int type = _type_(fragments[i]); // - 1; - vec4 color = _color_(fragments[i]); + vec3 position = _position_(fragments[i]); float depth = _depth_(fragments[i]); + uint blend = _blend_(fragments[i]); if (type > 0) { // enter raycaster int raycasterId = type - 1; if (entryDepths[raycasterId] < 0) { // first entry - raycasterData[raycasterId].position = color.rgb; + raycasterData[raycasterId].position = position; raycasterData[raycasterId].previousJitterDistance = 0; + raycasterData[raycasterId].blend = blend; entryDepths[raycasterId] = depth; raycasterData[raycasterId].scale = -1; } } else if (type < 0) { // exit raycaster int raycasterId = -type - 1; - vec3 localDirection = color.xyz - raycasterData[raycasterId].position; + vec3 localDirection = position - raycasterData[raycasterId].position; raycasterData[raycasterId].direction = safeNormalize(localDirection); raycasterData[raycasterId].scale = safeLength(localDirection) / (depth - entryDepths[raycasterId]); } @@ -183,6 +185,7 @@ void raycast(float raycastDepth, uint raycasterMask, inout vec4 finalColor) { nextStepSize = raycastDepth - currentDepth; #for index, raycaster in raycasters + if ((raycasterMask & #{raycaster.bitmask}) != 0) { RaycasterData data = raycasterData[#{raycaster.id}]; float stepSizeLocal = currentStepSize * data.scale; @@ -195,8 +198,13 @@ void raycast(float raycastDepth, uint raycasterMask, inout vec4 finalColor) { vec4 raycasterContribution = sample#{raycaster.id}(jitteredPosition, data.direction, finalColor, maxStepSizeLocal); float sampleDistance = jitteredStepSizeLocal + data.previousJitterDistance; + uint blend = raycasterData[#{raycaster.id}].blend; - blendStep(finalColor, raycasterContribution, sampleDistance); + if (blend == BLEND_MODE_NORMAL) { + normalBlendStep(finalColor, raycasterContribution, sampleDistance); + } else if (blend == BLEND_MODE_ADDITIVE) { + additiveBlendStep(finalColor, raycasterContribution, sampleDistance); + } raycasterData[#{raycaster.id}].previousJitterDistance = stepSizeLocal - jitteredStepSizeLocal; float maxStepSize = maxStepSizeLocal/data.scale; @@ -224,10 +232,15 @@ void main() { ABufferFragment frag = fragments[i]; int type = _type_(frag); + uint blend = _blend_(frag); if (type == 0) { // geometry fragment vec4 color = _color_(frag); - blend(finalColor, color); + if (blend == BLEND_MODE_NORMAL) { + normalBlend(finalColor, color); + } else if (blend == BLEND_MODE_ADDITIVE) { + additiveBlend(finalColor, color); + } } #if RAYCASTING_ENABLED else if (type > 0) { // enter volume diff --git a/shaders/blending.glsl b/shaders/blending.glsl index 9606abc607..d0e068c960 100644 --- a/shaders/blending.glsl +++ b/shaders/blending.glsl @@ -25,6 +25,52 @@ #ifndef _BLENDING_GLSL_ #define _BLENDING_GLSL_ + +/** + * Blend in src behind dst using normal blending + * dst is premultiplied + * src is expressed in straight RGBA + */ +void normalBlend(inout vec4 dst, vec4 src) { + dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb; + dst.a = dst.a + (1.0 - dst.a) * src.a; +} + +/** + * Blend in src behind dst using additive blending + * dst is premultiplied + * src is expressed in straight RGBA + */ +void additiveBlend(inout vec4 dst, vec4 src) { + dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb;// dst.rgb = dst.rgb + src.a * src.rgb; + //dst.a = dst.a + src.a; +} + + +/** + * Blend in src behind dst using normal blending + * dst is premultiplied + * src is expressed in straight RGBA + * stepSize = 0: alpha becomes 0 + * stepSize = 1: alpha becomes src.a + */ +void normalBlendStep(inout vec4 dst, vec4 src, float stepSize) { + src.a = 1.0 - pow(1.0 - src.a, stepSize); + normalBlend(dst, src); +} + +/** + * Blend in src behind dst using addivtive blending + * dst is premultiplied + * src is expressed in straight RGBA + * stepSize = 0: alpha becomes 0 + * stepSize = 1: alpha becomes src.a + */ +void additiveBlendStep(inout vec4 dst, vec4 src, float stepSize) { + src.a = 1.0 - pow(1.0 - src.a, stepSize); + additiveBlend(dst, src); +} + /** * Blend in src behind dst * dst is premultiplied @@ -47,4 +93,4 @@ void blendStep(inout vec4 dst, vec4 src, float stepSize) { blend(dst, src); } -#endif \ No newline at end of file +#endif diff --git a/shaders/fragment.glsl b/shaders/fragment.glsl index 76ecfccbd5..5064fb4e95 100644 --- a/shaders/fragment.glsl +++ b/shaders/fragment.glsl @@ -25,10 +25,13 @@ #ifndef _FRAGMENT_GLSL_ #define _FRAGMENT_GLSL_ +#define BLEND_MODE_NORMAL 0 +#define BLEND_MODE_ADDITIVE 1 + struct Fragment { vec4 color; float depth; - int blend; + uint blend; }; #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a941baf63..d3c34cdcea 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/rendering/renderable.cpp ${OPENSPACE_BASE_DIR}/src/rendering/renderengine.cpp ${OPENSPACE_BASE_DIR}/src/rendering/renderengine_lua.inl + ${OPENSPACE_BASE_DIR}/src/rendering/transferfunction.cpp ${OPENSPACE_BASE_DIR}/src/scene/ephemeris.cpp ${OPENSPACE_BASE_DIR}/src/scene/scene.cpp ${OPENSPACE_BASE_DIR}/src/scene/scene_lua.inl @@ -135,6 +136,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderer.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderengine.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/volumeraycaster.h + ${OPENSPACE_BASE_DIR}/include/openspace/rendering/transferfunction.h ${OPENSPACE_BASE_DIR}/include/openspace/scene/ephemeris.h ${OPENSPACE_BASE_DIR}/include/openspace/scene/scene.h ${OPENSPACE_BASE_DIR}/include/openspace/scene/scenegraph.h diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index e2e7213ede..00f6a4723a 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -220,12 +220,12 @@ void FramebufferRenderer::updateResolution() { glTexImage2D( GL_TEXTURE_2D, 0, - GL_RGBA, + GL_RGBA16, GLsizei(_resolution.x), GLsizei(_resolution.y), 0, GL_RGBA, - GL_BYTE, + GL_UNSIGNED_SHORT, nullptr); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/src/rendering/transferfunction.cpp b/src/rendering/transferfunction.cpp new file mode 100644 index 0000000000..1bfcb87b0b --- /dev/null +++ b/src/rendering/transferfunction.cpp @@ -0,0 +1,227 @@ +/***************************************************************************************** + * * + * 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. * + ****************************************************************************************/ + +// open space includes +#include + +// ghoul includes +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +namespace { + const std::string _loggerCat = "TransferFunction"; + + ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear; + ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge; + + bool hasExtension (std::string const &filepath, std::string const &extension) + { + std::string ending = "." + extension; + if (filepath.length() > ending.length()) { + return (0 == filepath.compare (filepath.length() - ending.length(), ending.length(), ending)); + } else { + return false; + } + } + +} + + +namespace openspace { +TransferFunction::TransferFunction(const std::string& filepath, TfChangedCallback tfChangedCallback) : _filepath(filepath) { + setPath(filepath); + setCallback(tfChangedCallback); +} + +void TransferFunction::setPath(const std::string& filepath) { + if (_file) { + _file = nullptr; + } + std::string f = absPath(filepath); + if (!FileSys.fileExists(f)) { + LERROR("Could not find transfer function file."); + _file = nullptr; + } + _filepath = f; + _file = std::make_unique(filepath, ghoul::filesystem::File::RawPath::Yes); + _needsUpdate = true; + _file->setCallback([this](const ghoul::filesystem::File& file) { + _needsUpdate = true; + }); +} + +ghoul::opengl::Texture& TransferFunction::getTexture() { + ghoul_assert(_texture != nullptr, "Transfer function is null"); + update(); + return *_texture.get(); +} + +void TransferFunction::update() { + if (_needsUpdate) { + if (hasExtension(_filepath, "txt")) { + setTextureFromTxt(); + } else { + setTextureFromImage(); + } + _texture->uploadTexture(); + _needsUpdate = false; + if (_tfChangedCallback) { + _tfChangedCallback(*this); + } + } +} + +void TransferFunction::setCallback(TfChangedCallback callback) { + _tfChangedCallback = std::move(callback); +} + +void TransferFunction::setTextureFromTxt() { + std::ifstream in; + in.open(_filepath.c_str()); + + if (!in.is_open()) { + LERROR("Could not open file " << _filepath); + return; + } + + int width = 512; + float lower = 0.0f; + float upper = 1.0f; + + std::vector mappingKeys; + + std::string line; + + while (std::getline(in, line)) { + std::istringstream iss(line); + std::string key; + iss >> key; + + if(key == "width") { + iss >> width; + } else if(key == "lower") { + iss >> lower; + lower = glm::clamp(lower, 0.0f, 1.0f); + } else if(key == "upper") { + iss >> upper; + upper = glm::clamp(upper, lower, 1.0f); + } else if(key == "mappingkey") { + float intensity; + glm::vec4 rgba = glm::vec4(0.0f); + iss >> intensity; + for(int i = 0; i < 4; ++i) { + iss >> rgba[i]; + } + mappingKeys.push_back({intensity, rgba}); + } + } + in.close(); + + if (mappingKeys.size() < 1) { + return; + } + + if (mappingKeys.front().position > lower) { + mappingKeys.insert(mappingKeys.begin(), {lower,mappingKeys.front().color}); + } + + if (mappingKeys.back().position < upper) { + mappingKeys.push_back({upper,mappingKeys.back().color}); + } + + // allocate new float array with zeros + float* transferFunction = new float[width*4](); + for (int i = 0; i < 4*width; ++i) { + transferFunction[i] = 0.0f; + } + + size_t lowerIndex = static_cast(floorf(lower*static_cast(width-1))); + size_t upperIndex = static_cast(floorf(upper*static_cast(width-1))); + + auto prevKey = mappingKeys.begin(); + auto currentKey = prevKey + 1; + auto lastKey = mappingKeys.end() -1; + + for (size_t i=lowerIndex; i<=upperIndex; i++) { + float fpos = static_cast(i)/static_cast(width-1); + if (fpos > (*currentKey).position) { + prevKey = currentKey; + currentKey++; + if (currentKey == mappingKeys.end()) { + currentKey = lastKey; + } + } + + float dist = fpos-(*prevKey).position; + float weight = dist/((*currentKey).position-(*prevKey).position); + + for (size_t channel=0; channel<4; ++channel) { + size_t position = 4*i + channel; + // Interpolate linearly between prev and next mapping key + + float value = + ((*prevKey).color[channel]*(1.f-weight) + (*currentKey).color[channel]*weight)/255.f; + transferFunction[position] = value; + } + } + + // no need to deallocate transferFunction. Ownership is transferred to the Texture. + _texture = std::make_unique(transferFunction, + glm::size3_t(width,1,1),ghoul::opengl::Texture::Format::RGBA, + GL_RGBA, GL_FLOAT, filtermode, wrappingmode); +} + +void TransferFunction::setTextureFromImage() { + _texture = ghoul::io::TextureReader::ref().loadTexture(_filepath); + _texture->setWrapping(wrappingmode); +} + +glm::vec4 TransferFunction::sample(size_t offset) { + if (!_texture) return glm::vec4(0.0); + + int nPixels = _texture->width(); + + // Clamp to range. + if (offset >= nPixels) offset = nPixels - 1; + if (offset < 0) offset = 0; + + return _texture->texelAsFloat(offset); +} + +size_t TransferFunction::width() { + update(); + return _texture->width(); +} +} From e4f8f8c830129d24e7c6844ab5f2be195ca64e6b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 11 Apr 2016 11:18:50 -0400 Subject: [PATCH 17/38] Clang compile fixes --- modules/fieldlines/rendering/renderablefieldlines.cpp | 2 +- modules/multiresvolume/rendering/renderablemultiresvolume.h | 2 +- modules/multiresvolume/rendering/tsp.cpp | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/fieldlines/rendering/renderablefieldlines.cpp b/modules/fieldlines/rendering/renderablefieldlines.cpp index 76b18d889a..c22c343cca 100644 --- a/modules/fieldlines/rendering/renderablefieldlines.cpp +++ b/modules/fieldlines/rendering/renderablefieldlines.cpp @@ -225,7 +225,7 @@ void RenderableFieldlines::render(const RenderData& data) { _program->setUniform("modelViewProjection", data.camera.viewProjectionMatrix()); _program->setUniform("modelTransform", glm::mat4(1.0)); _program->setUniform("cameraViewDir", data.camera.viewDirection()); - setPscUniforms(_program.get(), &data.camera, data.position); + setPscUniforms(*_program, data.camera, data.position); _program->setUniform("classification", _classification); if (!_classification) diff --git a/modules/multiresvolume/rendering/renderablemultiresvolume.h b/modules/multiresvolume/rendering/renderablemultiresvolume.h index bf8f23939e..408f5eea0a 100644 --- a/modules/multiresvolume/rendering/renderablemultiresvolume.h +++ b/modules/multiresvolume/rendering/renderablemultiresvolume.h @@ -80,7 +80,7 @@ public: bool isReady() const override; virtual void update(const UpdateData& data) override; - virtual void RenderableMultiresVolume::render(const RenderData& data, RendererTasks& tasks); + virtual void render(const RenderData& data, RendererTasks& tasks); //virtual void preResolve(ghoul::opengl::ProgramObject* program) override; //virtual std::string getHeaderPath() override; //virtual std::string getHelperPath() override; diff --git a/modules/multiresvolume/rendering/tsp.cpp b/modules/multiresvolume/rendering/tsp.cpp index 0aa18704dd..886f903dbe 100644 --- a/modules/multiresvolume/rendering/tsp.cpp +++ b/modules/multiresvolume/rendering/tsp.cpp @@ -22,16 +22,18 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +//#include #include // ghoul #include #include #include +#include // std #include +#include #include namespace { From 6b5681626b99aae16b04d14d7288f48ca51903e4 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 13 Apr 2016 11:46:07 -0400 Subject: [PATCH 18/38] Removing clang-analyze warnings --- ext/ghoul | 2 +- modules/base/ephemeris/spiceephemeris.cpp | 2 +- modules/newhorizons/rendering/renderablefov.cpp | 2 +- .../rendering/renderablemodelprojection.cpp | 2 ++ .../newhorizons/rendering/renderableshadowcylinder.cpp | 10 +++++----- src/rendering/renderengine.cpp | 4 ++-- src/scene/scene.cpp | 3 ++- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index 8a715dd042..1dea593710 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 8a715dd04287864dff4290f6e607e49338f11f2e +Subproject commit 1dea593710eea134006d6059d925f6ab80823683 diff --git a/modules/base/ephemeris/spiceephemeris.cpp b/modules/base/ephemeris/spiceephemeris.cpp index 1d4a2220ec..588607897c 100644 --- a/modules/base/ephemeris/spiceephemeris.cpp +++ b/modules/base/ephemeris/spiceephemeris.cpp @@ -63,7 +63,7 @@ SpiceEphemeris::SpiceEphemeris(const ghoul::Dictionary& dictionary) LERROR("'" << KeyKernels << "' has to be an array-style table"); try { - SpiceManager::KernelHandle id = SpiceManager::ref().loadKernel(kernel); + SpiceManager::ref().loadKernel(kernel); _kernelsLoadedSuccessfully = true; } catch (const SpiceManager::SpiceException& e) { diff --git a/modules/newhorizons/rendering/renderablefov.cpp b/modules/newhorizons/rendering/renderablefov.cpp index d0c5cbb91c..f2131c3da8 100644 --- a/modules/newhorizons/rendering/renderablefov.cpp +++ b/modules/newhorizons/rendering/renderablefov.cpp @@ -258,7 +258,7 @@ psc RenderableFov::checkForIntercept(glm::dvec3 ray) { ipoint = result.surfaceIntercept; ivec = result.surfaceVector; - bool intercepted = result.interceptFound; +// bool intercepted = result.interceptFound; ivec *= 0.9999;// because fov lands exactly on top of surface we need to move it out slightly _interceptVector = PowerScaledCoordinate::CreatePowerScaledCoordinate(ivec[0], ivec[1], ivec[2]); diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp index b8d3bb48c0..c50363f19a 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.cpp +++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp @@ -142,6 +142,7 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di bool s = dictionary.getValue(keyProjAberration, a); _aberration = SpiceManager::AberrationCorrection(a); completeSuccess &= s; + ghoul_assert(completeSuccess, "All neccessary attributes not found in modfile"); openspace::SpiceManager::ref().addFrame(_target, _source); setBoundingSphere(pss(1.f, 9.f)); @@ -159,6 +160,7 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di _sequenceSource = absPath(_sequenceSource); foundSequence = dictionary.getValue(keySequenceType, _sequenceType); + ghoul_assert(foundSequence, "Did not find sequence"); //Important: client must define translation-list in mod file IFF playbook if (dictionary.hasKey(keyTranslation)) { ghoul::Dictionary translationDictionary; diff --git a/modules/newhorizons/rendering/renderableshadowcylinder.cpp b/modules/newhorizons/rendering/renderableshadowcylinder.cpp index 062706fd3a..0df082bec9 100644 --- a/modules/newhorizons/rendering/renderableshadowcylinder.cpp +++ b/modules/newhorizons/rendering/renderableshadowcylinder.cpp @@ -172,11 +172,11 @@ void RenderableShadowCylinder::createCylinder() { double targetEpoch; glm::dvec3 observerPosition; std::vector terminatorPoints; - SpiceManager::TerminatorType t; - if (_terminatorType == "UMBRAL") - t = SpiceManager::TerminatorType::Umbral; - else if (_terminatorType == "PENUMBRAL") - t = SpiceManager::TerminatorType::Penumbral; + SpiceManager::TerminatorType t = SpiceManager::terminatorTypeFromString(_terminatorType); +// if (_terminatorType == "UMBRAL") +// t = SpiceManager::TerminatorType::Umbral; +// else if (_terminatorType == "PENUMBRAL") +// t = SpiceManager::TerminatorType::Penumbral; auto res = SpiceManager::ref().terminatorEllipse(_body, _observer, _bodyFrame, _lightSource, t, _aberration, _time, _numberOfPoints); diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 817290650b..f26fc24f90 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -736,8 +736,8 @@ void RenderEngine::changeViewPoint(std::string origin) { SceneGraphNode* newHorizonsNode = scene()->sceneGraphNode("NewHorizons"); SceneGraphNode* newHorizonsPathNodeJ = scene()->sceneGraphNode("NewHorizonsPathJupiter"); SceneGraphNode* newHorizonsPathNodeP = scene()->sceneGraphNode("NewHorizonsPathPluto"); - SceneGraphNode* cg67pNode = scene()->sceneGraphNode("67P"); - SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta"); +// SceneGraphNode* cg67pNode = scene()->sceneGraphNode("67P"); +// SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta"); RenderablePath* nhPath; diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index d1724f5b50..b33bbebdbb 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -107,11 +107,12 @@ void Scene::update(const UpdateData& data) { if (!_sceneGraphToLoad.empty()) { OsEng.renderEngine().scene()->clearSceneGraph(); try { - bool success = loadSceneInternal(_sceneGraphToLoad); + loadSceneInternal(_sceneGraphToLoad); _sceneGraphToLoad = ""; } catch (const ghoul::RuntimeError& e) { LERROR(e.what()); + _sceneGraphToLoad = ""; return; } } From cf517f53091a946769cb556affaa4aca3e1b3b27 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 14 Apr 2016 10:27:59 -0400 Subject: [PATCH 19/38] Replacing CMake-based version setting with C++-based version Adding function to OpenSpace that returns the license header --- CMakeLists.txt | 1 - include/openspace/openspace.h | 42 ++++++++++++++++++++++++ src/CMakeLists.txt | 2 ++ src/engine/openspaceengine.cpp | 2 +- src/network/parallelconnection.cpp | 2 +- src/openspace.cpp | 52 ++++++++++++++++++++++++++++++ support/cmake/support_macros.cmake | 12 ------- support/cmake/version.template | 11 ------- 8 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 include/openspace/openspace.h create mode 100644 src/openspace.cpp delete mode 100644 support/cmake/version.template diff --git a/CMakeLists.txt b/CMakeLists.txt index f006b1afb6..c08556a2d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,6 @@ include(${GHOUL_BASE_DIR}/support/cmake/CopySharedLibraries.cmake) test_compiler_compatibility() cleanup_project() set_build_output_directories() -configure_openspace_version(0 3 0 "prerelease-8") option(OPENSPACE_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF) diff --git a/include/openspace/openspace.h b/include/openspace/openspace.h new file mode 100644 index 0000000000..c6640e989d --- /dev/null +++ b/include/openspace/openspace.h @@ -0,0 +1,42 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_H__ +#define __OPENSPACE_H__ + +#include + +namespace openspace { + +std::string licenseText(); + +const int OPENSPACE_VERSION_MAJOR = 0; +const int OPENSPACE_VERSION_MINOR = 3; +const int OPENSPACE_VERSION_PATCH = 0; + +const std::string OPENSPACE_VERSION_STRING = "prerelease-8"; + +} // namespace openspace + +#endif // __OPENSPACE_H__ \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc750b659b..f6532392b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,7 @@ ######################################################################################### set(OPENSPACE_SOURCE + ${OPENSPACE_BASE_DIR}/src/openspace.cpp ${OPENSPACE_BASE_DIR}/src/engine/configurationmanager.cpp ${OPENSPACE_BASE_DIR}/src/engine/downloadmanager.cpp ${OPENSPACE_BASE_DIR}/src/engine/logfactory.cpp @@ -90,6 +91,7 @@ set(OPENSPACE_SOURCE ) set(OPENSPACE_HEADER + ${OPENSPACE_BASE_DIR}/include/openspace/openspace.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/configurationmanager.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/downloadmanager.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/logfactory.h diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index c924357c9e..212890124d 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -24,7 +24,7 @@ #include -#include +#include #include #include diff --git a/src/network/parallelconnection.cpp b/src/network/parallelconnection.cpp index 11c5c2b4a2..e7dfa28e43 100644 --- a/src/network/parallelconnection.cpp +++ b/src/network/parallelconnection.cpp @@ -57,7 +57,7 @@ #include #include #include -#include +#include #include //lua functions diff --git a/src/openspace.cpp b/src/openspace.cpp new file mode 100644 index 0000000000..8fa5d3e266 --- /dev/null +++ b/src/openspace.cpp @@ -0,0 +1,52 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +namespace openspace { + +std::string licenseText() { + return "OpenSpace\n\ +\n\ +Copyright (c) 2014-2016\n\ +\n\ +Permission is hereby granted, free of charge, to any person obtaining a copy of this\n\ +software and associated documentation files (the \"Software\"), to deal in the Software\n\ +without restriction, including without limitation the rights to use, copy, modify,\n\ +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to\n\ +permit persons to whom the Software is furnished to do so, subject to the following\n\ +conditions:\n\ +\n\ +The above copyright notice and this permission notice shall be included in all copies\n\ +or substantial portions of the Software.\n\ +\n\ +THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n\ +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\n\ +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n\ +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n\ +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE\n\ +OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; +} + +} // namespace openspace diff --git a/support/cmake/support_macros.cmake b/support/cmake/support_macros.cmake index 0a42c263a9..8e3bb7e588 100644 --- a/support/cmake/support_macros.cmake +++ b/support/cmake/support_macros.cmake @@ -52,18 +52,6 @@ endmacro () -function (configure_openspace_version major_version minor_version patch_version string_version) - set(OPENSPACE_MAJOR_VERSION ${major_version}) - set(OPENSPACE_MINOR_VERSION ${minor_version}) - set(OPENSPACE_PATCH_VERSION ${patch_version}) - set(OPENSPACE_VERSION_STRING ${string_version}) - message(STATUS "Version: ${OPENSPACE_MAJOR_VERSION}.${OPENSPACE_MINOR_VERSION}.${OPENSPACE_PATCH_VERSION} (${OPENSPACE_VERSION_STRING})") - mark_as_advanced(OPENSPACE_MAJOR_VERSION, OPENSPACE_MINOR_VERSION, OPENSPACE_PATCH_VERSION, OPENSPACE_VERSION_STRING) - configure_file(${OPENSPACE_CMAKE_EXT_DIR}/version.template ${CMAKE_BINARY_DIR}/_generated/include/openspace/version.h) -endfunction () - - - function (create_openspace_target) add_library(libOpenSpace STATIC ${OPENSPACE_HEADER} ${OPENSPACE_SOURCE}) target_include_directories(libOpenSpace PUBLIC ${OPENSPACE_BASE_DIR}/include) diff --git a/support/cmake/version.template b/support/cmake/version.template deleted file mode 100644 index ca81b3da2d..0000000000 --- a/support/cmake/version.template +++ /dev/null @@ -1,11 +0,0 @@ -/* This is a file that was automatically generated by CMake */ - -#ifndef __VERSION_H__ -#define __VERSION_H__ - -#define OPENSPACE_VERSION_MAJOR @OPENSPACE_MAJOR_VERSION@ -#define OPENSPACE_VERSION_MINOR @OPENSPACE_MINOR_VERSION@ -#define OPENSPACE_VERSION_PATCH @OPENSPACE_PATCH_VERSION@ -#define OPENSPACE_VERSION_STRING "@OPENSPACE_VERSION_STRING@" - -#endif // __VERSION_H__ From f5012d496dea115eefd56e3c936dc195f1544aa6 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 14 Apr 2016 21:16:25 -0400 Subject: [PATCH 20/38] Compile fix for the SyncWidget in the Launcher --- apps/Launcher/syncwidget.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/Launcher/syncwidget.cpp b/apps/Launcher/syncwidget.cpp index 0710378173..ef92e50b5f 100644 --- a/apps/Launcher/syncwidget.cpp +++ b/apps/Launcher/syncwidget.cpp @@ -26,7 +26,7 @@ #include "infowidget.h" -#include +#include #include #include @@ -138,9 +138,9 @@ SyncWidget::SyncWidget(QWidget* parent, Qt::WindowFlags f) libtorrent::session_settings settings = _session->settings(); settings.user_agent = "OpenSpace/" + - std::to_string(OPENSPACE_VERSION_MAJOR) + "." + - std::to_string(OPENSPACE_VERSION_MINOR) + "." + - std::to_string(OPENSPACE_VERSION_PATCH); + std::to_string(openspace::OPENSPACE_VERSION_MAJOR) + "." + + std::to_string(openspace::OPENSPACE_VERSION_MINOR) + "." + + std::to_string(openspace::OPENSPACE_VERSION_PATCH); settings.allow_multiple_connections_per_ip = true; settings.ignore_limits_on_local_network = true; settings.connection_speed = 20; From dcf5507e1c21e87aa851346bc494ae3be6060d6f Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 14 Apr 2016 21:17:19 -0400 Subject: [PATCH 21/38] Add the images of the plutoprojection into gitignore Add a data directive to the plutoprojection that will download the New Horizons LORRI images --- .gitignore | 1 + data/scene/plutoprojectionhybrid/plutoprojectionhybrid.data | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec3414bf7d..c1004bfa33 100644 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,4 @@ data/scene/vestaprojection/textures/projectMe.png data/spice/MAR063.BSP data/spice/de430_1850-2150.bsp data/spice/jup260.bsp +data/scene/plutoprojectionhybrid/images diff --git a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.data b/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.data index 49e26de6dc..626f2eb2b5 100644 --- a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.data +++ b/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.data @@ -2,6 +2,7 @@ return { FileRequest = { { Identifier = "newhorizons_plutoencounter_pluto_assets", Destination = "assets", Version = 1 }, { Identifier = "newhorizons_plutoencounter_pluto_textures", Destination = "textures", Version = 2 }, - { Identifier = "pluto_textures", Destination = "textures", Version = 2 } + { Identifier = "pluto_textures", Destination = "textures", Version = 2 }, + { Identifier = "newhorizons_plutoencounter_pluto_images", Destination = "images", Version = 1 } }, } \ No newline at end of file From ef2981f5357226c00521f26764a9d53d5e300cc7 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 14 Apr 2016 22:33:28 -0400 Subject: [PATCH 22/38] Enable global variables for module Lua scripts (closing #172) Adapt New Horizons kernels to global switch between accurate and publicly avaiable kernels --- .../charonprojection/charonprojection.mod | 4 +- data/scene/default_nh.scene | 14 +------ data/scene/hydra/hydra.mod | 4 +- data/scene/kerberos/kerberos.mod | 4 +- data/scene/newhorizons/newhorizons.mod | 4 +- data/scene/nix/nix.mod | 4 +- .../plutoprojectionhybrid.mod | 4 +- data/scene/styx/styx.mod | 4 +- ext/ghoul | 2 +- openspace.cfg | 6 +-- src/scene/scenegraph.cpp | 8 +++- src/scripting/scriptengine.cpp | 42 +++++++++---------- 12 files changed, 38 insertions(+), 62 deletions(-) diff --git a/data/scene/charonprojection/charonprojection.mod b/data/scene/charonprojection/charonprojection.mod index 622ed99782..5e1c3ad60c 100644 --- a/data/scene/charonprojection/charonprojection.mod +++ b/data/scene/charonprojection/charonprojection.mod @@ -1,6 +1,4 @@ -UseAccurateKernels = false - -if UseAccurateKernels then +if UseAccurateNewHorizonsKernels then NewHorizonsKernels = { "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" } diff --git a/data/scene/default_nh.scene b/data/scene/default_nh.scene index 5eab7337a7..7eda34bb0f 100644 --- a/data/scene/default_nh.scene +++ b/data/scene/default_nh.scene @@ -1,3 +1,5 @@ +UseAccurateNewHorizonsKernels = false + return { ScenePath = ".", CommonFolder = "common", @@ -14,7 +16,6 @@ return { "saturn", "uranus", "neptune", - --"PlutoProjection", "plutoprojectionhybrid", "charonprojection", "kerberos", @@ -38,17 +39,6 @@ return { "callistoprojection", "newhorizons", "newhorizonsfov", - --"gridGalactic", - --"gridEcliptic", - --"gridEquatorial", - -- "ephemeris", - - -- "newhorizonspath", - -- "newhorizonstrail", - -- "enlil", - -- "volumegl3", - -- "volumegl2", - -- "volumegl", } } diff --git a/data/scene/hydra/hydra.mod b/data/scene/hydra/hydra.mod index f6053a2e61..e6f27bbff5 100644 --- a/data/scene/hydra/hydra.mod +++ b/data/scene/hydra/hydra.mod @@ -1,6 +1,4 @@ -UseAccurateKernels = false - -if UseAccurateKernels then +if UseAccurateNewHorizonsKernels then NewHorizonsKernels = { "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" } diff --git a/data/scene/kerberos/kerberos.mod b/data/scene/kerberos/kerberos.mod index ecb10bb6c8..75720abde4 100644 --- a/data/scene/kerberos/kerberos.mod +++ b/data/scene/kerberos/kerberos.mod @@ -1,6 +1,4 @@ -UseAccurateKernels = false - -if UseAccurateKernels then +if UseAccurateNewHorizonsKernels then NewHorizonsKernels = { "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" } diff --git a/data/scene/newhorizons/newhorizons.mod b/data/scene/newhorizons/newhorizons.mod index 87dacae1a2..a58b2f73f5 100644 --- a/data/scene/newhorizons/newhorizons.mod +++ b/data/scene/newhorizons/newhorizons.mod @@ -1,6 +1,4 @@ -UseAccurateKernels = false - -if UseAccurateKernels then +if UseAccurateNewHorizonsKernels then NewHorizonsKernels = { -- SCLK "${SPICE}/nh_kernels/sclk/new-horizons_0976.tsc", diff --git a/data/scene/nix/nix.mod b/data/scene/nix/nix.mod index 91a11dcd29..8e56474f56 100644 --- a/data/scene/nix/nix.mod +++ b/data/scene/nix/nix.mod @@ -1,6 +1,4 @@ -UseAccurateKernels = false - -if UseAccurateKernels then +if UseAccurateNewHorizonsKernels then NewHorizonsKernels = { "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" } diff --git a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod b/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod index 1ae2d6186e..40e29f35b6 100644 --- a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod +++ b/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod @@ -1,6 +1,4 @@ -UseAccurateKernels = false - -if UseAccurateKernels then +if UseAccurateNewHorizonsKernels then NewHorizonsKernels = { "${SPICE}/nh_kernels/spk/NavPE_de433_od122.bsp", "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" diff --git a/data/scene/styx/styx.mod b/data/scene/styx/styx.mod index 205dafb3fb..56523e95da 100644 --- a/data/scene/styx/styx.mod +++ b/data/scene/styx/styx.mod @@ -1,6 +1,4 @@ -UseAccurateKernels = false - -if UseAccurateKernels then +if UseAccurateNewHorizonsKernels then NewHorizonsKernels = { "${SPICE}/nh_kernels/spk/NavSE_plu047_od122.bsp" } diff --git a/ext/ghoul b/ext/ghoul index 1dea593710..ad456dd4b2 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 1dea593710eea134006d6059d925f6ab80823683 +Subproject commit ad456dd4b273bd9db5a5f7f8f50915fef01b5469 diff --git a/openspace.cfg b/openspace.cfg index db69a9aa85..7cfefd58bd 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -8,11 +8,7 @@ return { -- Sets the scene that is to be loaded by OpenSpace. A scene file is a description -- of all entities that will be visible during an instance of OpenSpace Scene = "${SCENE}/default_nh.scene", - -- Scene = "${SCENE}/default.scene", - -- Scene = "${SCENE}/default-modified.scene", - -- Scene = "${SCENE}/rosetta.scene", - -- Scene = "${SCENE}/dawn.scene", - + Paths = { SGCT = "${BASE_PATH}/config/sgct", SCRIPTS = "${BASE_PATH}/scripts", diff --git a/src/scene/scenegraph.cpp b/src/scene/scenegraph.cpp index 00975b8485..825c6224a1 100644 --- a/src/scene/scenegraph.cpp +++ b/src/scene/scenegraph.cpp @@ -126,10 +126,16 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { if (!success) // There are no modules that are loaded return true; - + lua_State* state = ghoul::lua::createNewLuaState(); OsEng.scriptEngine().initializeLuaState(state); + // Above we generated a ghoul::Dictionary from the scene file; now we run the scene + // file again to load any variables defined inside into the state that is passed to + // the modules. This allows us to specify global variables that can then be used + // inside the modules to toggle settings + ghoul::lua::runScriptFile(state, absSceneFile); + // Get the common directory bool commonFolderSpecified = sceneDictionary.hasKey(KeyCommonFolder); bool commonFolderCorrectType = sceneDictionary.hasKeyAndValue(KeyCommonFolder); diff --git a/src/scripting/scriptengine.cpp b/src/scripting/scriptengine.cpp index c0f7c2c6f7..753d0db2fb 100644 --- a/src/scripting/scriptengine.cpp +++ b/src/scripting/scriptengine.cpp @@ -141,22 +141,20 @@ bool ScriptEngine::runScript(const std::string& script) { return false; } - int status = luaL_loadstring(_state, script.c_str()); - if (status != LUA_OK) { - LERROR("Error loading script: '" << lua_tostring(_state, -1) << "'"); + try { + ghoul::lua::runScript(_state, script); + } + catch (const ghoul::lua::LuaLoadingException& e) { + LERRORC(e.component, e.message); + return false; + } + catch (const ghoul::lua::LuaExecutionException& e) { + LERRORC(e.component, e.message); return false; } - //LDEBUG("Executing script"); - //LINFO(script); - if (lua_pcall(_state, 0, LUA_MULTRET, 0)) { - LERROR("Error executing script: " << lua_tostring(_state, -1)); - return false; - } - - //if we're currently hosting the parallel session, find out if script should be synchronized. - if (OsEng.parallelConnection().isHost()){ - + // if we're currently hosting the parallel session, find out if script should be synchronized. + if (OsEng.parallelConnection().isHost()) { std::string lib, func; if (parseLibraryAndFunctionNames(lib, func, script) && shouldScriptBeSent(lib, func)){ // OsEng.parallelConnection()->sendScript(script); @@ -177,18 +175,18 @@ bool ScriptEngine::runScriptFile(const std::string& filename) { return false; } - int status = luaL_loadfile(_state, filename.c_str()); - if (status != LUA_OK) { - LERROR("Error loading script: '" << lua_tostring(_state, -1) << "'"); + try { + ghoul::lua::runScriptFile(_state, filename); + } + catch (const ghoul::lua::LuaLoadingException& e) { + LERRORC(e.component, e.message); + return false; + } + catch (const ghoul::lua::LuaExecutionException& e) { + LERRORC(e.component, e.message); return false; } - LDEBUG("Executing script '" << filename << "'"); - if (lua_pcall(_state, 0, LUA_MULTRET, 0)) { - LERROR("Error executing script: " << lua_tostring(_state, -1)); - return false; - } - return true; } From b43a454e9ffdbe384fd445b19c87e51e792c062e Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 14 Apr 2016 22:40:25 -0400 Subject: [PATCH 23/38] Fix GCC compiler warnings --- include/openspace/util/spicemanager.h | 24 ++++++++++++------------ include/openspace/util/time.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h index bc18dd88bc..a5a8f1d73c 100644 --- a/include/openspace/util/spicemanager.h +++ b/include/openspace/util/spicemanager.h @@ -142,7 +142,7 @@ public: * UMBRAL and PENUMBRAL. All other values will result in an * exception. * \param type The terminator type - * \param The terminator type enum + * \return The terminator type enum * \throws std::out_of_range if \p type is not a valid string * \pre \p type must not be empty */ @@ -519,10 +519,8 @@ public: * compute the intercept * \param ephemerisTime Intercept time in ephemeris seconds past J2000 TDB * \param directionVector Probing ray's direction - * \param surfaceIntercept Surface intercept point on the target body - * \param surfaceVector Vector from observer to intercept point - * \param isVisible Flag indicating whether intercept was found - * \return true if not error occurred, false otherwise + * \return A SurfaceInterceptResult structure that contains all information about the + * intercept, including whether an intercept was found * \throws SpiceException If the \p target or \p observer do not name the same * NAIF object, the \p target or \p observer name the same NAIF object or are in the * same location, the \p referenceFrame or \p fovFrame are not recognized, @@ -618,11 +616,12 @@ public: * \param referenceFrame The reference frame of the output position vector * \param aberrationCorrection The aberration correction method * \param ephemerisTime The time at which the position is to be queried - * \return A TargetStateResult object that contains the position>, containing - * the position of the target; the velocity, containing the velocity of - * the target; and the lightTime, containing the one-way light time - * between the \p target and the \p observer. This method is only set if the - * \p aberrationCorrection is set to a valid different from AberrationCorrection::None + * \return A TargetStateResult object that contains the position, + * containing the position of the target; the velocity, containing the + * velocity of the target; and the lightTime, containing the one-way + * light time between the \p target and the \p observer. This method is only set if + * the \p aberrationCorrection is set to a valid different from + * AberrationCorrection::None * \throws SpiceException If the \p target or \p observer do not name a valid * NAIF object, the \p referenceFrame is not a valid frame, or if there is * insufficient kernel information. @@ -770,8 +769,9 @@ public: * surface that is completely illuminated. Note that in astronomy references, the * unqualified word "terminator" refers to the umbral terminator. * \param aberrationCorrection The aberration correction method that is used - * \param numberOfPoints The number of points along terminator that should be computed - * by this method + * \param ephemerisTime The time at which the terminator ellipse shall be computed + * \param numberOfTerminatorPoints The number of points along terminator that should + * be computed by this method * \return A TerminatorEllipseResult structure that contains all outputs of this * function * \throws SpiceException If the \p target, \p observer, or \p lightSource are diff --git a/include/openspace/util/time.h b/include/openspace/util/time.h index 38a8242033..44f279bc8d 100644 --- a/include/openspace/util/time.h +++ b/include/openspace/util/time.h @@ -142,8 +142,8 @@ public: * Sets the pause function, i.e. setting the deltaTime to 0 (pause = * true) and restoring it when the function is called with a parameter of * false. - * \param If true, the simulation time stops; if false, the - * simulation time continues at the previous rate + * \param pause If true, the simulation time stops; + * if false, the simulation time continues at the previous rate */ void setPause(bool pause); From 46b207b379a3c9e9f8297f327f6b2a2a5e824960 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 14 Apr 2016 22:49:03 -0400 Subject: [PATCH 24/38] Removing some cppcheck warnings --- apps/OpenSpace/main.cpp | 2 +- apps/TimelineView/mainwindow.cpp | 4 ++-- apps/TimelineView/timelinewidget.cpp | 15 +++++---------- include/openspace/util/spicemanager.h | 2 +- src/util/spicemanager.cpp | 2 +- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 753aa07ed3..4dcf2495ef 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -199,7 +199,7 @@ void mainInitFunc() { size_t nWindows = _sgctEngine->getNumberOfWindows(); for (size_t i = 0; i < nWindows; ++i) { sgct::SGCTWindow* w = _sgctEngine->getWindowPtr(i); - size_t nViewports = nViewports = w->getNumberOfViewports(); + size_t nViewports = w->getNumberOfViewports(); for (size_t j = 0; j < nViewports; ++j) { sgct_core::Viewport* v = w->getViewport(j); ghoul_assert(v != nullptr, "Number of reported viewports was incorrect"); diff --git a/apps/TimelineView/mainwindow.cpp b/apps/TimelineView/mainwindow.cpp index bbf66f7e8c..54bec61456 100644 --- a/apps/TimelineView/mainwindow.cpp +++ b/apps/TimelineView/mainwindow.cpp @@ -138,7 +138,7 @@ void MainWindow::readTcpData() { static const uint16_t MessageTypePlayBookHongKang = 4; QByteArray data = continuousData.append(_socket->readAll()); - int d = data.size(); +// int d = data.size(); if (QString(data) == "Connected to SGCT!\r\n") { continuousData.clear(); @@ -191,7 +191,7 @@ void MainWindow::readTcpData() { case MessageTypePlayBookHongKang: case MessageTypePlayBookLabel: { - const char* payloadDebug = data.mid(2).data(); +// const char* payloadDebug = data.mid(2).data(); size_t beginning = 0; uint32_t size = readFromBuffer(data.mid(2).data(), beginning); diff --git a/apps/TimelineView/timelinewidget.cpp b/apps/TimelineView/timelinewidget.cpp index aa25576041..791e90dba1 100644 --- a/apps/TimelineView/timelinewidget.cpp +++ b/apps/TimelineView/timelinewidget.cpp @@ -78,6 +78,7 @@ namespace { TimelineWidget::TimelineWidget(QWidget* parent) : QWidget(parent) + , _currentTime{"", 0.0} { setMinimumWidth(600); setMinimumHeight(600); @@ -152,17 +153,14 @@ void TimelineWidget::drawContent(QPainter& painter, QRectF rect) { } void TimelineWidget::drawLegend(QPainter& painter, QRectF rect) { - static const int HalfHeight = LegendHeight / 2; static const int Padding = 5; static const int BoxSize = 20; - // Draw Targets int currentHorizontalPosition = Padding; - int currentVerticalPosition = Padding; + int currentVerticalPosition = Padding + BoxSize + Padding; + // Draw Targets // Draw Instruments - currentHorizontalPosition = Padding; - currentVerticalPosition = Padding + BoxSize + Padding; for (int i = 0; i < _instruments.size(); ++i) { if (i == _instruments.size() / 3 || i == _instruments.size() * 2 / 3) { currentVerticalPosition += BoxSize + Padding; @@ -179,7 +177,7 @@ void TimelineWidget::drawLegend(QPainter& painter, QRectF rect) { painter.setPen(QPen(QColor(200, 200, 200))); //painter.setPen(QPen(Qt::black)); painter.drawText(currentHorizontalPosition, currentVerticalPosition + BoxSize / 2 + TextOffset, InstrumentConversion[QString::fromStdString(instrument)]); - int textWidth = painter.boundingRect(QRect(), QString::fromStdString(instrument)).width(); +// int textWidth = painter.boundingRect(QRect(), QString::fromStdString(instrument)).width(); //currentHorizontalPosition += std::max(textWidth, 25) + Padding; currentHorizontalPosition += 125; } @@ -198,9 +196,6 @@ void TimelineWidget::drawImages( std::vector images, double minimumTime, double maximumTime) { - int width = timelineRect.width(); - - int nInstruments = 0; std::set instrumentSet; for (Image* i : images) { for (std::string instrument : i->instruments) @@ -225,7 +220,7 @@ void TimelineWidget::drawImages( std::string target = i->target; auto it = std::find(_targets.begin(), _targets.end(), target); - int iTarget = std::distance(_targets.begin(), it); +// int iTarget = std::distance(_targets.begin(), it); for (std::string instrument : i->instruments) { auto it = std::find(_instruments.begin(), _instruments.end(), instrument); diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h index a5a8f1d73c..4e0eb64fcf 100644 --- a/include/openspace/util/spicemanager.h +++ b/include/openspace/util/spicemanager.h @@ -807,7 +807,7 @@ public: * \return the frame of the body * \todo I think this function should die ---abock */ - std::string frameFromBody(const std::string body) const; + std::string frameFromBody(const std::string& body) const; private: /// Struct storing the information about all loaded kernels diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index 45f3b5e293..bf57fc843c 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -832,7 +832,7 @@ bool SpiceManager::addFrame(std::string body, std::string frame) { } } -std::string SpiceManager::frameFromBody(const std::string body) const { +std::string SpiceManager::frameFromBody(const std::string& body) const { for (auto pair : _frameByBody) { if (pair.first == body) { return pair.second; From 588bc74a8842ea388f951c82db89e6a53c0774b9 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 15 Apr 2016 09:52:08 -0400 Subject: [PATCH 25/38] Enable subdirectories for modules Move newhorizons scene modules into subdirectories --- .gitignore | 49 ++++--- data/scene/default_nh.scene | 31 ++--- .../callistoprojection.data | 0 .../callistoprojection/callistoprojection.mod | 0 .../textures/Callisto-Text.png | Bin .../textures/defaultProj.png | Bin .../europaprojection/europaprojection.data | 0 .../europaprojection/europaprojection.mod | 0 .../europaprojection/textures/Europa-Text.png | Bin .../europaprojection/textures/defaultProj.png | Bin .../ganymedeprojection.data | 0 .../ganymedeprojection/ganymedeprojection.mod | 0 .../textures/Ganymede-Text.png | Bin .../textures/defaultProj.png | Bin .../jupiter}/ioprojection/ioprojection.data | 0 .../jupiter}/ioprojection/ioprojection.mod | 0 .../ioprojection/textures/Io-Text.png | Bin .../ioprojection/textures/defaultProj.png | Bin .../ProjectionsOfInterest.torrent | 0 .../jupiterprojection/jupiterprojection.data | 0 .../jupiterprojection/jupiterprojection.mod | 0 .../jupiter}/jupiterprojection/textures/1.jpg | Bin .../jupiter}/jupiterprojection/textures/2.jpg | Bin .../jupiter}/jupiterprojection/textures/3.jpg | Bin .../textures/Jupiter-text.png | Bin .../textures/defaultProj.png | Bin .../textures/defaultProj2.png | Bin .../textures/europaRise1.jpg | Bin .../textures/europaRise2.jpg | Bin .../jupiterprojection/textures/grid.jpg | Bin .../jupiterprojection/textures/jupiter.jpg | Bin .../textures/jupiterFlipped.jpg | Bin .../textures/jupiterFlipped_low.jpg | Bin .../lor_0034817584_0x630_sci_1.fit.jpg | Bin .../lor_0034817654_0x630_sci_1.fit.jpg | Bin .../textures/lor_0034817724_0x630_sci_1.jpg | Bin .../lor_0034817794_0x630_sci_1.fit.jpg | Bin .../jupiterprojection/textures/lorriTest1.jpg | Bin .../jupiterprojection/textures/lorriTest2.jpg | Bin .../jupiterprojection/textures/scope.png | Bin .../jupiterprojection/textures/show.jpg | Bin .../jupiterprojection/textures/show_3072.jpg | Bin .../jupiterprojection/textures/small.jpg | Bin .../jupiterprojection/textures/small.png | Bin .../jupiterprojection/textures/test.jpg | Bin .../NewHorizonsKernels.torrent | Bin .../{ => newhorizons}/jup260.bsp.torrent | Bin .../{ => newhorizons}/newhorizons.data | 0 .../{ => newhorizons}/newhorizons.mod | 4 +- .../newhorizonsfov/newhorizonsfov.mod | 0 .../newhorizonsfov/textures/glare.png | Bin .../newhorizonsfov/textures/glare_blue.png | Bin .../newhorizonspath/newhorizonspath.mod | 0 .../newhorizonspath/textures/glare.png | Bin .../newhorizonspath/textures/glare_blue.png | Bin .../newhorizonstrail/newhorizonstrail.mod | 0 .../newhorizonstrail/textures/glare.png | Bin .../newhorizonstrail/textures/glare_blue.png | Bin .../charonprojection/charonprojection.data | 0 .../charonprojection/charonprojection.mod | 0 .../{ => newhorizons/pluto}/hydra/hydra.mod | 0 .../pluto}/hydra/textures/Hydra-Text.png | Bin .../pluto}/hydra/textures/gray.jpg | Bin .../pluto}/kerberos/kerberos.mod | 0 .../kerberos/textures/Kerberos-Text.png | Bin .../pluto}/kerberos/textures/gray.jpg | Bin .../scene/{ => newhorizons/pluto}/nix/nix.mod | 0 .../pluto}/nix/textures/Nix-Text.png | Bin .../pluto}/nix/textures/gray.jpg | Bin .../plutoprojectionhybrid.data | 0 .../plutoprojectionhybrid.mod | 0 .../{ => newhorizons/pluto}/styx/styx.mod | 0 .../pluto}/styx/textures/Styx-Text.png | Bin .../pluto}/styx/textures/gray.jpg | Bin ext/ghoul | 2 +- src/scene/scenegraph.cpp | 123 ++++++++++-------- 76 files changed, 108 insertions(+), 101 deletions(-) rename data/scene/{ => newhorizons/jupiter}/callistoprojection/callistoprojection.data (100%) rename data/scene/{ => newhorizons/jupiter}/callistoprojection/callistoprojection.mod (100%) rename data/scene/{ => newhorizons/jupiter}/callistoprojection/textures/Callisto-Text.png (100%) rename data/scene/{ => newhorizons/jupiter}/callistoprojection/textures/defaultProj.png (100%) rename data/scene/{ => newhorizons/jupiter}/europaprojection/europaprojection.data (100%) rename data/scene/{ => newhorizons/jupiter}/europaprojection/europaprojection.mod (100%) rename data/scene/{ => newhorizons/jupiter}/europaprojection/textures/Europa-Text.png (100%) rename data/scene/{ => newhorizons/jupiter}/europaprojection/textures/defaultProj.png (100%) rename data/scene/{ => newhorizons/jupiter}/ganymedeprojection/ganymedeprojection.data (100%) rename data/scene/{ => newhorizons/jupiter}/ganymedeprojection/ganymedeprojection.mod (100%) rename data/scene/{ => newhorizons/jupiter}/ganymedeprojection/textures/Ganymede-Text.png (100%) rename data/scene/{ => newhorizons/jupiter}/ganymedeprojection/textures/defaultProj.png (100%) rename data/scene/{ => newhorizons/jupiter}/ioprojection/ioprojection.data (100%) rename data/scene/{ => newhorizons/jupiter}/ioprojection/ioprojection.mod (100%) rename data/scene/{ => newhorizons/jupiter}/ioprojection/textures/Io-Text.png (100%) rename data/scene/{ => newhorizons/jupiter}/ioprojection/textures/defaultProj.png (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/ProjectionsOfInterest.torrent (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/jupiterprojection.data (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/jupiterprojection.mod (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/1.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/2.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/3.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/Jupiter-text.png (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/defaultProj.png (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/defaultProj2.png (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/europaRise1.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/europaRise2.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/grid.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/jupiter.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/jupiterFlipped.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/jupiterFlipped_low.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/lor_0034817584_0x630_sci_1.fit.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/lor_0034817654_0x630_sci_1.fit.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/lor_0034817724_0x630_sci_1.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/lor_0034817794_0x630_sci_1.fit.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/lorriTest1.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/lorriTest2.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/scope.png (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/show.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/show_3072.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/small.jpg (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/small.png (100%) rename data/scene/{ => newhorizons/jupiter}/jupiterprojection/textures/test.jpg (100%) rename data/scene/newhorizons/{ => newhorizons}/NewHorizonsKernels.torrent (100%) rename data/scene/newhorizons/{ => newhorizons}/jup260.bsp.torrent (100%) rename data/scene/newhorizons/{ => newhorizons}/newhorizons.data (100%) rename data/scene/newhorizons/{ => newhorizons}/newhorizons.mod (97%) rename data/scene/{ => newhorizons}/newhorizonsfov/newhorizonsfov.mod (100%) rename data/scene/{ => newhorizons}/newhorizonsfov/textures/glare.png (100%) rename data/scene/{ => newhorizons}/newhorizonsfov/textures/glare_blue.png (100%) rename data/scene/{ => newhorizons}/newhorizonspath/newhorizonspath.mod (100%) rename data/scene/{ => newhorizons}/newhorizonspath/textures/glare.png (100%) rename data/scene/{ => newhorizons}/newhorizonspath/textures/glare_blue.png (100%) rename data/scene/{ => newhorizons}/newhorizonstrail/newhorizonstrail.mod (100%) rename data/scene/{ => newhorizons}/newhorizonstrail/textures/glare.png (100%) rename data/scene/{ => newhorizons}/newhorizonstrail/textures/glare_blue.png (100%) rename data/scene/{ => newhorizons/pluto}/charonprojection/charonprojection.data (100%) rename data/scene/{ => newhorizons/pluto}/charonprojection/charonprojection.mod (100%) rename data/scene/{ => newhorizons/pluto}/hydra/hydra.mod (100%) rename data/scene/{ => newhorizons/pluto}/hydra/textures/Hydra-Text.png (100%) rename data/scene/{ => newhorizons/pluto}/hydra/textures/gray.jpg (100%) rename data/scene/{ => newhorizons/pluto}/kerberos/kerberos.mod (100%) rename data/scene/{ => newhorizons/pluto}/kerberos/textures/Kerberos-Text.png (100%) rename data/scene/{ => newhorizons/pluto}/kerberos/textures/gray.jpg (100%) rename data/scene/{ => newhorizons/pluto}/nix/nix.mod (100%) rename data/scene/{ => newhorizons/pluto}/nix/textures/Nix-Text.png (100%) rename data/scene/{ => newhorizons/pluto}/nix/textures/gray.jpg (100%) rename data/scene/{ => newhorizons/pluto}/plutoprojectionhybrid/plutoprojectionhybrid.data (100%) rename data/scene/{ => newhorizons/pluto}/plutoprojectionhybrid/plutoprojectionhybrid.mod (100%) rename data/scene/{ => newhorizons/pluto}/styx/styx.mod (100%) rename data/scene/{ => newhorizons/pluto}/styx/textures/Styx-Text.png (100%) rename data/scene/{ => newhorizons/pluto}/styx/textures/gray.jpg (100%) diff --git a/.gitignore b/.gitignore index c1004bfa33..150deb205c 100644 --- a/.gitignore +++ b/.gitignore @@ -40,16 +40,15 @@ gui/externaltimecontrol/CMakeLists.txt gui/externaltimecontrol/main.cpp gui/externaltimecontrol/mainwindow.cpp gui/externaltimecontrol/mainwindow.h -include/openspace/version.h data/scene/67P/obj/67P_rotated_5_130.obj data/spice/NewHorizonsKernels/ data/spice/RosettaKernels/ -data/scene/plutoprojectionhybrid/textures/ -data/scene/plutoprojectionhybrid/textures/Shenk_180.jpg -data/scene/plutoprojectionhybrid/textures/barycenter.png -data/scene/plutoprojectionhybrid/textures/defaultProj.png -data/scene/plutoprojectionhybrid/textures/pluto_highres_180.jpg -data/scene/plutoprojectionhybrid/utcEvents.txt +data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/ +data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/Shenk_180.jpg +data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/barycenter.png +data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/defaultProj.png +data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/pluto_highres_180.jpg +data/scene/newhorizons/pluto/plutoprojectionhybrid/utcEvents.txt data/scene/rosetta/obj/mainbodyros.obj data/scene/rosetta/obj/solarpanelleft.obj data/scene/rosetta/obj/solarpanelright.obj @@ -69,7 +68,7 @@ data/scene/uranus/textures/uranus.jpg data/scene/venus/textures/venus.jpg data/scene/vestaprojection/VestaComet/VestaComet_5000.obj data/spice/DawnKernels/ -data/scene/jupiterprojection/ProjectionsOfInterest/ +data/scene/newhorizons/jupiter/jupiterprojection/ProjectionsOfInterest/ data/scene/67P/textures/black.jpg data/scene/67P/textures/defaultProj.jpg data/scene/67P/textures/gray.jpg @@ -77,12 +76,12 @@ data/scene/67P/textures/gray.png data/scene/67P/textures/texmapflipped.jpg data/scene/67P/textures/white.jpg data/scene/67P/textures/white.png -data/scene/callistoprojection/textures/callisto.jpg +data/scene/newhorizons/jupiter/callistoprojection/textures/callisto.jpg data/scene/ceres/textures/gray.png -data/scene/charonprojection/textures/Charon-Text.png -data/scene/charonprojection/textures/charon_highres.jpg -data/scene/charonprojection/textures/charon_highres_annotated.jpg -data/scene/charonprojection/textures/defaultProj.png +data/scene/newhorizons/pluto/charonprojection/textures/Charon-Text.png +data/scene/newhorizons/pluto/charonprojection/textures/charon_highres.jpg +data/scene/newhorizons/pluto/charonprojection/textures/charon_highres_annotated.jpg +data/scene/newhorizons/pluto/charonprojection/textures/defaultProj.png data/scene/dawn/obj/mainbodydawn.obj data/scene/dawn/obj/solarpanelleft.obj data/scene/dawn/obj/solarpanelright.obj @@ -93,25 +92,25 @@ data/scene/earth/textures/earth_bluemarble.jpg data/scene/earth/textures/earth_bluemarble_height.jpg data/scene/earth/textures/earth_night.jpg data/scene/earth/textures/marker.png -data/scene/europaprojection/textures/europa.jpg -data/scene/ganymedeprojection/textures/ganymede.jpg -data/scene/ioprojection/textures/io.jpg +data/scene/newhorizons/jupiter/europaprojection/textures/europa.jpg +data/scene/newhorizons/jupiter/ganymedeprojection/textures/ganymede.jpg +data/scene/newhorizons/jupiter/ioprojection/textures/io.jpg data/scene/jupiter/textures/jupiter.jpg data/scene/mars/textures/mars.jpg data/scene/mercury/textures/mercury.jpg data/scene/milkyway/textures/DarkUniverse_mellinger_8k.jpg data/scene/neptune/textures/neptune.jpg -data/scene/newhorizons/models/Labels.obj -data/scene/newhorizons/models/NewHorizonsCleanModel.obj -data/scene/newhorizons/textures/NHTextureFlipCol.jpg -data/scene/newhorizons/textures/goldfoilbump.tif -data/scene/newhorizons/textures/labels.png +data/scene/newhorizons/newhorizons/models/Labels.obj +data/scene/newhorizons/newhorizons/models/NewHorizonsCleanModel.obj +data/scene/newhorizons/newhorizons/textures/NHTextureFlipCol.jpg +data/scene/newhorizons/newhorizons/textures/goldfoilbump.tif +data/scene/newhorizons/newhorizons/textures/labels.png data/scene/pluto/textures/ data/scene/pluto/textures/Shenk_180.jpg data/scene/pluto/textures/pluto_highres_180.jpg -data/scene/plutoprojectionhybrid/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt -data/scene/plutoprojectionhybrid/textures/3.jpg -data/scene/plutoprojectionhybrid/textures/Pluto-Text.png +data/scene/newhorizons/pluto/plutoprojectionhybrid/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt +data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/3.jpg +data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/Pluto-Text.png data/scene/vestaprojection/VestaComet/VestaComet.mtl data/scene/vestaprojection/textures/defaultProj_backup.png data/scene/vestaprojection/textures/dummy.jpg @@ -120,4 +119,4 @@ data/scene/vestaprojection/textures/projectMe.png data/spice/MAR063.BSP data/spice/de430_1850-2150.bsp data/spice/jup260.bsp -data/scene/plutoprojectionhybrid/images +data/scene/newhorizons/pluto/plutoprojectionhybrid/images diff --git a/data/scene/default_nh.scene b/data/scene/default_nh.scene index 7eda34bb0f..07cd84a34f 100644 --- a/data/scene/default_nh.scene +++ b/data/scene/default_nh.scene @@ -16,29 +16,24 @@ return { "saturn", "uranus", "neptune", - "plutoprojectionhybrid", - "charonprojection", - "kerberos", - "nix", - "styx", - "hydra", + "newhorizons/pluto/plutoprojectionhybrid", + "newhorizons/pluto/charonprojection", + "newhorizons/pluto/kerberos", + "newhorizons/pluto/nix", + "newhorizons/pluto/styx", + "newhorizons/pluto/hydra", "stars", -- "stars-denver", "milkyway", -- "milkyway-eso", "imageplane", - --"constellationbounds", - --"io", - --"europa", - --"ganymede", - --"callisto", - "jupiterprojection", - "ioprojection", - "europaprojection", - "ganymedeprojection", - "callistoprojection", - "newhorizons", - "newhorizonsfov", + "newhorizons/jupiter/jupiterprojection", + "newhorizons/jupiter/ioprojection", + "newhorizons/jupiter/europaprojection", + "newhorizons/jupiter/ganymedeprojection", + "newhorizons/jupiter/callistoprojection", + "newhorizons/newhorizons", + "newhorizons/newhorizonsfov", } } diff --git a/data/scene/callistoprojection/callistoprojection.data b/data/scene/newhorizons/jupiter/callistoprojection/callistoprojection.data similarity index 100% rename from data/scene/callistoprojection/callistoprojection.data rename to data/scene/newhorizons/jupiter/callistoprojection/callistoprojection.data diff --git a/data/scene/callistoprojection/callistoprojection.mod b/data/scene/newhorizons/jupiter/callistoprojection/callistoprojection.mod similarity index 100% rename from data/scene/callistoprojection/callistoprojection.mod rename to data/scene/newhorizons/jupiter/callistoprojection/callistoprojection.mod diff --git a/data/scene/callistoprojection/textures/Callisto-Text.png b/data/scene/newhorizons/jupiter/callistoprojection/textures/Callisto-Text.png similarity index 100% rename from data/scene/callistoprojection/textures/Callisto-Text.png rename to data/scene/newhorizons/jupiter/callistoprojection/textures/Callisto-Text.png diff --git a/data/scene/callistoprojection/textures/defaultProj.png b/data/scene/newhorizons/jupiter/callistoprojection/textures/defaultProj.png similarity index 100% rename from data/scene/callistoprojection/textures/defaultProj.png rename to data/scene/newhorizons/jupiter/callistoprojection/textures/defaultProj.png diff --git a/data/scene/europaprojection/europaprojection.data b/data/scene/newhorizons/jupiter/europaprojection/europaprojection.data similarity index 100% rename from data/scene/europaprojection/europaprojection.data rename to data/scene/newhorizons/jupiter/europaprojection/europaprojection.data diff --git a/data/scene/europaprojection/europaprojection.mod b/data/scene/newhorizons/jupiter/europaprojection/europaprojection.mod similarity index 100% rename from data/scene/europaprojection/europaprojection.mod rename to data/scene/newhorizons/jupiter/europaprojection/europaprojection.mod diff --git a/data/scene/europaprojection/textures/Europa-Text.png b/data/scene/newhorizons/jupiter/europaprojection/textures/Europa-Text.png similarity index 100% rename from data/scene/europaprojection/textures/Europa-Text.png rename to data/scene/newhorizons/jupiter/europaprojection/textures/Europa-Text.png diff --git a/data/scene/europaprojection/textures/defaultProj.png b/data/scene/newhorizons/jupiter/europaprojection/textures/defaultProj.png similarity index 100% rename from data/scene/europaprojection/textures/defaultProj.png rename to data/scene/newhorizons/jupiter/europaprojection/textures/defaultProj.png diff --git a/data/scene/ganymedeprojection/ganymedeprojection.data b/data/scene/newhorizons/jupiter/ganymedeprojection/ganymedeprojection.data similarity index 100% rename from data/scene/ganymedeprojection/ganymedeprojection.data rename to data/scene/newhorizons/jupiter/ganymedeprojection/ganymedeprojection.data diff --git a/data/scene/ganymedeprojection/ganymedeprojection.mod b/data/scene/newhorizons/jupiter/ganymedeprojection/ganymedeprojection.mod similarity index 100% rename from data/scene/ganymedeprojection/ganymedeprojection.mod rename to data/scene/newhorizons/jupiter/ganymedeprojection/ganymedeprojection.mod diff --git a/data/scene/ganymedeprojection/textures/Ganymede-Text.png b/data/scene/newhorizons/jupiter/ganymedeprojection/textures/Ganymede-Text.png similarity index 100% rename from data/scene/ganymedeprojection/textures/Ganymede-Text.png rename to data/scene/newhorizons/jupiter/ganymedeprojection/textures/Ganymede-Text.png diff --git a/data/scene/ganymedeprojection/textures/defaultProj.png b/data/scene/newhorizons/jupiter/ganymedeprojection/textures/defaultProj.png similarity index 100% rename from data/scene/ganymedeprojection/textures/defaultProj.png rename to data/scene/newhorizons/jupiter/ganymedeprojection/textures/defaultProj.png diff --git a/data/scene/ioprojection/ioprojection.data b/data/scene/newhorizons/jupiter/ioprojection/ioprojection.data similarity index 100% rename from data/scene/ioprojection/ioprojection.data rename to data/scene/newhorizons/jupiter/ioprojection/ioprojection.data diff --git a/data/scene/ioprojection/ioprojection.mod b/data/scene/newhorizons/jupiter/ioprojection/ioprojection.mod similarity index 100% rename from data/scene/ioprojection/ioprojection.mod rename to data/scene/newhorizons/jupiter/ioprojection/ioprojection.mod diff --git a/data/scene/ioprojection/textures/Io-Text.png b/data/scene/newhorizons/jupiter/ioprojection/textures/Io-Text.png similarity index 100% rename from data/scene/ioprojection/textures/Io-Text.png rename to data/scene/newhorizons/jupiter/ioprojection/textures/Io-Text.png diff --git a/data/scene/ioprojection/textures/defaultProj.png b/data/scene/newhorizons/jupiter/ioprojection/textures/defaultProj.png similarity index 100% rename from data/scene/ioprojection/textures/defaultProj.png rename to data/scene/newhorizons/jupiter/ioprojection/textures/defaultProj.png diff --git a/data/scene/jupiterprojection/ProjectionsOfInterest.torrent b/data/scene/newhorizons/jupiter/jupiterprojection/ProjectionsOfInterest.torrent similarity index 100% rename from data/scene/jupiterprojection/ProjectionsOfInterest.torrent rename to data/scene/newhorizons/jupiter/jupiterprojection/ProjectionsOfInterest.torrent diff --git a/data/scene/jupiterprojection/jupiterprojection.data b/data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.data similarity index 100% rename from data/scene/jupiterprojection/jupiterprojection.data rename to data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.data diff --git a/data/scene/jupiterprojection/jupiterprojection.mod b/data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.mod similarity index 100% rename from data/scene/jupiterprojection/jupiterprojection.mod rename to data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.mod diff --git a/data/scene/jupiterprojection/textures/1.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/1.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/1.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/1.jpg diff --git a/data/scene/jupiterprojection/textures/2.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/2.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/2.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/2.jpg diff --git a/data/scene/jupiterprojection/textures/3.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/3.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/3.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/3.jpg diff --git a/data/scene/jupiterprojection/textures/Jupiter-text.png b/data/scene/newhorizons/jupiter/jupiterprojection/textures/Jupiter-text.png similarity index 100% rename from data/scene/jupiterprojection/textures/Jupiter-text.png rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/Jupiter-text.png diff --git a/data/scene/jupiterprojection/textures/defaultProj.png b/data/scene/newhorizons/jupiter/jupiterprojection/textures/defaultProj.png similarity index 100% rename from data/scene/jupiterprojection/textures/defaultProj.png rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/defaultProj.png diff --git a/data/scene/jupiterprojection/textures/defaultProj2.png b/data/scene/newhorizons/jupiter/jupiterprojection/textures/defaultProj2.png similarity index 100% rename from data/scene/jupiterprojection/textures/defaultProj2.png rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/defaultProj2.png diff --git a/data/scene/jupiterprojection/textures/europaRise1.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/europaRise1.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/europaRise1.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/europaRise1.jpg diff --git a/data/scene/jupiterprojection/textures/europaRise2.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/europaRise2.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/europaRise2.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/europaRise2.jpg diff --git a/data/scene/jupiterprojection/textures/grid.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/grid.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/grid.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/grid.jpg diff --git a/data/scene/jupiterprojection/textures/jupiter.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/jupiter.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/jupiter.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/jupiter.jpg diff --git a/data/scene/jupiterprojection/textures/jupiterFlipped.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/jupiterFlipped.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/jupiterFlipped.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/jupiterFlipped.jpg diff --git a/data/scene/jupiterprojection/textures/jupiterFlipped_low.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/jupiterFlipped_low.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/jupiterFlipped_low.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/jupiterFlipped_low.jpg diff --git a/data/scene/jupiterprojection/textures/lor_0034817584_0x630_sci_1.fit.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817584_0x630_sci_1.fit.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/lor_0034817584_0x630_sci_1.fit.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817584_0x630_sci_1.fit.jpg diff --git a/data/scene/jupiterprojection/textures/lor_0034817654_0x630_sci_1.fit.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817654_0x630_sci_1.fit.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/lor_0034817654_0x630_sci_1.fit.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817654_0x630_sci_1.fit.jpg diff --git a/data/scene/jupiterprojection/textures/lor_0034817724_0x630_sci_1.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817724_0x630_sci_1.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/lor_0034817724_0x630_sci_1.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817724_0x630_sci_1.jpg diff --git a/data/scene/jupiterprojection/textures/lor_0034817794_0x630_sci_1.fit.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817794_0x630_sci_1.fit.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/lor_0034817794_0x630_sci_1.fit.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/lor_0034817794_0x630_sci_1.fit.jpg diff --git a/data/scene/jupiterprojection/textures/lorriTest1.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/lorriTest1.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/lorriTest1.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/lorriTest1.jpg diff --git a/data/scene/jupiterprojection/textures/lorriTest2.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/lorriTest2.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/lorriTest2.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/lorriTest2.jpg diff --git a/data/scene/jupiterprojection/textures/scope.png b/data/scene/newhorizons/jupiter/jupiterprojection/textures/scope.png similarity index 100% rename from data/scene/jupiterprojection/textures/scope.png rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/scope.png diff --git a/data/scene/jupiterprojection/textures/show.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/show.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/show.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/show.jpg diff --git a/data/scene/jupiterprojection/textures/show_3072.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/show_3072.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/show_3072.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/show_3072.jpg diff --git a/data/scene/jupiterprojection/textures/small.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/small.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/small.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/small.jpg diff --git a/data/scene/jupiterprojection/textures/small.png b/data/scene/newhorizons/jupiter/jupiterprojection/textures/small.png similarity index 100% rename from data/scene/jupiterprojection/textures/small.png rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/small.png diff --git a/data/scene/jupiterprojection/textures/test.jpg b/data/scene/newhorizons/jupiter/jupiterprojection/textures/test.jpg similarity index 100% rename from data/scene/jupiterprojection/textures/test.jpg rename to data/scene/newhorizons/jupiter/jupiterprojection/textures/test.jpg diff --git a/data/scene/newhorizons/NewHorizonsKernels.torrent b/data/scene/newhorizons/newhorizons/NewHorizonsKernels.torrent similarity index 100% rename from data/scene/newhorizons/NewHorizonsKernels.torrent rename to data/scene/newhorizons/newhorizons/NewHorizonsKernels.torrent diff --git a/data/scene/newhorizons/jup260.bsp.torrent b/data/scene/newhorizons/newhorizons/jup260.bsp.torrent similarity index 100% rename from data/scene/newhorizons/jup260.bsp.torrent rename to data/scene/newhorizons/newhorizons/jup260.bsp.torrent diff --git a/data/scene/newhorizons/newhorizons.data b/data/scene/newhorizons/newhorizons/newhorizons.data similarity index 100% rename from data/scene/newhorizons/newhorizons.data rename to data/scene/newhorizons/newhorizons/newhorizons.data diff --git a/data/scene/newhorizons/newhorizons.mod b/data/scene/newhorizons/newhorizons/newhorizons.mod similarity index 97% rename from data/scene/newhorizons/newhorizons.mod rename to data/scene/newhorizons/newhorizons/newhorizons.mod index a58b2f73f5..61f9dae0cc 100644 --- a/data/scene/newhorizons/newhorizons.mod +++ b/data/scene/newhorizons/newhorizons/newhorizons.mod @@ -89,7 +89,7 @@ return { Body = "NEW HORIZONS", Geometry = { Type = "MultiModelGeometry", - GeometryFile = "${OPENSPACE_DATA}/scene/newhorizons/models/NewHorizonsCleanModel.obj", + GeometryFile = "models/NewHorizonsCleanModel.obj", Magnification = 4, }, Textures = { @@ -151,7 +151,7 @@ return { Body = "NEW HORIZONS", Geometry = { Type = "MultiModelGeometry", - GeometryFile = "${OPENSPACE_DATA}/scene/newhorizons/models/Labels.obj", + GeometryFile = "models/Labels.obj", Magnification = 4, }, Textures = { diff --git a/data/scene/newhorizonsfov/newhorizonsfov.mod b/data/scene/newhorizons/newhorizonsfov/newhorizonsfov.mod similarity index 100% rename from data/scene/newhorizonsfov/newhorizonsfov.mod rename to data/scene/newhorizons/newhorizonsfov/newhorizonsfov.mod diff --git a/data/scene/newhorizonsfov/textures/glare.png b/data/scene/newhorizons/newhorizonsfov/textures/glare.png similarity index 100% rename from data/scene/newhorizonsfov/textures/glare.png rename to data/scene/newhorizons/newhorizonsfov/textures/glare.png diff --git a/data/scene/newhorizonsfov/textures/glare_blue.png b/data/scene/newhorizons/newhorizonsfov/textures/glare_blue.png similarity index 100% rename from data/scene/newhorizonsfov/textures/glare_blue.png rename to data/scene/newhorizons/newhorizonsfov/textures/glare_blue.png diff --git a/data/scene/newhorizonspath/newhorizonspath.mod b/data/scene/newhorizons/newhorizonspath/newhorizonspath.mod similarity index 100% rename from data/scene/newhorizonspath/newhorizonspath.mod rename to data/scene/newhorizons/newhorizonspath/newhorizonspath.mod diff --git a/data/scene/newhorizonspath/textures/glare.png b/data/scene/newhorizons/newhorizonspath/textures/glare.png similarity index 100% rename from data/scene/newhorizonspath/textures/glare.png rename to data/scene/newhorizons/newhorizonspath/textures/glare.png diff --git a/data/scene/newhorizonspath/textures/glare_blue.png b/data/scene/newhorizons/newhorizonspath/textures/glare_blue.png similarity index 100% rename from data/scene/newhorizonspath/textures/glare_blue.png rename to data/scene/newhorizons/newhorizonspath/textures/glare_blue.png diff --git a/data/scene/newhorizonstrail/newhorizonstrail.mod b/data/scene/newhorizons/newhorizonstrail/newhorizonstrail.mod similarity index 100% rename from data/scene/newhorizonstrail/newhorizonstrail.mod rename to data/scene/newhorizons/newhorizonstrail/newhorizonstrail.mod diff --git a/data/scene/newhorizonstrail/textures/glare.png b/data/scene/newhorizons/newhorizonstrail/textures/glare.png similarity index 100% rename from data/scene/newhorizonstrail/textures/glare.png rename to data/scene/newhorizons/newhorizonstrail/textures/glare.png diff --git a/data/scene/newhorizonstrail/textures/glare_blue.png b/data/scene/newhorizons/newhorizonstrail/textures/glare_blue.png similarity index 100% rename from data/scene/newhorizonstrail/textures/glare_blue.png rename to data/scene/newhorizons/newhorizonstrail/textures/glare_blue.png diff --git a/data/scene/charonprojection/charonprojection.data b/data/scene/newhorizons/pluto/charonprojection/charonprojection.data similarity index 100% rename from data/scene/charonprojection/charonprojection.data rename to data/scene/newhorizons/pluto/charonprojection/charonprojection.data diff --git a/data/scene/charonprojection/charonprojection.mod b/data/scene/newhorizons/pluto/charonprojection/charonprojection.mod similarity index 100% rename from data/scene/charonprojection/charonprojection.mod rename to data/scene/newhorizons/pluto/charonprojection/charonprojection.mod diff --git a/data/scene/hydra/hydra.mod b/data/scene/newhorizons/pluto/hydra/hydra.mod similarity index 100% rename from data/scene/hydra/hydra.mod rename to data/scene/newhorizons/pluto/hydra/hydra.mod diff --git a/data/scene/hydra/textures/Hydra-Text.png b/data/scene/newhorizons/pluto/hydra/textures/Hydra-Text.png similarity index 100% rename from data/scene/hydra/textures/Hydra-Text.png rename to data/scene/newhorizons/pluto/hydra/textures/Hydra-Text.png diff --git a/data/scene/hydra/textures/gray.jpg b/data/scene/newhorizons/pluto/hydra/textures/gray.jpg similarity index 100% rename from data/scene/hydra/textures/gray.jpg rename to data/scene/newhorizons/pluto/hydra/textures/gray.jpg diff --git a/data/scene/kerberos/kerberos.mod b/data/scene/newhorizons/pluto/kerberos/kerberos.mod similarity index 100% rename from data/scene/kerberos/kerberos.mod rename to data/scene/newhorizons/pluto/kerberos/kerberos.mod diff --git a/data/scene/kerberos/textures/Kerberos-Text.png b/data/scene/newhorizons/pluto/kerberos/textures/Kerberos-Text.png similarity index 100% rename from data/scene/kerberos/textures/Kerberos-Text.png rename to data/scene/newhorizons/pluto/kerberos/textures/Kerberos-Text.png diff --git a/data/scene/kerberos/textures/gray.jpg b/data/scene/newhorizons/pluto/kerberos/textures/gray.jpg similarity index 100% rename from data/scene/kerberos/textures/gray.jpg rename to data/scene/newhorizons/pluto/kerberos/textures/gray.jpg diff --git a/data/scene/nix/nix.mod b/data/scene/newhorizons/pluto/nix/nix.mod similarity index 100% rename from data/scene/nix/nix.mod rename to data/scene/newhorizons/pluto/nix/nix.mod diff --git a/data/scene/nix/textures/Nix-Text.png b/data/scene/newhorizons/pluto/nix/textures/Nix-Text.png similarity index 100% rename from data/scene/nix/textures/Nix-Text.png rename to data/scene/newhorizons/pluto/nix/textures/Nix-Text.png diff --git a/data/scene/nix/textures/gray.jpg b/data/scene/newhorizons/pluto/nix/textures/gray.jpg similarity index 100% rename from data/scene/nix/textures/gray.jpg rename to data/scene/newhorizons/pluto/nix/textures/gray.jpg diff --git a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.data b/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.data similarity index 100% rename from data/scene/plutoprojectionhybrid/plutoprojectionhybrid.data rename to data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.data diff --git a/data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod b/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod similarity index 100% rename from data/scene/plutoprojectionhybrid/plutoprojectionhybrid.mod rename to data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod diff --git a/data/scene/styx/styx.mod b/data/scene/newhorizons/pluto/styx/styx.mod similarity index 100% rename from data/scene/styx/styx.mod rename to data/scene/newhorizons/pluto/styx/styx.mod diff --git a/data/scene/styx/textures/Styx-Text.png b/data/scene/newhorizons/pluto/styx/textures/Styx-Text.png similarity index 100% rename from data/scene/styx/textures/Styx-Text.png rename to data/scene/newhorizons/pluto/styx/textures/Styx-Text.png diff --git a/data/scene/styx/textures/gray.jpg b/data/scene/newhorizons/pluto/styx/textures/gray.jpg similarity index 100% rename from data/scene/styx/textures/gray.jpg rename to data/scene/newhorizons/pluto/styx/textures/gray.jpg diff --git a/ext/ghoul b/ext/ghoul index ad456dd4b2..5bfff36b5d 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit ad456dd4b273bd9db5a5f7f8f50915fef01b5469 +Subproject commit 5bfff36b5d26e16418da62adf64d6c523a64e6f8 diff --git a/src/scene/scenegraph.cpp b/src/scene/scenegraph.cpp index 825c6224a1..c9462023db 100644 --- a/src/scene/scenegraph.cpp +++ b/src/scene/scenegraph.cpp @@ -175,9 +175,14 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { std::sort(keys.begin(), keys.end()); ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory(); for (const std::string& key : keys) { - std::string moduleName = moduleDictionary.value(key); - std::string modulePath = FileSys.pathByAppendingComponent(sceneDirectory, moduleName); - + std::string fullModuleName = moduleDictionary.value(key); + std::string modulePath = FileSys.pathByAppendingComponent(sceneDirectory, fullModuleName); + + std::string moduleName = fullModuleName; + std::string::size_type pos = fullModuleName.find_last_of(FileSys.PathSeparator); + if (pos != std::string::npos) + moduleName = fullModuleName.substr(pos + 1); + if (!FileSys.directoryExists(modulePath)) { LERROR("Could not load module '" << moduleName << "'. Directory did not exist"); continue; @@ -188,70 +193,78 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { moduleName + _moduleExtension ); - if (!FileSys.fileExists(moduleFile)) { - LERROR("Could not load module file '" << moduleFile << "'. File did not exist"); - continue; - } - - ghoul::Dictionary moduleDictionary; - try { - ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state); - } - catch (...) { - continue; - } - - std::vector keys = moduleDictionary.keys(); - for (const std::string& key : keys) { - if (!moduleDictionary.hasValue(key)) { - LERROR("SceneGraphNode '" << key << "' is not a table in module '" - << moduleFile << "'"); + std::vector moduleDictionaries; + if (FileSys.fileExists(moduleFile)) { + // We have a module file, so it is a direct include + try { + ghoul::Dictionary moduleDictionary; + ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state); + moduleDictionaries.push_back(std::move(moduleDictionary)); + } + catch (...) { continue; } + } +// else { +// // If we do not have a module file, we have to include all subdirectories +// ghoul::filesystem:: +// ghoul::filesystem::Directory d = modulePath; + +// } + + for (const ghoul::Dictionary& moduleDictionary : moduleDictionaries) { + std::vector keys = moduleDictionary.keys(); + for (const std::string& key : keys) { + if (!moduleDictionary.hasValue(key)) { + LERROR("SceneGraphNode '" << key << "' is not a table in module '" + << moduleFile << "'"); + continue; + } - ghoul::Dictionary element; - std::string nodeName; - std::string parentName; + ghoul::Dictionary element; + std::string nodeName; + std::string parentName; - moduleDictionary.getValue(key, element); - element.setValue(KeyPathModule, modulePath); + moduleDictionary.getValue(key, element); + element.setValue(KeyPathModule, modulePath); - element.getValue(SceneGraphNode::KeyName, nodeName); - element.getValue(SceneGraphNode::KeyParentName, parentName); + element.getValue(SceneGraphNode::KeyName, nodeName); + element.getValue(SceneGraphNode::KeyParentName, parentName); - FileSys.setCurrentDirectory(modulePath); - SceneGraphNode* node = SceneGraphNode::createFromDictionary(element); - if (node == nullptr) { - LERROR("Error loading SceneGraphNode '" << nodeName << "' in module '" << moduleName << "'"); - continue; - //clear(); - //return false; - } + FileSys.setCurrentDirectory(modulePath); + SceneGraphNode* node = SceneGraphNode::createFromDictionary(element); + if (node == nullptr) { + LERROR("Error loading SceneGraphNode '" << nodeName << "' in module '" << moduleName << "'"); + continue; + //clear(); + //return false; + } - dependencies[nodeName].push_back(parentName); - parents[nodeName] = parentName; - // Also include loaded dependencies + dependencies[nodeName].push_back(parentName); + parents[nodeName] = parentName; + // Also include loaded dependencies - if (element.hasKey(SceneGraphNode::KeyDependencies)) { - if (element.hasValue(SceneGraphNode::KeyDependencies)) { - ghoul::Dictionary nodeDependencies; - element.getValue(SceneGraphNode::KeyDependencies, nodeDependencies); + if (element.hasKey(SceneGraphNode::KeyDependencies)) { + if (element.hasValue(SceneGraphNode::KeyDependencies)) { + ghoul::Dictionary nodeDependencies; + element.getValue(SceneGraphNode::KeyDependencies, nodeDependencies); - std::vector keys = nodeDependencies.keys(); - for (const std::string& key : keys) { - std::string value = nodeDependencies.value(key); - dependencies[nodeName].push_back(value); + std::vector keys = nodeDependencies.keys(); + for (const std::string& key : keys) { + std::string value = nodeDependencies.value(key); + dependencies[nodeName].push_back(value); + } + } + else { + LERROR("Dependencies did not have the corrent type"); } } - else { - LERROR("Dependencies did not have the corrent type"); - } + + + SceneGraphNodeInternal* internalNode = new SceneGraphNodeInternal; + internalNode->node = node; + _nodes.push_back(internalNode); } - - - SceneGraphNodeInternal* internalNode = new SceneGraphNodeInternal; - internalNode->node = node; - _nodes.push_back(internalNode); } } ghoul::lua::destroyLuaState(state); From 04af38f546f2b691fc9bc5117844fb8d7014a7fa Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 15 Apr 2016 10:27:41 -0400 Subject: [PATCH 26/38] Enable subdirectories by specifying an intermediate directory in the scene file --- data/scene/default_nh.scene | 13 +-- .../jupiterprojection/jupiterprojection.mod | 2 +- .../plutoprojectionhybrid.mod | 4 +- src/scene/scenegraph.cpp | 96 +++++++++++++++---- 4 files changed, 80 insertions(+), 35 deletions(-) diff --git a/data/scene/default_nh.scene b/data/scene/default_nh.scene index 07cd84a34f..dacd320a0c 100644 --- a/data/scene/default_nh.scene +++ b/data/scene/default_nh.scene @@ -16,22 +16,13 @@ return { "saturn", "uranus", "neptune", - "newhorizons/pluto/plutoprojectionhybrid", - "newhorizons/pluto/charonprojection", - "newhorizons/pluto/kerberos", - "newhorizons/pluto/nix", - "newhorizons/pluto/styx", - "newhorizons/pluto/hydra", + "newhorizons/pluto", + "newhorizons/jupiter", "stars", -- "stars-denver", "milkyway", -- "milkyway-eso", "imageplane", - "newhorizons/jupiter/jupiterprojection", - "newhorizons/jupiter/ioprojection", - "newhorizons/jupiter/europaprojection", - "newhorizons/jupiter/ganymedeprojection", - "newhorizons/jupiter/callistoprojection", "newhorizons/newhorizons", "newhorizons/newhorizonsfov", } diff --git a/data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.mod b/data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.mod index e2f47aef77..706938f06b 100644 --- a/data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.mod +++ b/data/scene/newhorizons/jupiter/jupiterprojection/jupiterprojection.mod @@ -39,7 +39,7 @@ return { }, Projection = { --Sequence = "F:/JupiterFullSequence", - Sequence = "${OPENSPACE_DATA}/scene/jupiterprojection/ProjectionsOfInterest", + Sequence = "${OPENSPACE_DATA}/scene/newhorizons/jupiter/jupiterprojection/ProjectionsOfInterest", SequenceType = "image-sequence", Observer = "NEW HORIZONS", Target = "JUPITER", diff --git a/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod b/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod index 40e29f35b6..706000d4fd 100644 --- a/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod +++ b/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod @@ -50,8 +50,8 @@ return { MieColor = {1.0, 1.0, 1.0} }, Projection = { - Sequence = "${OPENSPACE_DATA}/scene/plutoprojectionhybrid/images", - EventFile = "${OPENSPACE_DATA}/scene/plutoprojectionhybrid/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt", + Sequence = "${OPENSPACE_DATA}/scene/newhorizons/pluto/plutoprojectionhybrid/images", + EventFile = "${OPENSPACE_DATA}/scene/newhorizons/pluto/plutoprojectionhybrid/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt", SequenceType = "hybrid", Observer = "NEW HORIZONS", Target = "PLUTO", diff --git a/src/scene/scenegraph.cpp b/src/scene/scenegraph.cpp index c9462023db..11f59c3675 100644 --- a/src/scene/scenegraph.cpp +++ b/src/scene/scenegraph.cpp @@ -193,62 +193,112 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { moduleName + _moduleExtension ); - std::vector moduleDictionaries; + struct ModuleInformation { + ghoul::Dictionary dictionary; + std::string moduleFile; + std::string modulePath; + std::string moduleName; + }; + std::vector moduleDictionaries; if (FileSys.fileExists(moduleFile)) { // We have a module file, so it is a direct include try { ghoul::Dictionary moduleDictionary; ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state); - moduleDictionaries.push_back(std::move(moduleDictionary)); + moduleDictionaries.push_back({ + moduleDictionary, + moduleFile, + modulePath, + moduleName + }); } catch (...) { continue; } } -// else { -// // If we do not have a module file, we have to include all subdirectories -// ghoul::filesystem:: -// ghoul::filesystem::Directory d = modulePath; + else { + // If we do not have a module file, we have to include all subdirectories + using ghoul::filesystem::Directory; + using std::string; + std::vector directories = Directory(modulePath).readDirectories(); + + for (const string& s : directories) { + std::string::size_type pos = s.find_last_of(FileSys.PathSeparator); + if (pos == std::string::npos) { + LERROR("Error parsing subdirectory name '" << s << "'"); + continue; + } + string moduleName = s.substr(pos+1); + + string submodulePath = s; + string moduleFile = FileSys.pathByAppendingComponent(submodulePath, moduleName) + _moduleExtension; +// string moduleName = s; + + if (!FileSys.fileExists(moduleFile)) { + LERROR("Could not find module file '" << moduleFile << "'. " + "Indirectly included through '" << modulePath << "'"); + continue; + } + + // We have a module file, so it is a direct include + try { + ghoul::Dictionary moduleDictionary; + ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state); + moduleDictionaries.push_back({ + moduleDictionary, + moduleFile, + submodulePath, + moduleName + }); + } + catch (...) { + continue; + } + + } + + } + + auto addModule = [this, &dependencies, &parents](const ModuleInformation& moduleInformation) { + const ghoul::Dictionary& moduleDictionary = moduleInformation.dictionary; + const std::string& moduleFile = moduleInformation.moduleFile; + const std::string& modulePath = moduleInformation.modulePath; + const std::string& moduleName = moduleInformation.moduleName; -// } - - for (const ghoul::Dictionary& moduleDictionary : moduleDictionaries) { std::vector keys = moduleDictionary.keys(); for (const std::string& key : keys) { if (!moduleDictionary.hasValue(key)) { LERROR("SceneGraphNode '" << key << "' is not a table in module '" - << moduleFile << "'"); + << moduleFile << "'"); continue; } - + ghoul::Dictionary element; std::string nodeName; std::string parentName; - + moduleDictionary.getValue(key, element); element.setValue(KeyPathModule, modulePath); - + element.getValue(SceneGraphNode::KeyName, nodeName); element.getValue(SceneGraphNode::KeyParentName, parentName); - + FileSys.setCurrentDirectory(modulePath); SceneGraphNode* node = SceneGraphNode::createFromDictionary(element); if (node == nullptr) { LERROR("Error loading SceneGraphNode '" << nodeName << "' in module '" << moduleName << "'"); continue; - //clear(); - //return false; } - + dependencies[nodeName].push_back(parentName); parents[nodeName] = parentName; // Also include loaded dependencies - + if (element.hasKey(SceneGraphNode::KeyDependencies)) { if (element.hasValue(SceneGraphNode::KeyDependencies)) { ghoul::Dictionary nodeDependencies; element.getValue(SceneGraphNode::KeyDependencies, nodeDependencies); - + std::vector keys = nodeDependencies.keys(); for (const std::string& key : keys) { std::string value = nodeDependencies.value(key); @@ -259,12 +309,16 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { LERROR("Dependencies did not have the corrent type"); } } - - + + SceneGraphNodeInternal* internalNode = new SceneGraphNodeInternal; internalNode->node = node; _nodes.push_back(internalNode); } + }; + + for (const ModuleInformation& i : moduleDictionaries) { + addModule(i); } } ghoul::lua::destroyLuaState(state); From c73404a1de741529f9c5c23a3b82da61fc3ebd1a Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 15 Apr 2016 10:37:24 -0400 Subject: [PATCH 27/38] Rename PlutoProjectionHybrid module to PlutoProjection Remove outdated PlutoProjection module --- .gitignore | 20 +- .../plutoprojection.data} | 0 .../plutoprojection.mod} | 0 .../plutoprojection/plutoprojection.data | 7 - .../scene/plutoprojection/plutoprojection.mod | 308 ------------------ 5 files changed, 10 insertions(+), 325 deletions(-) rename data/scene/newhorizons/pluto/{plutoprojectionhybrid/plutoprojectionhybrid.data => plutoprojection/plutoprojection.data} (100%) rename data/scene/newhorizons/pluto/{plutoprojectionhybrid/plutoprojectionhybrid.mod => plutoprojection/plutoprojection.mod} (100%) delete mode 100644 data/scene/plutoprojection/plutoprojection.data delete mode 100644 data/scene/plutoprojection/plutoprojection.mod diff --git a/.gitignore b/.gitignore index 150deb205c..a607eada61 100644 --- a/.gitignore +++ b/.gitignore @@ -43,12 +43,12 @@ gui/externaltimecontrol/mainwindow.h data/scene/67P/obj/67P_rotated_5_130.obj data/spice/NewHorizonsKernels/ data/spice/RosettaKernels/ -data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/ -data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/Shenk_180.jpg -data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/barycenter.png -data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/defaultProj.png -data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/pluto_highres_180.jpg -data/scene/newhorizons/pluto/plutoprojectionhybrid/utcEvents.txt +data/scene/newhorizons/pluto/plutoprojection/textures/ +data/scene/newhorizons/pluto/plutoprojection/textures/Shenk_180.jpg +data/scene/newhorizons/pluto/plutoprojection/textures/barycenter.png +data/scene/newhorizons/pluto/plutoprojection/textures/defaultProj.png +data/scene/newhorizons/pluto/plutoprojection/textures/pluto_highres_180.jpg +data/scene/newhorizons/pluto/plutoprojection/utcEvents.txt data/scene/rosetta/obj/mainbodyros.obj data/scene/rosetta/obj/solarpanelleft.obj data/scene/rosetta/obj/solarpanelright.obj @@ -108,9 +108,9 @@ data/scene/newhorizons/newhorizons/textures/labels.png data/scene/pluto/textures/ data/scene/pluto/textures/Shenk_180.jpg data/scene/pluto/textures/pluto_highres_180.jpg -data/scene/newhorizons/pluto/plutoprojectionhybrid/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt -data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/3.jpg -data/scene/newhorizons/pluto/plutoprojectionhybrid/textures/Pluto-Text.png +data/scene/newhorizons/pluto/plutoprojection/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt +data/scene/newhorizons/pluto/plutoprojection/textures/3.jpg +data/scene/newhorizons/pluto/plutoprojection/textures/Pluto-Text.png data/scene/vestaprojection/VestaComet/VestaComet.mtl data/scene/vestaprojection/textures/defaultProj_backup.png data/scene/vestaprojection/textures/dummy.jpg @@ -119,4 +119,4 @@ data/scene/vestaprojection/textures/projectMe.png data/spice/MAR063.BSP data/spice/de430_1850-2150.bsp data/spice/jup260.bsp -data/scene/newhorizons/pluto/plutoprojectionhybrid/images +data/scene/newhorizons/pluto/plutoprojection/images diff --git a/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.data b/data/scene/newhorizons/pluto/plutoprojection/plutoprojection.data similarity index 100% rename from data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.data rename to data/scene/newhorizons/pluto/plutoprojection/plutoprojection.data diff --git a/data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod b/data/scene/newhorizons/pluto/plutoprojection/plutoprojection.mod similarity index 100% rename from data/scene/newhorizons/pluto/plutoprojectionhybrid/plutoprojectionhybrid.mod rename to data/scene/newhorizons/pluto/plutoprojection/plutoprojection.mod diff --git a/data/scene/plutoprojection/plutoprojection.data b/data/scene/plutoprojection/plutoprojection.data deleted file mode 100644 index 49e26de6dc..0000000000 --- a/data/scene/plutoprojection/plutoprojection.data +++ /dev/null @@ -1,7 +0,0 @@ -return { - FileRequest = { - { Identifier = "newhorizons_plutoencounter_pluto_assets", Destination = "assets", Version = 1 }, - { Identifier = "newhorizons_plutoencounter_pluto_textures", Destination = "textures", Version = 2 }, - { Identifier = "pluto_textures", Destination = "textures", Version = 2 } - }, -} \ No newline at end of file diff --git a/data/scene/plutoprojection/plutoprojection.mod b/data/scene/plutoprojection/plutoprojection.mod deleted file mode 100644 index 9afc71086a..0000000000 --- a/data/scene/plutoprojection/plutoprojection.mod +++ /dev/null @@ -1,308 +0,0 @@ -return { - -- Pluto barycenter module - { - Name = "PlutoBarycenter", - Parent = "SolarSystemBarycenter", - Ephemeris = { - Type = "Spice", - Body = "PLUTO BARYCENTER", - Reference = "ECLIPJ2000", - Observer = "SUN", - Kernels = { - "${OPENSPACE_DATA}/spice/de430_1850-2150.bsp" - } - }, - }, - -- PlutoProjection module - { - Name = "PlutoProjection", - Parent = "PlutoBarycenter", - Renderable = { - Type = "RenderablePlanetProjection", - Frame = "IAU_PLUTO", - Body = "PLUTO", - Geometry = { - Type = "SimpleSphereProjection", - Radius = { 1.173 , 6 }, - Segments = 100 - }, - Textures = { - Type = "simple", - Color = "textures/pluto_large.jpg", - Project = "textures/3.jpg", - Sequencing = "true", - }, - Atmosphere = { - Type = "Nishita", -- for example, values missing etc etc - MieFactor = 1.0, - MieColor = {1.0, 1.0, 1.0} - }, - Projection = { - --Sequence = "${OPENSPACE_DATA}/scene/plutoprojection/assets/incomingImagery", - --SequenceType = "image-sequence", - Sequence = "${OPENSPACE_DATA}/scene/plutoprojection/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt", - SequenceType = "playbook", - Observer = "NEW HORIZONS", - Target = "PLUTO", - Aberration = "NONE", - }, - DataInputTranslation = { - --[[Instrument = { - LORRI = { - DetectorType = "Camera", - Spice = {"NH_LORRI"}, - }, - RALPH_MVIC_PAN_FRAME = { - DetectorType = "Scanner", - StopCommand = "RALPH_ABORT", - Spice = {"NH_RALPH_MVIC_FT"}, - }, - }, - Target ={ - Read = { - "TARGET_NAME", - "INSTRUMENT_HOST_NAME", - "INSTRUMENT_ID", - "START_TIME", - "STOP_TIME", - "DETECTOR_TYPE", - --"SEQUENCE_ID", - }, - Convert = { - PLUTO = {"PLUTO" }, - NEWHORIZONS = {"NEW HORIZONS"}, - CCD = {"CAMERA" }, - FRAMECCD = {"SCANNER" }, - }, - }, - --]] - Instrument = { - LORRI = { - DetectorType = "Camera", - Spice = {"NH_LORRI"}, - }, - RALPH_MVIC_PAN_FRAME = { - DetectorType = "Scanner", - StopCommand = "RALPH_ABORT", - Spice = {"NH_RALPH_MVIC_FT"}, - }, - RALPH_MVIC_COLOR = { - DetectorType = "Scanner", - StopCommand = "END_NOM", - Spice = { "NH_RALPH_MVIC_NIR", - "NH_RALPH_MVIC_METHANE", - "NH_RALPH_MVIC_RED", - "NH_RALPH_MVIC_BLUE" }, - }, - RALPH_LEISA = { - DetectorType = "Scanner", - StopCommand = "END_NOM", - Spice = {"NH_RALPH_LEISA"}, - }, - RALPH_MVIC_PAN1 = { - DetectorType = "Scanner", - StopCommand = "END_NOM", - Spice = {"NH_RALPH_MVIC_PAN1"}, - }, - RALPH_MVIC_PAN2 = { - DetectorType = "Scanner", - StopCommand = "END_NOM", - Spice = {"NH_RALPH_MVIC_PAN2"}, - }, - ALICE_Use_AIRGLOW = { - DetectorType = "Scanner", - StopCommand = "ALICE_END_PIXELLIST", - Spice = {"NH_ALICE_AIRGLOW"}, - }, - ALICE_Use_AIRGLOW = { - DetectorType = "Scanner", - StopCommand = "ALICE_END_HISTOGRAM", - Spice = {"NH_ALICE_AIRGLOW"}, - }, - ALICE_Use_SOCC = { - DetectorType = "Scanner", - StopCommand = "ALICE_END_PIXELLIST", - Spice = {"NH_ALICE_SOC"}, - }, - ALICE_Use_SOCC = { - DetectorType = "Scanner", - StopCommand = "ALICE_END_HISTOGRAM", - Spice = {"NH_ALICE_SOC"}, - }, - REX_START = { - DetectorType = "Scanner", - StopCommand = "REX_MODE_OFF", - Spice = { "NH_REX" }, - } - }, - }, - Instrument = { - Name = "NH_LORRI", - Method = "ELLIPSOID", - Aberration = "NONE", - Fovy = 0.2907, - Aspect = 1, - Near = 0.2, - Far = 10000, - }, - PotentialTargets = { - "PLUTO", - "CHARON", - "NIX", - "HYDRA", - "P5", - "P4", - } - }, - Ephemeris = { - Type = "Spice", - Body = "PLUTO", - Reference = "GALACTIC", - Observer = "PLUTO BARYCENTER", - Kernels = { - "${SPICE}/NewHorizonsKernels/nh_plu017.bsp" - } - }, - Rotation = { - Type = "Spice", - Frame = "IAU_PLUTO", - Reference = "GALACTIC" - }, - GuiName = "/Solar/Planets/Pluto" - }, - { - Name = "Barycenter", - Parent = "PlutoBarycenter", - Renderable = { - Type = "RenderablePlane", - Billboard = true, - Size = { 5, 4 }, - Texture = "textures/barycenter.png", - Atmosphere = { - Type = "Nishita", -- for example, values missing etc etc - MieFactor = 1.0, - MieColor = {1.0, 1.0, 1.0} - } - }, - Ephemeris = { - Type = "Spice", - Body = "PLUTO BARYCENTER", - Reference = "ECLIPJ2000", - Observer = "SUN", - Kernels = { - --"${OPENSPACE_DATA}/spice/de430_1850-2150.bsp" - "${OPENSPACE_DATA}/spice/nh_plu017.bsp" - } - }, - }, - { - Name = "PlutoText", - Parent = "PlutoProjection", - Renderable = { - Type = "RenderablePlane", - Size = {1.0, 6.3}, - Origin = "Center", - Billboard = true, - Texture = "textures/Pluto-Text.png" - }, - Ephemeris = { - Type = "Static", - Position = {0, -20, 0, 5} - } - }, - { - Name = "PlutoTexture", - Parent = "PlutoProjection", - Renderable = { - Type = "RenderablePlane", - Size = {1.0, 6.4}, - Origin = "Center", - Billboard = true, - ProjectionListener = true, - Texture = "textures/Pluto-Text.png" - }, - Ephemeris = { - Type = "Static", - Position = {0, 0, 40, 5} - } - }, - { - Name = "PlutoShadow", - Parent = "PlutoProjection", - Renderable = { - Type = "RenderableShadowCylinder", - TerminatorType = "PENUMBRAL", - LightSource = "SUN", - Observer = "NEW HORIZONS", - Body = "PLUTO", - BodyFrame = "IAU_PLUTO", - MainFrame = "GALACTIC", - Aberration = "NONE", - }, - Ephemeris = { - Type = "Static", - Position = {0, 0, 0, 5} - } - }, - -- PlutoBarycentricTrail module - { - Name = "PlutoBarycentricTrail", - Parent = "PlutoBarycenter", - Renderable = { - Type = "RenderableTrail", - Body = "PLUTO", - Frame = "GALACTIC", - Observer = "PLUTO BARYCENTER", - RGB = {0.00,0.62,1.00}, - TropicalOrbitPeriod = 120 , - EarthOrbitRatio = 0.03, - DayLength = 1, - Textures = { - Type = "simple", - Color = "${COMMON_MODULE}/textures/glare_blue.png", - -- need to add different texture - }, - }, - GuiName = "/Solar/CharonTrail" - }, - { - Name = "PlutoBarycenterLabel", - Parent = "PlutoBarycenter", - Renderable = { - Type = "RenderablePlane", - Billboard = true, - Size = { 5, 4 }, - Texture = "textures/barycenter.png", - Atmosphere = { - Type = "Nishita", -- for example, values missing etc etc - MieFactor = 1.0, - MieColor = {1.0, 1.0, 1.0} - } - }, - Ephemeris = { - Type = "Static", - Position = {0, 0, 0, 1} - }, - }, - -- PlutoTrail module - { - Name = "PlutoTrail", - Parent = "SolarSystemBarycenter", - Renderable = { - Type = "RenderableTrail", - Body = "PLUTO BARYCENTER", - Frame = "GALACTIC", - Observer = "SUN", - RGB = { 0.3, 0.7, 0.3 }, - TropicalOrbitPeriod = 90588 , - EarthOrbitRatio = 248.02, - DayLength = 9.9259, - Textures = { - Type = "simple", - Color = "${COMMON_MODULE}/textures/glare_blue.png", - -- need to add different texture - }, - }, - GuiName = "/Solar/PlutoTrail" - } -} From 7e44ac06213dd2c5f2369e9aa41987ff9e52cd03 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 15 Apr 2016 15:05:24 -0400 Subject: [PATCH 28/38] Fixed Launcher to work with new possible module directory structure --- apps/Launcher/syncwidget.cpp | 90 ++++++++++++++++++++++++++++-------- apps/Launcher/syncwidget.h | 3 ++ 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/apps/Launcher/syncwidget.cpp b/apps/Launcher/syncwidget.cpp index ef92e50b5f..386c44c320 100644 --- a/apps/Launcher/syncwidget.cpp +++ b/apps/Launcher/syncwidget.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -275,8 +276,8 @@ void SyncWidget::handleFileRequest() { LDEBUG(f.identifier.toStdString() << " (" << f.version << ") -> " << f.destination.toStdString()); ghoul::filesystem::Directory d = FileSys.currentDirectory(); - std::string thisDirectory = absPath("${SCENE}/" + f.module.toStdString() + "/"); - FileSys.setCurrentDirectory(thisDirectory); +// std::string thisDirectory = absPath("${SCENE}/" + f.module.toStdString() + "/"); + FileSys.setCurrentDirectory(f.baseDir.toStdString()); std::string identifier = f.identifier.toStdString(); @@ -301,8 +302,9 @@ void SyncWidget::handleTorrentFiles() { LDEBUG(f.file.toStdString() << " -> " << f.destination.toStdString()); ghoul::filesystem::Directory d = FileSys.currentDirectory(); - std::string thisDirectory = absPath("${SCENE}/" + f.module.toStdString() + "/"); - FileSys.setCurrentDirectory(thisDirectory); +// std::string thisDirectory = absPath("${SCENE}/" + f.module.toStdString() + "/"); + FileSys.setCurrentDirectory(f.baseDir.toStdString()); +// FileSys.setCurrentDirectory(thisDirectory); QString file = QString::fromStdString(absPath(f.file.toStdString())); @@ -367,18 +369,65 @@ void SyncWidget::syncButtonPressed() { LERROR("Could not find 'Modules'"); return; } - - QStringList modulesList; - for (int i = 1; i <= modules.size(); ++i) { - std::string module = modules.value(std::to_string(i)); - modulesList.append(QString::fromStdString(module)); - } - modulesList.append("common"); - + + struct ModuleInformation { + QString moduleName; + QString moduleDatafile; + QString modulePath; + }; + QDir sceneDir(scene); sceneDir.cdUp(); - for (QString module : modulesList) { - QString dataFile = sceneDir.absoluteFilePath(module + "/" + module + ".data"); + QList modulesList; + for (int i = 1; i <= modules.size(); ++i) { + std::string module = modules.value(std::to_string(i)); + std::string shortModule = module; + + std::string::size_type pos = module.find_last_of(FileSys.PathSeparator); + if (pos != std::string::npos) { + shortModule = module.substr(pos+1); + } + + QString m = QString::fromStdString(module); + + QString dataFile = sceneDir.absoluteFilePath( + QString::fromStdString(module) + "/" + QString::fromStdString(shortModule) + ".data" + ); + + if (QFileInfo(dataFile).exists()) { + modulesList.append({ + QString::fromStdString(module), + dataFile, + sceneDir.absolutePath() + "/" + QString::fromStdString(module) + }); + } + else { + QDir metaModuleDir = sceneDir; + metaModuleDir.cd(QString::fromStdString(module)); + + QDirIterator it(metaModuleDir.absolutePath(), QStringList() << "*.data", QDir::Files, QDirIterator::Subdirectories); + while (it.hasNext()) { + QString v = it.next(); + QDir d(v); + d.cdUp(); + + modulesList.append({ + d.dirName(), + v, + d.absolutePath() + }); + } + } + } + modulesList.append({ + "common", + sceneDir.absolutePath() + "/common/common.data", + sceneDir.absolutePath() + "/common" + }); + + for (const ModuleInformation& module : modulesList) { + QString dataFile = module.moduleDatafile; +// QString dataFile = sceneDir.absoluteFilePath(module + "/" + module + ".data"); if (QFileInfo(dataFile).exists()) { ghoul::Dictionary dataDictionary; @@ -407,9 +456,10 @@ void SyncWidget::syncButtonPressed() { dest = d.value(DestinationKey); _directFiles.append({ - module, + module.moduleName, QString::fromStdString(url), - QString::fromStdString(dest) + QString::fromStdString(dest), + module.modulePath }); } } @@ -436,9 +486,10 @@ void SyncWidget::syncButtonPressed() { int version = static_cast(d.value(VersionKey)); _fileRequests.append({ - module, + module.moduleName, QString::fromStdString(url), QString::fromStdString(dest), + module.modulePath, version }); } @@ -462,9 +513,10 @@ void SyncWidget::syncButtonPressed() { dest = ""; _torrentFiles.append({ - module, + module.moduleName, QString::fromStdString(file), - QString::fromStdString(dest) + QString::fromStdString(dest), + module.modulePath }); } } diff --git a/apps/Launcher/syncwidget.h b/apps/Launcher/syncwidget.h index e17f54be7f..c91838c13c 100644 --- a/apps/Launcher/syncwidget.h +++ b/apps/Launcher/syncwidget.h @@ -65,12 +65,14 @@ private: QString module; QString url; QString destination; + QString baseDir; }; struct FileRequest { QString module; QString identifier; QString destination; + QString baseDir; int version; }; @@ -78,6 +80,7 @@ private: QString module; QString file; QString destination; + QString baseDir; }; void clear(); From 9c375db63540e3ebd258082720fe1828bc981461 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 17 Apr 2016 12:17:44 +0100 Subject: [PATCH 29/38] Updated Ghoul repository --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 5bfff36b5d..3aa7270fa4 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 5bfff36b5d26e16418da62adf64d6c523a64e6f8 +Subproject commit 3aa7270fa459aa4d4b7974d97d45e177355db27c From 990f22bc6d098893a94d4db9a0931b2275b6ece1 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 09:23:19 +0200 Subject: [PATCH 30/38] Update the ghoul library --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 3aa7270fa4..5cecda6057 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 3aa7270fa459aa4d4b7974d97d45e177355db27c +Subproject commit 5cecda605764688065b282e0cb3b7ae16257d305 From 4936a4a0841d83f910c23111ee97e36ef88694f1 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 11:12:12 +0200 Subject: [PATCH 31/38] Remove sgct.h inclusion from LuaConsole Untabify more files --- include/openspace/util/syncbuffer.h | 60 ++--- src/engine/wrapper/sgctwindowwrapper.cpp | 2 +- src/interaction/luaconsole.cpp | 266 +++++++++++------------ 3 files changed, 163 insertions(+), 165 deletions(-) diff --git a/include/openspace/util/syncbuffer.h b/include/openspace/util/syncbuffer.h index 0633d68ccc..6e9b0e6701 100644 --- a/include/openspace/util/syncbuffer.h +++ b/include/openspace/util/syncbuffer.h @@ -35,7 +35,7 @@ namespace openspace { class SyncBuffer { public: - SyncBuffer(size_t n); + SyncBuffer(size_t n); void encode(const std::string& s) { const size_t size = sizeof(char) * s.size() + sizeof(int32_t); @@ -48,14 +48,14 @@ public: _encodeOffset += length; } - template - void encode(const T& v) { - const size_t size = sizeof(T); - assert(_encodeOffset + size < _n); + template + void encode(const T& v) { + const size_t size = sizeof(T); + assert(_encodeOffset + size < _n); - memcpy(_dataStream.data() + _encodeOffset, &v, size); - _encodeOffset += size; - } + memcpy(_dataStream.data() + _encodeOffset, &v, size); + _encodeOffset += size; + } std::string decode() { int32_t length; @@ -70,38 +70,38 @@ public: return ret; } - template - T decode() { - const size_t size = sizeof(T); - assert(_decodeOffset + size < _n); - T value; - memcpy(&value, _dataStream.data() + _decodeOffset, size); - _decodeOffset += size; - return value; - } + template + T decode() { + const size_t size = sizeof(T); + assert(_decodeOffset + size < _n); + T value; + memcpy(&value, _dataStream.data() + _decodeOffset, size); + _decodeOffset += size; + return value; + } void decode(std::string& s) { s = decode(); } - template - void decode(T& value) { - const size_t size = sizeof(T); - assert(_decodeOffset + size < _n); - memcpy(&value, _dataStream.data() + _decodeOffset, size); - _decodeOffset += size; - } + template + void decode(T& value) { + const size_t size = sizeof(T); + assert(_decodeOffset + size < _n); + memcpy(&value, _dataStream.data() + _decodeOffset, size); + _decodeOffset += size; + } void write(); - void read(); + void read(); private: - size_t _n; - size_t _encodeOffset; - size_t _decodeOffset; - std::vector _dataStream; - sgct::SharedVector _synchronizationBuffer; + size_t _n; + size_t _encodeOffset; + size_t _decodeOffset; + std::vector _dataStream; + sgct::SharedVector _synchronizationBuffer; }; } // namespace openspace diff --git a/src/engine/wrapper/sgctwindowwrapper.cpp b/src/engine/wrapper/sgctwindowwrapper.cpp index 0d9ffb69d8..b3a3134a22 100644 --- a/src/engine/wrapper/sgctwindowwrapper.cpp +++ b/src/engine/wrapper/sgctwindowwrapper.cpp @@ -90,7 +90,7 @@ glm::ivec2 SGCTWindowWrapper::currentDrawBufferResolution() const { if (viewport->hasSubViewports() && viewport->getNonLinearProjectionPtr()) { int res = viewport->getNonLinearProjectionPtr()->getCubemapResolution(); return glm::ivec2(res, res); - } else { + } else { return currentWindowResolution(); } } diff --git a/src/interaction/luaconsole.cpp b/src/interaction/luaconsole.cpp index 506e395d5a..a7bf1ccb99 100644 --- a/src/interaction/luaconsole.cpp +++ b/src/interaction/luaconsole.cpp @@ -41,11 +41,9 @@ #include #include -#include - namespace { - const std::string _loggerCat = "LuaConsole"; - const std::string historyFile = "ConsoleHistory"; + const std::string _loggerCat = "LuaConsole"; + const std::string historyFile = "ConsoleHistory"; const int NoAutoComplete = -1; } @@ -55,11 +53,11 @@ namespace { namespace openspace { LuaConsole::LuaConsole() - : _inputPosition(0) - , _activeCommand(0) - , _filename("") + : _inputPosition(0) + , _activeCommand(0) + , _filename("") , _autoCompleteInfo({NoAutoComplete, false, ""}) - , _isVisible(false) + , _isVisible(false) { // _commands.push_back(""); // _activeCommand = _commands.size() - 1; @@ -111,73 +109,73 @@ void LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction actio const bool modifierControl = (modifier == KeyModifier::Control); const bool modifierShift = (modifier == KeyModifier::Shift); - // Paste from clipboard + // Paste from clipboard if (modifierControl && (key == Key::V)) - addToCommand(ghoul::clipboardText()); + addToCommand(ghoul::clipboardText()); - // Copy to clipboard + // Copy to clipboard if (modifierControl && (key == Key::C)) - ghoul::setClipboardText(_commands.at(_activeCommand)); + ghoul::setClipboardText(_commands.at(_activeCommand)); - // Go to the previous character + // Go to the previous character if ((key == Key::Left) && (_inputPosition > 0)) - --_inputPosition; + --_inputPosition; - // Go to the next character + // Go to the next character if ((key == Key::Right) && _inputPosition < _commands.at(_activeCommand).length()) - ++_inputPosition; + ++_inputPosition; - // Go to previous command + // Go to previous command if (key == Key::Up) { - if (_activeCommand > 0) - --_activeCommand; - _inputPosition = _commands.at(_activeCommand).length(); - } + if (_activeCommand > 0) + --_activeCommand; + _inputPosition = _commands.at(_activeCommand).length(); + } - // Go to next command (the last is empty) + // Go to next command (the last is empty) if (key == Key::Down) { - if (_activeCommand < _commands.size() - 1) - ++_activeCommand; - _inputPosition = _commands.at(_activeCommand).length(); - } + if (_activeCommand < _commands.size() - 1) + ++_activeCommand; + _inputPosition = _commands.at(_activeCommand).length(); + } - // Remove character before _inputPosition + // Remove character before _inputPosition if (key == Key::BackSpace) { - if (_inputPosition > 0) { - _commands.at(_activeCommand).erase(_inputPosition - 1, 1); - --_inputPosition; - } - } + if (_inputPosition > 0) { + _commands.at(_activeCommand).erase(_inputPosition - 1, 1); + --_inputPosition; + } + } - // Remove character after _inputPosition + // Remove character after _inputPosition if (key == Key::Delete) { if (_inputPosition <= _commands.at(_activeCommand).size()) _commands.at(_activeCommand).erase(_inputPosition, 1); } - // Go to the beginning of command string + // Go to the beginning of command string if (key == Key::Home) - _inputPosition = 0; + _inputPosition = 0; - // Go to the end of command string + // Go to the end of command string if (key == Key::End) - _inputPosition = _commands.at(_activeCommand).size(); + _inputPosition = _commands.at(_activeCommand).size(); if (key == Key::Enter) { - // SHIFT+ENTER == new line - if (modifierShift) - addToCommand("\n"); - // ENTER == run lua script - else { + // SHIFT+ENTER == new line + if (modifierShift) + addToCommand("\n"); + // ENTER == run lua script + else { std::string cmd = _commands.at(_activeCommand); - if (cmd != "") { - OsEng.scriptEngine().queueScript(cmd); + if (cmd != "") { + OsEng.scriptEngine().queueScript(cmd); // Only add the current command to the history if it hasn't been // executed before. We don't want two of the same commands in a row if (_commandsHistory.empty() || (cmd != _commandsHistory.back())) - _commandsHistory.push_back(_commands.at(_activeCommand)); - } + _commandsHistory.push_back(_commands.at(_activeCommand)); + } // Some clean up after the execution of the command _commands = _commandsHistory; @@ -185,8 +183,8 @@ void LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction actio _activeCommand = _commands.size() - 1; _inputPosition = 0; setVisible(false); - } - } + } + } if (key == Key::Tab) { // We get a list of all the available commands and initially find the first @@ -282,28 +280,28 @@ void LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction actio if (!modifierShift) _autoCompleteInfo = { NoAutoComplete, false, ""}; } - } + } } void LuaConsole::charCallback(unsigned int codepoint, KeyModifier modifier) { - if (codepoint == static_cast(commandInputButton())) - return; + if (codepoint == static_cast(commandInputButton())) + return; #ifndef WIN32 const bool modifierControl = (modifier == KeyModifier::Control); - const int codepoint_C = 99; - const int codepoint_V = 118; - if (modifierControl && (codepoint == codepoint_C || codepoint == codepoint_V)) { - return; - } + const int codepoint_C = 99; + const int codepoint_V = 118; + if (modifierControl && (codepoint == codepoint_C || codepoint == codepoint_V)) { + return; + } #endif - addToCommand(UnicodeToUTF8(codepoint)); + addToCommand(UnicodeToUTF8(codepoint)); } void LuaConsole::render() { - const float font_size = 10.0f; + const float font_size = 10.0f; glm::ivec4 viewportPixelCoordinates = OsEng.windowWrapper().viewportPixelCoordinates(); int x1 = viewportPixelCoordinates.x; @@ -311,12 +309,12 @@ void LuaConsole::render() { int y1 = viewportPixelCoordinates.z; int ySize = viewportPixelCoordinates.w; - float startY = static_cast(ySize) - 2.0f * font_size; - startY = startY - font_size * 15.0f * 2.0f; + float startY = static_cast(ySize) - 2.0f * font_size; + startY = startY - font_size * 15.0f * 2.0f; - const glm::vec4 red(1, 0, 0, 1); - const glm::vec4 green(0, 1, 0, 1); - const glm::vec4 white(1, 1, 1, 1); + const glm::vec4 red(1, 0, 0, 1); + const glm::vec4 green(0, 1, 0, 1); + const glm::vec4 white(1, 1, 1, 1); std::shared_ptr font = OsEng.fontManager().font("Mono", font_size); using ghoul::fontrendering::RenderFont; @@ -324,106 +322,106 @@ void LuaConsole::render() { RenderFont(*font, glm::vec2(15.f, startY), red, "$"); RenderFont(*font, glm::vec2(15.f + font_size, startY), white, "%s", _commands.at(_activeCommand).c_str()); - size_t n = std::count(_commands.at(_activeCommand).begin(), _commands.at(_activeCommand).begin() + _inputPosition, '\n'); - size_t p = _commands.at(_activeCommand).find_last_of('\n', _inputPosition); - size_t linepos = _inputPosition; + size_t n = std::count(_commands.at(_activeCommand).begin(), _commands.at(_activeCommand).begin() + _inputPosition, '\n'); + size_t p = _commands.at(_activeCommand).find_last_of('\n', _inputPosition); + size_t linepos = _inputPosition; - if (n>0) { - if (p == _inputPosition) { - p = _commands.at(_activeCommand).find_last_of('\n', _inputPosition - 1); - if (p != std::string::npos) { - linepos -= p + 1; - } - else { - linepos = _inputPosition - 1; - } - } - else{ - linepos -= p + 1; - } - } + if (n>0) { + if (p == _inputPosition) { + p = _commands.at(_activeCommand).find_last_of('\n', _inputPosition - 1); + if (p != std::string::npos) { + linepos -= p + 1; + } + else { + linepos = _inputPosition - 1; + } + } + else{ + linepos -= p + 1; + } + } - std::stringstream ss; - ss << "%" << linepos + 1 << "s"; + std::stringstream ss; + ss << "%" << linepos + 1 << "s"; RenderFont(*font, glm::vec2(15.f + font_size * 0.5f, startY - (font_size)*(n + 1)*3.0f / 2.0f), green, ss.str().c_str(), "^"); // sgct_text::print(font, 15.0f + font_size*0.5f, startY - (font_size)*(n + 1)*3.0f / 2.0f, green, ss.str().c_str(), "^"); } Key LuaConsole::commandInputButton() { - // Button left of 1 and above TAB + // Button left of 1 and above TAB // How to deal with different keyboard languages? ---abock return Key::GraveAccent; } void LuaConsole::addToCommand(std::string c) { - size_t length = c.length(); - _commands.at(_activeCommand).insert(_inputPosition, c); - _inputPosition += length; + size_t length = c.length(); + _commands.at(_activeCommand).insert(_inputPosition, c); + _inputPosition += length; } std::string LuaConsole::UnicodeToUTF8(unsigned int codepoint) { - std::string out; + std::string out; - if (codepoint <= 0x7f) - out.append(1, static_cast(codepoint)); - else if (codepoint <= 0x7ff) - { - out.append(1, static_cast(0xc0 | ((codepoint >> 6) & 0x1f))); - out.append(1, static_cast(0x80 | (codepoint & 0x3f))); - } - else if (codepoint <= 0xffff) - { - out.append(1, static_cast(0xe0 | ((codepoint >> 12) & 0x0f))); - out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); - out.append(1, static_cast(0x80 | (codepoint & 0x3f))); - } - else - { - out.append(1, static_cast(0xf0 | ((codepoint >> 18) & 0x07))); - out.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3f))); - out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); - out.append(1, static_cast(0x80 | (codepoint & 0x3f))); - } - return out; + if (codepoint <= 0x7f) + out.append(1, static_cast(codepoint)); + else if (codepoint <= 0x7ff) + { + out.append(1, static_cast(0xc0 | ((codepoint >> 6) & 0x1f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + else if (codepoint <= 0xffff) + { + out.append(1, static_cast(0xe0 | ((codepoint >> 12) & 0x0f))); + out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + else + { + out.append(1, static_cast(0xf0 | ((codepoint >> 18) & 0x07))); + out.append(1, static_cast(0x80 | ((codepoint >> 12) & 0x3f))); + out.append(1, static_cast(0x80 | ((codepoint >> 6) & 0x3f))); + out.append(1, static_cast(0x80 | (codepoint & 0x3f))); + } + return out; } bool LuaConsole::isVisible() const { - return _isVisible; + return _isVisible; } void LuaConsole::setVisible(bool visible) { - _isVisible = visible; + _isVisible = visible; } void LuaConsole::toggleVisibility() { - _isVisible = !_isVisible; + _isVisible = !_isVisible; } scripting::ScriptEngine::LuaLibrary LuaConsole::luaLibrary() { - return { - "console", - { - { - "show", - &luascriptfunctions::show, - "", - "Shows the console" - }, - { - "hide", - &luascriptfunctions::hide, - "", - "Hides the console" - }, - { - "toggle", - &luascriptfunctions::toggle, - "", - "Toggles the console" - } - } - }; + return { + "console", + { + { + "show", + &luascriptfunctions::show, + "", + "Shows the console" + }, + { + "hide", + &luascriptfunctions::hide, + "", + "Hides the console" + }, + { + "toggle", + &luascriptfunctions::toggle, + "", + "Toggles the console" + } + } + }; } From f76d65cf191eac8dfae3e8dc37556014eb51970a Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 15:11:13 +0200 Subject: [PATCH 32/38] Remove high-resolution Mars kernel and fall back to regular de430 kernel Use correct PlutoProject path instead of previous PlutoProjectionHybrid Updated Ghoul version --- data/scene/mars/mars.data | 2 +- data/scene/mars/mars.mod | 2 +- .../newhorizons/pluto/plutoprojection/plutoprojection.mod | 4 ++-- ext/ghoul | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/data/scene/mars/mars.data b/data/scene/mars/mars.data index fdb9a8d161..afaf7ab69d 100644 --- a/data/scene/mars/mars.data +++ b/data/scene/mars/mars.data @@ -3,6 +3,6 @@ return { { Identifier = "mars_textures", Destination = "textures", Version = 1 } }, TorrentFiles = { - { File = "MAR063.BSP.torrent", Destination = "${SPICE}" } + -- { File = "MAR063.BSP.torrent", Destination = "${SPICE}" } } } \ No newline at end of file diff --git a/data/scene/mars/mars.mod b/data/scene/mars/mars.mod index 7e60f4c79b..ba4605c8f3 100644 --- a/data/scene/mars/mars.mod +++ b/data/scene/mars/mars.mod @@ -37,7 +37,7 @@ return { Reference = "ECLIPJ2000", Observer = "SUN", Kernels = { - "${OPENSPACE_DATA}/spice/MAR063.BSP" + "${OPENSPACE_DATA}/spice/de430_1850-2150.bsp" } }, Rotation = { diff --git a/data/scene/newhorizons/pluto/plutoprojection/plutoprojection.mod b/data/scene/newhorizons/pluto/plutoprojection/plutoprojection.mod index 706000d4fd..2338b3653d 100644 --- a/data/scene/newhorizons/pluto/plutoprojection/plutoprojection.mod +++ b/data/scene/newhorizons/pluto/plutoprojection/plutoprojection.mod @@ -50,8 +50,8 @@ return { MieColor = {1.0, 1.0, 1.0} }, Projection = { - Sequence = "${OPENSPACE_DATA}/scene/newhorizons/pluto/plutoprojectionhybrid/images", - EventFile = "${OPENSPACE_DATA}/scene/newhorizons/pluto/plutoprojectionhybrid/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt", + Sequence = "${OPENSPACE_DATA}/scene/newhorizons/pluto/plutoprojection/images", + EventFile = "${OPENSPACE_DATA}/scene/newhorizons/pluto/plutoprojection/assets/core_v9h_obs_getmets_v8_time_fix_nofrcd_mld.txt", SequenceType = "hybrid", Observer = "NEW HORIZONS", Target = "PLUTO", diff --git a/ext/ghoul b/ext/ghoul index 5cecda6057..f3c46149dd 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 5cecda605764688065b282e0cb3b7ae16257d305 +Subproject commit f3c46149dd6e224f565a8fced5e3eeff003828bc From f0748505b79a1180fe11e87d22e2169eb02d1bb0 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 15:12:40 +0200 Subject: [PATCH 33/38] Include VisualStudioOutputLog Correctly allow '/' character in SceneGraph description files --- src/engine/openspaceengine.cpp | 475 +++++++++++++++++---------------- src/scene/scenegraph.cpp | 16 +- 2 files changed, 253 insertions(+), 238 deletions(-) diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 212890124d..b4c4aa6405 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,10 @@ #endif #endif +#ifdef WIN32 +#include +#endif + using namespace openspace::scripting; using namespace ghoul::filesystem; using namespace ghoul::logging; @@ -79,7 +84,7 @@ using namespace ghoul::cmdparser; namespace { const std::string _loggerCat = "OpenSpaceEngine"; const std::string _sgctDefaultConfigFile = "${SGCT}/single.xml"; - const std::string _defaultCacheLocation = "${BASE_PATH}/cache"; + const std::string _defaultCacheLocation = "${BASE_PATH}/cache"; const std::string _sgctConfigArgumentCommand = "-config"; @@ -88,7 +93,7 @@ namespace { struct { std::string configurationName; - std::string sgctConfigurationName; + std::string sgctConfigurationName; std::string sceneName; } commandlineArgumentPlaceholders; } @@ -113,7 +118,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, , _parallelConnection(new network::ParallelConnection) , _windowWrapper(std::move(windowWrapper)) , _globalPropertyNamespace(new properties::PropertyOwner) - , _isMaster(false) + , _isMaster(false) , _runTime(0.0) , _syncBuffer(new SyncBuffer(1024)) { @@ -147,7 +152,7 @@ OpenSpaceEngine::~OpenSpaceEngine() { _console = nullptr; _moduleEngine = nullptr; _gui = nullptr; - _syncBuffer = nullptr; + _syncBuffer = nullptr; } OpenSpaceEngine& OpenSpaceEngine::ref() { @@ -164,18 +169,18 @@ bool OpenSpaceEngine::create(int argc, char** argv, ghoul::initialize(); - // Initialize the LogManager and add the console log as this will be used every time - // and we need a fall back if something goes wrong between here and when we add the - // logs from the configuration file. If the user requested as specific loglevel in the - // configuration file, we will deinitialize this LogManager and reinitialize it later - // with the correct LogLevel - LogManager::initialize( + // Initialize the LogManager and add the console log as this will be used every time + // and we need a fall back if something goes wrong between here and when we add the + // logs from the configuration file. If the user requested as specific loglevel in the + // configuration file, we will deinitialize this LogManager and reinitialize it later + // with the correct LogLevel + LogManager::initialize( LogManager::LogLevel::Debug, ghoul::logging::LogManager::ImmediateFlush::Yes ); LogMgr.addLog(std::make_unique()); - LDEBUG("Initialize FileSystem"); + LDEBUG("Initialize FileSystem"); #ifdef __APPLE__ ghoul::filesystem::File app(argv[0]); @@ -184,33 +189,33 @@ bool OpenSpaceEngine::create(int argc, char** argv, FileSys.setCurrentDirectory(dirName); #endif - // Sanity check of values - if (argc < 1 || argv == nullptr) { - LFATAL("No arguments were passed to this function"); - return false; - } + // Sanity check of values + if (argc < 1 || argv == nullptr) { + LFATAL("No arguments were passed to this function"); + return false; + } - // Create other objects - LDEBUG("Creating OpenSpaceEngine"); + // Create other objects + LDEBUG("Creating OpenSpaceEngine"); _engine = new OpenSpaceEngine(std::string(argv[0]), std::move(windowWrapper)); - // Query modules for commandline arguments - bool gatherSuccess = _engine->gatherCommandlineArguments(); - if (!gatherSuccess) - return false; + // Query modules for commandline arguments + bool gatherSuccess = _engine->gatherCommandlineArguments(); + if (!gatherSuccess) + return false; - // Parse commandline arguments + // Parse commandline arguments sgctArguments = *(_engine->_commandlineParser->setCommandLine(argc, argv)); - bool showHelp = _engine->_commandlineParser->execute(); + bool showHelp = _engine->_commandlineParser->execute(); if (showHelp) { _engine->_commandlineParser->displayHelp(); return false; } - // Find configuration - std::string configurationFilePath = commandlineArgumentPlaceholders.configurationName; - if (configurationFilePath.empty()) { - LDEBUG("Finding configuration"); + // Find configuration + std::string configurationFilePath = commandlineArgumentPlaceholders.configurationName; + if (configurationFilePath.empty()) { + LDEBUG("Finding configuration"); try { configurationFilePath = ConfigurationManager::findConfiguration(configurationFilePath); @@ -218,12 +223,12 @@ bool OpenSpaceEngine::create(int argc, char** argv, catch (const ghoul::RuntimeError& e) { LFATALC(e.component, e.message); } - } - configurationFilePath = absPath(configurationFilePath); - LINFO("Configuration Path: '" << configurationFilePath << "'"); + } + configurationFilePath = absPath(configurationFilePath); + LINFO("Configuration Path: '" << configurationFilePath << "'"); - // Loading configuration from disk - LDEBUG("Loading configuration from disk"); + // Loading configuration from disk + LDEBUG("Loading configuration from disk"); try { _engine->configurationManager().loadFromFile(configurationFilePath); } @@ -233,55 +238,55 @@ bool OpenSpaceEngine::create(int argc, char** argv, return false; } - // Initialize the requested logs from the configuration file - _engine->configureLogging(); + // Initialize the requested logs from the configuration file + _engine->configureLogging(); LINFOC("OpenSpace Version", OPENSPACE_VERSION_MAJOR << "." << OPENSPACE_VERSION_MINOR << "." << OPENSPACE_VERSION_PATCH << " (" << OPENSPACE_VERSION_STRING << ")"); - // Create directories that doesn't exist - auto tokens = FileSys.tokens(); - for (const std::string& token : tokens) { - if (!FileSys.directoryExists(token)) { - std::string p = absPath(token); - LDEBUG("Directory '" << p << "' does not exist, creating."); + // Create directories that doesn't exist + auto tokens = FileSys.tokens(); + for (const std::string& token : tokens) { + if (!FileSys.directoryExists(token)) { + std::string p = absPath(token); + LDEBUG("Directory '" << p << "' does not exist, creating."); FileSys.createDirectory(p, ghoul::filesystem::FileSystem::Recursive::Yes); - } - } + } + } // Register modules _engine->_moduleEngine->initialize(); - // Create the cachemanager - FileSys.createCacheManager( + // Create the cachemanager + FileSys.createCacheManager( absPath("${" + ConfigurationManager::KeyCache + "}"), CacheVersion ); - _engine->_console->initialize(); + _engine->_console->initialize(); - // Register the provided shader directories - ghoul::opengl::ShaderPreprocessor::addIncludePath(absPath("${SHADERS}")); + // Register the provided shader directories + ghoul::opengl::ShaderPreprocessor::addIncludePath(absPath("${SHADERS}")); - // Determining SGCT configuration file - LDEBUG("Determining SGCT configuration file"); - std::string sgctConfigurationPath = _sgctDefaultConfigFile; - _engine->configurationManager().getValue( - ConfigurationManager::KeyConfigSgct, sgctConfigurationPath); + // Determining SGCT configuration file + LDEBUG("Determining SGCT configuration file"); + std::string sgctConfigurationPath = _sgctDefaultConfigFile; + _engine->configurationManager().getValue( + ConfigurationManager::KeyConfigSgct, sgctConfigurationPath); - if (!commandlineArgumentPlaceholders.sgctConfigurationName.empty()) { - LDEBUG("Overwriting SGCT configuration file with commandline argument: " << - commandlineArgumentPlaceholders.sgctConfigurationName); - sgctConfigurationPath = commandlineArgumentPlaceholders.sgctConfigurationName; - } + if (!commandlineArgumentPlaceholders.sgctConfigurationName.empty()) { + LDEBUG("Overwriting SGCT configuration file with commandline argument: " << + commandlineArgumentPlaceholders.sgctConfigurationName); + sgctConfigurationPath = commandlineArgumentPlaceholders.sgctConfigurationName; + } - // Prepend the outgoing sgctArguments with the program name - // as well as the configuration file that sgct is supposed to use - sgctArguments.insert(sgctArguments.begin(), argv[0]); - sgctArguments.insert(sgctArguments.begin() + 1, _sgctConfigArgumentCommand); - sgctArguments.insert(sgctArguments.begin() + 2, absPath(sgctConfigurationPath)); + // Prepend the outgoing sgctArguments with the program name + // as well as the configuration file that sgct is supposed to use + sgctArguments.insert(sgctArguments.begin(), argv[0]); + sgctArguments.insert(sgctArguments.begin() + 1, _sgctConfigArgumentCommand); + sgctArguments.insert(sgctArguments.begin() + 2, absPath(sgctConfigurationPath)); - return true; + return true; } void OpenSpaceEngine::destroy() { @@ -289,30 +294,30 @@ void OpenSpaceEngine::destroy() { _engine->_console->deinitialize(); _engine->_scriptEngine->deinitialize(); - delete _engine; - ghoul::systemcapabilities::SystemCapabilities::deinitialize(); - FactoryManager::deinitialize(); - Time::deinitialize(); - SpiceManager::deinitialize(); + delete _engine; + ghoul::systemcapabilities::SystemCapabilities::deinitialize(); + FactoryManager::deinitialize(); + Time::deinitialize(); + SpiceManager::deinitialize(); - LogManager::deinitialize(); + LogManager::deinitialize(); ghoul::deinitialize(); } bool OpenSpaceEngine::initialize() { - // clear the screen so the user don't have to see old buffer contents from the - // graphics card - clearAllWindows(); + // clear the screen so the user don't have to see old buffer contents from the + // graphics card + clearAllWindows(); - // Detect and log OpenCL and OpenGL versions and available devices + // Detect and log OpenCL and OpenGL versions and available devices SysCap.addComponent( std::make_unique() ); SysCap.addComponent( std::make_unique() ); - SysCap.detectCapabilities(); + SysCap.detectCapabilities(); using Verbosity = ghoul::systemcapabilities::SystemCapabilitiesComponent::Verbosity; Verbosity verbosity = Verbosity::Default; @@ -328,43 +333,43 @@ bool OpenSpaceEngine::initialize() { if (verbosityMap.find(v) != verbosityMap.end()) verbosity = verbosityMap[v]; } - SysCap.logCapabilities(verbosity); + SysCap.logCapabilities(verbosity); std::string requestURL = ""; bool success = configurationManager().getValue(ConfigurationManager::KeyDownloadRequestURL, requestURL); if (success) DownloadManager::initialize(requestURL, DownloadVersion); - // Load SPICE time kernel - success = loadSpiceKernels(); - if (!success) - return false; + // Load SPICE time kernel + success = loadSpiceKernels(); + if (!success) + return false; - // Register Lua script functions - LDEBUG("Registering Lua libraries"); - _scriptEngine->addLibrary(RenderEngine::luaLibrary()); - _scriptEngine->addLibrary(Scene::luaLibrary()); - _scriptEngine->addLibrary(Time::luaLibrary()); - _scriptEngine->addLibrary(interaction::InteractionHandler::luaLibrary()); - _scriptEngine->addLibrary(LuaConsole::luaLibrary()); - _scriptEngine->addLibrary(gui::GUI::luaLibrary()); + // Register Lua script functions + LDEBUG("Registering Lua libraries"); + _scriptEngine->addLibrary(RenderEngine::luaLibrary()); + _scriptEngine->addLibrary(Scene::luaLibrary()); + _scriptEngine->addLibrary(Time::luaLibrary()); + _scriptEngine->addLibrary(interaction::InteractionHandler::luaLibrary()); + _scriptEngine->addLibrary(LuaConsole::luaLibrary()); + _scriptEngine->addLibrary(gui::GUI::luaLibrary()); _scriptEngine->addLibrary(network::ParallelConnection::luaLibrary()); - // TODO: Maybe move all scenegraph and renderengine stuff to initializeGL - scriptEngine().initialize(); + // TODO: Maybe move all scenegraph and renderengine stuff to initializeGL + scriptEngine().initialize(); - // If a LuaDocumentationFile was specified, generate it now - const bool hasType = configurationManager().hasKey(ConfigurationManager::KeyLuaDocumentationType); - const bool hasFile = configurationManager().hasKey(ConfigurationManager::KeyLuaDocumentationFile); - if (hasType && hasFile) { - std::string luaDocumentationType; - configurationManager().getValue(ConfigurationManager::KeyLuaDocumentationType, luaDocumentationType); - std::string luaDocumentationFile; - configurationManager().getValue(ConfigurationManager::KeyLuaDocumentationFile, luaDocumentationFile); + // If a LuaDocumentationFile was specified, generate it now + const bool hasType = configurationManager().hasKey(ConfigurationManager::KeyLuaDocumentationType); + const bool hasFile = configurationManager().hasKey(ConfigurationManager::KeyLuaDocumentationFile); + if (hasType && hasFile) { + std::string luaDocumentationType; + configurationManager().getValue(ConfigurationManager::KeyLuaDocumentationType, luaDocumentationType); + std::string luaDocumentationFile; + configurationManager().getValue(ConfigurationManager::KeyLuaDocumentationFile, luaDocumentationFile); - luaDocumentationFile = absPath(luaDocumentationFile); - _scriptEngine->writeDocumentation(luaDocumentationFile, luaDocumentationType); - } + luaDocumentationFile = absPath(luaDocumentationFile); + _scriptEngine->writeDocumentation(luaDocumentationFile, luaDocumentationType); + } bool disableMasterRendering = false; configurationManager().getValue( @@ -372,41 +377,41 @@ bool OpenSpaceEngine::initialize() { _renderEngine->setDisableRenderingOnMaster(disableMasterRendering); - // Load scenegraph - Scene* sceneGraph = new Scene; - _renderEngine->setSceneGraph(sceneGraph); + // Load scenegraph + Scene* sceneGraph = new Scene; + _renderEngine->setSceneGraph(sceneGraph); - // initialize the RenderEngine + // initialize the RenderEngine _renderEngine->initialize(); - sceneGraph->initialize(); + sceneGraph->initialize(); std::string sceneDescriptionPath = ""; if (commandlineArgumentPlaceholders.sceneName.empty()) { - success = configurationManager().getValue( - ConfigurationManager::KeyConfigScene, sceneDescriptionPath); + success = configurationManager().getValue( + ConfigurationManager::KeyConfigScene, sceneDescriptionPath); } else sceneDescriptionPath = commandlineArgumentPlaceholders.sceneName; - sceneGraph->scheduleLoadSceneFile(sceneDescriptionPath); + sceneGraph->scheduleLoadSceneFile(sceneDescriptionPath); - _interactionHandler->setKeyboardController(new interaction::KeyboardControllerFixed); - _interactionHandler->setMouseController(new interaction::OrbitalMouseController); + _interactionHandler->setKeyboardController(new interaction::KeyboardControllerFixed); + _interactionHandler->setMouseController(new interaction::OrbitalMouseController); - // Run start up scripts - runStartupScripts(); + // Run start up scripts + runStartupScripts(); - // Load a light and a monospaced font + // Load a light and a monospaced font loadFonts(); LINFO("Initializing GUI"); - _gui->initialize(); + _gui->initialize(); LINFO("Finished initializing"); - return true; + return true; } bool OpenSpaceEngine::isInitialized() { - return _engine != nullptr; + return _engine != nullptr; } void OpenSpaceEngine::clearAllWindows() { @@ -416,13 +421,13 @@ void OpenSpaceEngine::clearAllWindows() { bool OpenSpaceEngine::gatherCommandlineArguments() { // TODO: Get commandline arguments from all modules - commandlineArgumentPlaceholders.configurationName = ""; + commandlineArgumentPlaceholders.configurationName = ""; _commandlineParser->addCommand(std::make_unique>( &commandlineArgumentPlaceholders.configurationName, "-config", "-c", "Provides the path to the OpenSpace configuration file" )); - commandlineArgumentPlaceholders.sgctConfigurationName = ""; + commandlineArgumentPlaceholders.sgctConfigurationName = ""; _commandlineParser->addCommand(std::make_unique>( &commandlineArgumentPlaceholders.sgctConfigurationName, "-sgct", "-s", "Provides the path to the SGCT configuration file, overriding the value set in " @@ -439,27 +444,27 @@ bool OpenSpaceEngine::gatherCommandlineArguments() { } bool OpenSpaceEngine::loadSpiceKernels() { - // Load time kernel - std::string timeKernel; - bool success = configurationManager().getValue(ConfigurationManager::KeySpiceTimeKernel, timeKernel); + // Load time kernel + std::string timeKernel; + bool success = configurationManager().getValue(ConfigurationManager::KeySpiceTimeKernel, timeKernel); // Move this to configurationmanager::completenesscheck ---abock - if (!success) { - LERROR("Configuration file does not contain a '" << ConfigurationManager::KeySpiceTimeKernel << "'"); - return false; - } - SpiceManager::KernelHandle id = - SpiceManager::ref().loadKernel(timeKernel); + if (!success) { + LERROR("Configuration file does not contain a '" << ConfigurationManager::KeySpiceTimeKernel << "'"); + return false; + } + SpiceManager::KernelHandle id = + SpiceManager::ref().loadKernel(timeKernel); - // Load SPICE leap second kernel - std::string leapSecondKernel; - success = configurationManager().getValue(ConfigurationManager::KeySpiceLeapsecondKernel, leapSecondKernel); - if (!success) { + // Load SPICE leap second kernel + std::string leapSecondKernel; + success = configurationManager().getValue(ConfigurationManager::KeySpiceLeapsecondKernel, leapSecondKernel); + if (!success) { // Move this to configurationmanager::completenesscheck ---abock - LERROR("Configuration file does not have a '" << ConfigurationManager::KeySpiceLeapsecondKernel << "'"); - return false; - } - id = SpiceManager::ref().loadKernel(std::move(leapSecondKernel)); - return true; + LERROR("Configuration file does not have a '" << ConfigurationManager::KeySpiceLeapsecondKernel << "'"); + return false; + } + id = SpiceManager::ref().loadKernel(std::move(leapSecondKernel)); + return true; } void OpenSpaceEngine::runScripts(const ghoul::Dictionary& scripts) { @@ -500,9 +505,9 @@ void OpenSpaceEngine::runScripts(const ghoul::Dictionary& scripts) { void OpenSpaceEngine::runStartupScripts() { - ghoul::Dictionary scripts; - configurationManager().getValue( - ConfigurationManager::KeyStartupScript, scripts); + ghoul::Dictionary scripts; + configurationManager().getValue( + ConfigurationManager::KeyStartupScript, scripts); runScripts(scripts); } @@ -546,30 +551,30 @@ void OpenSpaceEngine::loadFonts() { } void OpenSpaceEngine::configureLogging() { - if (configurationManager().hasKeyAndValue(ConfigurationManager::KeyLogLevel)) { - std::string logLevel; - configurationManager().getValue(ConfigurationManager::KeyLogLevel, logLevel); + if (configurationManager().hasKeyAndValue(ConfigurationManager::KeyLogLevel)) { + std::string logLevel; + configurationManager().getValue(ConfigurationManager::KeyLogLevel, logLevel); - bool immediateFlush = false; - configurationManager().getValue(ConfigurationManager::KeyLogImmediateFlush, immediateFlush); + bool immediateFlush = false; + configurationManager().getValue(ConfigurationManager::KeyLogImmediateFlush, immediateFlush); - LogManager::LogLevel level = LogManager::levelFromString(logLevel); - LogManager::deinitialize(); + LogManager::LogLevel level = LogManager::levelFromString(logLevel); + LogManager::deinitialize(); using ImmediateFlush = ghoul::logging::LogManager::ImmediateFlush; LogManager::initialize( level, immediateFlush ? ImmediateFlush::Yes : ImmediateFlush::No ); - LogMgr.addLog(std::make_unique()); - } + LogMgr.addLog(std::make_unique()); + } - if (configurationManager().hasKeyAndValue(ConfigurationManager::KeyLogs)) { - ghoul::Dictionary logs; - configurationManager().getValue(ConfigurationManager::KeyLogs, logs); + if (configurationManager().hasKeyAndValue(ConfigurationManager::KeyLogs)) { + ghoul::Dictionary logs; + configurationManager().getValue(ConfigurationManager::KeyLogs, logs); - for (size_t i = 1; i <= logs.size(); ++i) { - ghoul::Dictionary logInfo; - logs.getValue(std::to_string(i), logInfo); + for (size_t i = 1; i <= logs.size(); ++i) { + ghoul::Dictionary logInfo; + logs.getValue(std::to_string(i), logInfo); try { LogMgr.addLog(createLog(logInfo)); @@ -577,8 +582,14 @@ void OpenSpaceEngine::configureLogging() { catch (const ghoul::RuntimeError& e) { LERRORC(e.component, e.message); } - } - } + } + } + +#ifdef WIN32 + if (IsDebuggerPresent()) { + LogMgr.addLog(std::make_unique()); + } +#endif // WIN32 } bool OpenSpaceEngine::initializeGL() { @@ -592,15 +603,15 @@ bool OpenSpaceEngine::initializeGL() { LERROR(e.what()); } LINFO("Finished initializing OpenGL"); - return success; + return success; } bool OpenSpaceEngine::isMaster(){ - return _isMaster; + return _isMaster; } void OpenSpaceEngine::setMaster(bool master){ - _isMaster = master; + _isMaster = master; } double OpenSpaceEngine::runTime(){ @@ -612,24 +623,24 @@ void OpenSpaceEngine::setRunTime(double d){ } void OpenSpaceEngine::preSynchronization() { - FileSys.triggerFilesystemEvents(); + FileSys.triggerFilesystemEvents(); if (_isMaster) { double dt = _windowWrapper->averageDeltaTime(); - Time::ref().advanceTime(dt); - Time::ref().preSynchronization(); - + Time::ref().advanceTime(dt); + Time::ref().preSynchronization(); + _interactionHandler->update(dt); - _scriptEngine->preSynchronization(); + _scriptEngine->preSynchronization(); _renderEngine->preSynchronization(); _parallelConnection->preSynchronization(); } } void OpenSpaceEngine::postSynchronizationPreDraw() { - Time::ref().postSynchronizationPreDraw(); + Time::ref().postSynchronizationPreDraw(); - _scriptEngine->postSynchronizationPreDraw(); + _scriptEngine->postSynchronizationPreDraw(); _renderEngine->postSynchronizationPreDraw(); if (_isMaster && _gui->isEnabled() && _windowWrapper->isRegularRendering()) { @@ -639,116 +650,116 @@ void OpenSpaceEngine::postSynchronizationPreDraw() { double dt = _windowWrapper->averageDeltaTime(); - _gui->startFrame(static_cast(dt), glm::vec2(drawBufferResolution), mousePosition, mouseButtons); - } + _gui->startFrame(static_cast(dt), glm::vec2(drawBufferResolution), mousePosition, mouseButtons); + } } void OpenSpaceEngine::render(const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix) { _renderEngine->render(projectionMatrix, viewMatrix); - if (_isMaster && _windowWrapper->isRegularRendering()) { + if (_isMaster && _windowWrapper->isRegularRendering()) { if (_console->isVisible()) - _console->render(); - if (_gui->isEnabled()) - _gui->endFrame(); - } + _console->render(); + if (_gui->isEnabled()) + _gui->endFrame(); + } } void OpenSpaceEngine::postDraw() { - _renderEngine->postDraw(); + _renderEngine->postDraw(); } void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction action) { - if (_isMaster) { - if (_gui->isEnabled()) { - bool isConsumed = _gui->keyCallback(key, mod, action); - if (isConsumed) - return; - } + if (_isMaster) { + if (_gui->isEnabled()) { + bool isConsumed = _gui->keyCallback(key, mod, action); + if (isConsumed) + return; + } if (key == _console->commandInputButton() && (action == KeyAction::Press || action == KeyAction::Repeat)) - _console->toggleVisibility(); + _console->toggleVisibility(); - if (!_console->isVisible()) { - _interactionHandler->keyboardCallback(key, mod, action); - } - else { - _console->keyboardCallback(key, mod, action); - } - } + if (!_console->isVisible()) { + _interactionHandler->keyboardCallback(key, mod, action); + } + else { + _console->keyboardCallback(key, mod, action); + } + } } void OpenSpaceEngine::charCallback(unsigned int codepoint, KeyModifier modifier) { - if (_isMaster) { - if (_gui->isEnabled()) { - const bool isConsumed = _gui->charCallback(codepoint, modifier); - if (isConsumed) - return; - } + if (_isMaster) { + if (_gui->isEnabled()) { + const bool isConsumed = _gui->charCallback(codepoint, modifier); + if (isConsumed) + return; + } - if (_console->isVisible()) { - _console->charCallback(codepoint, modifier); - } - } + if (_console->isVisible()) { + _console->charCallback(codepoint, modifier); + } + } } void OpenSpaceEngine::mouseButtonCallback(MouseButton button, MouseAction action) { - if (_isMaster) { - if (_gui->isEnabled()) { - const bool isConsumed = _gui->mouseButtonCallback(button, action); + if (_isMaster) { + if (_gui->isEnabled()) { + const bool isConsumed = _gui->mouseButtonCallback(button, action); if (isConsumed && action != MouseAction::Release) - return; - } + return; + } - _interactionHandler->mouseButtonCallback(button, action); - } + _interactionHandler->mouseButtonCallback(button, action); + } } void OpenSpaceEngine::mousePositionCallback(double x, double y) { - if (_isMaster) { - _interactionHandler->mousePositionCallback(x, y); - } + if (_isMaster) { + _interactionHandler->mousePositionCallback(x, y); + } } void OpenSpaceEngine::mouseScrollWheelCallback(double pos) { - if (_isMaster) { - if (_gui->isEnabled()) { - const bool isConsumed = _gui->mouseWheelCallback(pos); - if (isConsumed) - return; - } + if (_isMaster) { + if (_gui->isEnabled()) { + const bool isConsumed = _gui->mouseWheelCallback(pos); + if (isConsumed) + return; + } - _interactionHandler->mouseScrollWheelCallback(pos); - } + _interactionHandler->mouseScrollWheelCallback(pos); + } } void OpenSpaceEngine::encode() { - if (_syncBuffer) { - Time::ref().serialize(_syncBuffer.get()); - _scriptEngine->serialize(_syncBuffer.get()); - _renderEngine->serialize(_syncBuffer.get()); - - _syncBuffer->write(); - } + if (_syncBuffer) { + Time::ref().serialize(_syncBuffer.get()); + _scriptEngine->serialize(_syncBuffer.get()); + _renderEngine->serialize(_syncBuffer.get()); + + _syncBuffer->write(); + } _networkEngine->publishStatusMessage(); _networkEngine->sendMessages(); } void OpenSpaceEngine::decode() { - if (_syncBuffer) { - _syncBuffer->read(); + if (_syncBuffer) { + _syncBuffer->read(); - Time::ref().deserialize(_syncBuffer.get()); - _scriptEngine->deserialize(_syncBuffer.get()); - _renderEngine->deserialize(_syncBuffer.get()); - } + Time::ref().deserialize(_syncBuffer.get()); + _scriptEngine->deserialize(_syncBuffer.get()); + _renderEngine->deserialize(_syncBuffer.get()); + } } void OpenSpaceEngine::externalControlCallback(const char* receivedChars, int size, int clientId) { - if (size == 0) - return; + if (size == 0) + return; _networkEngine->handleMessage(std::string(receivedChars, size)); } diff --git a/src/scene/scenegraph.cpp b/src/scene/scenegraph.cpp index 11f59c3675..78848535f7 100644 --- a/src/scene/scenegraph.cpp +++ b/src/scene/scenegraph.cpp @@ -43,8 +43,8 @@ namespace { const std::string _loggerCat = "SceneGraph"; const std::string _moduleExtension = ".mod"; - const std::string _defaultCommonDirectory = "common"; - const std::string _commonModuleToken = "${COMMON_MODULE}"; + const std::string _defaultCommonDirectory = "common"; + const std::string _commonModuleToken = "${COMMON_MODULE}"; const std::string KeyPathScene = "ScenePath"; const std::string KeyModules = "Modules"; @@ -176,6 +176,9 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory(); for (const std::string& key : keys) { std::string fullModuleName = moduleDictionary.value(key); + + std::replace(fullModuleName.begin(), fullModuleName.end(), '/', FileSys.PathSeparator); + std::string modulePath = FileSys.pathByAppendingComponent(sceneDirectory, fullModuleName); std::string moduleName = fullModuleName; @@ -212,7 +215,8 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { moduleName }); } - catch (...) { + catch (const ghoul::lua::LuaRuntimeException& e) { + LERRORC(e.component, e.message); continue; } } @@ -235,8 +239,6 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { // string moduleName = s; if (!FileSys.fileExists(moduleFile)) { - LERROR("Could not find module file '" << moduleFile << "'. " - "Indirectly included through '" << modulePath << "'"); continue; } @@ -251,7 +253,8 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { moduleName }); } - catch (...) { + catch (const ghoul::lua::LuaRuntimeException& e) { + LERRORC(e.component, e.message); continue; } @@ -331,6 +334,7 @@ bool SceneGraph::loadFromFile(const std::string& sceneDescription) { SceneGraphNode* parentNode = sceneGraphNode(parent); if (parentNode == nullptr) { LERROR("Could not find parent '" << parent << "' for '" << node->node->name() << "'"); + continue; } node->node->setParent(parentNode); From c8da82509863c5c8b9cef47a54d12c644ce3c928 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 15:14:59 +0200 Subject: [PATCH 34/38] Rename ImageSequencer2 to ImageSequencer --- modules/base/ephemeris/spiceephemeris.cpp | 4 +- modules/base/rendering/renderablemodel.cpp | 8 +- modules/newhorizons/newhorizonsmodule.cpp | 2 +- .../rendering/renderablecrawlingline.cpp | 4 +- .../newhorizons/rendering/renderablefov.cpp | 6 +- .../rendering/renderablemodelprojection.cpp | 8 +- .../rendering/renderableplaneprojection.cpp | 4 +- .../rendering/renderableplanetprojection.cpp | 14 +- modules/newhorizons/util/imagesequencer.cpp | 516 +++--- modules/newhorizons/util/imagesequencer.h | 284 +-- src/rendering/renderengine.cpp | 1604 ++++++++--------- 11 files changed, 1227 insertions(+), 1227 deletions(-) diff --git a/modules/base/ephemeris/spiceephemeris.cpp b/modules/base/ephemeris/spiceephemeris.cpp index 588607897c..d597ea96a4 100644 --- a/modules/base/ephemeris/spiceephemeris.cpp +++ b/modules/base/ephemeris/spiceephemeris.cpp @@ -84,9 +84,9 @@ void SpiceEphemeris::update(const UpdateData& data) { double lightTime = 0.0; glm::dvec3 position = SpiceManager::ref().targetPosition(_targetName, _originName, "GALACTIC", {}, data.time, lightTime); - //double interval = openspace::ImageSequencer2::ref().getIntervalLength(); + //double interval = openspace::ImageSequencer::ref().getIntervalLength(); //if (_ghosting == "TRUE" && interval > 60){ - // double _time = openspace::ImageSequencer2::ref().getNextCaptureTime(); + // double _time = openspace::ImageSequencer::ref().getNextCaptureTime(); // SpiceManager::ref().getTargetPosition(_targetName, _originName, // "GALACTIC", "NONE", _time, position, lightTime); //} diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index f5a282e5b1..f3953a4896 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -234,10 +234,10 @@ void RenderableModel::update(const UpdateData& data) { double _time = data.time; //if (_isGhost){ - // futureTime = openspace::ImageSequencer2::ref().getNextCaptureTime(); - // double remaining = openspace::ImageSequencer2::ref().getNextCaptureTime() - data.time; - // double interval = openspace::ImageSequencer2::ref().getIntervalLength(); - // double t = 1.f - remaining / openspace::ImageSequencer2::ref().getIntervalLength(); + // futureTime = openspace::ImageSequencer::ref().getNextCaptureTime(); + // double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - data.time; + // double interval = openspace::ImageSequencer::ref().getIntervalLength(); + // double t = 1.f - remaining / openspace::ImageSequencer::ref().getIntervalLength(); // if (interval > 60) { // if (t < 0.8) // _fading = static_cast(t); diff --git a/modules/newhorizons/newhorizonsmodule.cpp b/modules/newhorizons/newhorizonsmodule.cpp index 5daadd11d2..466439e989 100644 --- a/modules/newhorizons/newhorizonsmodule.cpp +++ b/modules/newhorizons/newhorizonsmodule.cpp @@ -51,7 +51,7 @@ NewHorizonsModule::NewHorizonsModule() {} void NewHorizonsModule::internalInitialize() { - ImageSequencer2::initialize(); + ImageSequencer::initialize(); FactoryManager::ref().addFactory(std::make_unique>()); FactoryManager::ref().addFactory(std::make_unique>()); diff --git a/modules/newhorizons/rendering/renderablecrawlingline.cpp b/modules/newhorizons/rendering/renderablecrawlingline.cpp index 2b63e17383..063262723b 100644 --- a/modules/newhorizons/rendering/renderablecrawlingline.cpp +++ b/modules/newhorizons/rendering/renderablecrawlingline.cpp @@ -186,8 +186,8 @@ void RenderableCrawlingLine::update(const UpdateData& data) { _positions[TargetPosition] = target; - if (ImageSequencer2::ref().isReady()) { - _imageSequenceTime = ImageSequencer2::ref().instrumentActiveTime(_instrumentName); + if (ImageSequencer::ref().isReady()) { + _imageSequenceTime = ImageSequencer::ref().instrumentActiveTime(_instrumentName); _drawLine = _imageSequenceTime != -1.f; } } diff --git a/modules/newhorizons/rendering/renderablefov.cpp b/modules/newhorizons/rendering/renderablefov.cpp index f2131c3da8..889a5acf00 100644 --- a/modules/newhorizons/rendering/renderablefov.cpp +++ b/modules/newhorizons/rendering/renderablefov.cpp @@ -421,7 +421,7 @@ void RenderableFov::fovSurfaceIntercept(bool H[], std::vector bounds // This method is purely cosmetics, can very well be removed // but be sure to set colors somewhere. void RenderableFov::computeColors() { - double t2 = (openspace::ImageSequencer2::ref().getNextCaptureTime()); + double t2 = (openspace::ImageSequencer::ref().getNextCaptureTime()); double diff = (t2 - _time); float t = 0.0; float interpolationStart = 7.0; //seconds before @@ -551,8 +551,8 @@ void RenderableFov::render(const RenderData& data) { _programObject->setUniform("ModelTransform", glm::mat4(1)); setPscUniforms(*_programObject.get(), data.camera, data.position); - if (openspace::ImageSequencer2::ref().isReady()) - _drawFOV = ImageSequencer2::ref().instrumentActive(_instrumentID); + if (openspace::ImageSequencer::ref().isReady()) + _drawFOV = ImageSequencer::ref().instrumentActive(_instrumentID); if (_drawFOV){ // update only when time progresses. diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp index c50363f19a..0030eaabd5 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.cpp +++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp @@ -168,7 +168,7 @@ RenderableModelProjection::RenderableModelProjection(const ghoul::Dictionary& di dictionary.getValue(keyTranslation, translationDictionary); if (_sequenceType == sequenceTypeImage) { parser = new LabelParser(name, _sequenceSource, translationDictionary); - openspace::ImageSequencer2::ref().runSequenceParser(parser); + openspace::ImageSequencer::ref().runSequenceParser(parser); } } @@ -351,9 +351,9 @@ void RenderableModelProjection::update(const UpdateData& data) { _time = data.time; - if (openspace::ImageSequencer2::ref().isReady() && _performProjection) { - openspace::ImageSequencer2::ref().updateSequencer(_time); - _capture = openspace::ImageSequencer2::ref().getImagePaths(_imageTimes, _projecteeID, _instrumentID); + if (openspace::ImageSequencer::ref().isReady() && _performProjection) { + openspace::ImageSequencer::ref().updateSequencer(_time); + _capture = openspace::ImageSequencer::ref().getImagePaths(_imageTimes, _projecteeID, _instrumentID); } // set spice-orientation in accordance to timestamp diff --git a/modules/newhorizons/rendering/renderableplaneprojection.cpp b/modules/newhorizons/rendering/renderableplaneprojection.cpp index 5cd01ad5c9..cdbd73dc50 100644 --- a/modules/newhorizons/rendering/renderableplaneprojection.cpp +++ b/modules/newhorizons/rendering/renderableplaneprojection.cpp @@ -130,7 +130,7 @@ bool RenderablePlaneProjection::deinitialize() { } void RenderablePlaneProjection::render(const RenderData& data) { - bool active = ImageSequencer2::ref().instrumentActive(_instrument); + bool active = ImageSequencer::ref().instrumentActive(_instrument); if (!_hasImage || (_moving && !active)) return; @@ -165,7 +165,7 @@ void RenderablePlaneProjection::update(const UpdateData& data) { double time = data.time; - const Image img = openspace::ImageSequencer2::ref().getLatestImageForInstrument(_instrument); + const Image img = openspace::ImageSequencer::ref().getLatestImageForInstrument(_instrument); if (img.path == "") return; diff --git a/modules/newhorizons/rendering/renderableplanetprojection.cpp b/modules/newhorizons/rendering/renderableplanetprojection.cpp index 4e1a67cfd0..46f343e699 100644 --- a/modules/newhorizons/rendering/renderableplanetprojection.cpp +++ b/modules/newhorizons/rendering/renderableplanetprojection.cpp @@ -194,20 +194,20 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& _projectorID, translationDictionary, _potentialTargets); - openspace::ImageSequencer2::ref().runSequenceParser(parser); + openspace::ImageSequencer::ref().runSequenceParser(parser); } else if (_sequenceType == sequenceTypeImage) { parser = new LabelParser(name, _sequenceSource, translationDictionary); - openspace::ImageSequencer2::ref().runSequenceParser(parser); + openspace::ImageSequencer::ref().runSequenceParser(parser); } else if (_sequenceType == sequenceTypeHybrid) { //first read labels parser = new LabelParser(name, _sequenceSource, translationDictionary); - openspace::ImageSequencer2::ref().runSequenceParser(parser); + openspace::ImageSequencer::ref().runSequenceParser(parser); std::string _eventFile; bool foundEventFile = dictionary.getValue("Projection.EventFile", _eventFile); @@ -219,7 +219,7 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& _projectorID, translationDictionary, _potentialTargets); - openspace::ImageSequencer2::ref().runSequenceParser(parser); + openspace::ImageSequencer::ref().runSequenceParser(parser); } else{ LWARNING("No eventfile has been provided, please check modfiles"); @@ -561,9 +561,9 @@ void RenderablePlanetProjection::update(const UpdateData& data){ _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 (openspace::ImageSequencer::ref().isReady() && _performProjection){ + openspace::ImageSequencer::ref().updateSequencer(_time); + _capture = openspace::ImageSequencer::ref().getImagePaths(_imageTimes, _projecteeID, _instrumentID); } if (_fboProgramObject && _fboProgramObject->isDirty()) { diff --git a/modules/newhorizons/util/imagesequencer.cpp b/modules/newhorizons/util/imagesequencer.cpp index 1f334c562a..5c5a96c7e8 100644 --- a/modules/newhorizons/util/imagesequencer.cpp +++ b/modules/newhorizons/util/imagesequencer.cpp @@ -38,179 +38,179 @@ #include namespace { -const std::string _loggerCat = "ImageSequencer2"; +const std::string _loggerCat = "ImageSequencer"; } namespace openspace { -ImageSequencer2* ImageSequencer2::_instance = nullptr; +ImageSequencer* ImageSequencer::_instance = nullptr; -ImageSequencer2::ImageSequencer2() +ImageSequencer::ImageSequencer() : _hasData(false) {} -ImageSequencer2& ImageSequencer2::ref() { - assert(_instance != nullptr); - return *_instance; +ImageSequencer& ImageSequencer::ref() { + assert(_instance != nullptr); + return *_instance; } -void ImageSequencer2::initialize() { - assert(_instance == nullptr); - _instance = new ImageSequencer2; +void ImageSequencer::initialize() { + assert(_instance == nullptr); + _instance = new ImageSequencer; _instance->_defaultCaptureImage = absPath("${OPENSPACE_DATA}/scene/common/textures/placeholder_blank.png"); } -void ImageSequencer2::deinitialize() { - delete _instance; - _instance = nullptr; +void ImageSequencer::deinitialize() { + delete _instance; + _instance = nullptr; } -bool ImageSequencer2::isReady(){ - return _hasData; +bool ImageSequencer::isReady(){ + return _hasData; } -void ImageSequencer2::updateSequencer(double time){ - if (Time::ref().timeJumped() && Time::ref().deltaTime() == 0){ - Time::ref().setDeltaTime(0.1); - } // Time is not properly updated when time jump with dt = 0 +void ImageSequencer::updateSequencer(double time){ + if (Time::ref().timeJumped() && Time::ref().deltaTime() == 0){ + Time::ref().setDeltaTime(0.1); + } // Time is not properly updated when time jump with dt = 0 - if (_currentTime != time){ - _previousTime = _currentTime; - _currentTime = time; - } + if (_currentTime != time){ + _previousTime = _currentTime; + _currentTime = time; + } } -std::pair ImageSequencer2::getNextTarget(){ - auto compareTime = [](const std::pair &a, - const std::pair &b)->bool{ - return a.first < b.first; - }; - std::pair findEqualToThis; - findEqualToThis.first = _currentTime; - auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime); +std::pair ImageSequencer::getNextTarget(){ + auto compareTime = [](const std::pair &a, + const std::pair &b)->bool{ + return a.first < b.first; + }; + std::pair findEqualToThis; + findEqualToThis.first = _currentTime; + auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime); - if (it != _targetTimes.end() && it != _targetTimes.begin()) - return (*it); + if (it != _targetTimes.end() && it != _targetTimes.begin()) + return (*it); else return std::make_pair(0.0, ""); } -std::pair ImageSequencer2::getCurrentTarget(){ - auto compareTime = [](const std::pair &a, - const std::pair &b)->bool{ - return a.first < b.first; - }; - std::pair findEqualToThis; - findEqualToThis.first = _currentTime; - auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime); +std::pair ImageSequencer::getCurrentTarget(){ + auto compareTime = [](const std::pair &a, + const std::pair &b)->bool{ + return a.first < b.first; + }; + std::pair findEqualToThis; + findEqualToThis.first = _currentTime; + auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime); - if (it != _targetTimes.end() && it != _targetTimes.begin()){ - return *std::prev(it); - } + if (it != _targetTimes.end() && it != _targetTimes.begin()){ + return *std::prev(it); + } else return std::make_pair(0.0, "No Target"); } -std::pair> ImageSequencer2::getIncidentTargetList(int range){ - std::pair> incidentTargets; +std::pair> ImageSequencer::getIncidentTargetList(int range){ + std::pair> incidentTargets; - auto compareTime = [](const std::pair &a, - const std::pair &b)->bool{ - return a.first < b.first; - }; - // what to look for - std::pair findEqualToThis; - findEqualToThis.first = _currentTime; - auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime); - - if (it != _targetTimes.end() && it != _targetTimes.begin()){ - // move the iterator to the first element of the range - std::advance(it, -(range + 1)); + auto compareTime = [](const std::pair &a, + const std::pair &b)->bool{ + return a.first < b.first; + }; + // what to look for + std::pair findEqualToThis; + findEqualToThis.first = _currentTime; + auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime); + + if (it != _targetTimes.end() && it != _targetTimes.begin()){ + // move the iterator to the first element of the range + std::advance(it, -(range + 1)); - // now extract incident range - for (int i = 0; i < 2 * range + 1; i++){ - incidentTargets.first = it->first; - incidentTargets.second.push_back(it->second); - it++; - if (it == _targetTimes.end()) - break; - } - } + // now extract incident range + for (int i = 0; i < 2 * range + 1; i++){ + incidentTargets.first = it->first; + incidentTargets.second.push_back(it->second); + it++; + if (it == _targetTimes.end()) + break; + } + } - return incidentTargets; + return incidentTargets; } -double ImageSequencer2::getIntervalLength(){ - double upcoming = getNextCaptureTime(); - if (_nextCapture != upcoming){ - _nextCapture = upcoming; - _intervalLength = upcoming - _currentTime; - } - return _intervalLength; +double ImageSequencer::getIntervalLength(){ + double upcoming = getNextCaptureTime(); + if (_nextCapture != upcoming){ + _nextCapture = upcoming; + _intervalLength = upcoming - _currentTime; + } + return _intervalLength; } -double ImageSequencer2::getNextCaptureTime(){ - auto compareTime = [](const double &a, const double &b)->bool{ - return a < b; - }; - double nextCaptureTime = 0; - auto it = std::lower_bound(_captureProgression.begin(), _captureProgression.end(), _currentTime, compareTime); - if (it != _captureProgression.end()) - nextCaptureTime = *it; +double ImageSequencer::getNextCaptureTime(){ + auto compareTime = [](const double &a, const double &b)->bool{ + return a < b; + }; + double nextCaptureTime = 0; + auto it = std::lower_bound(_captureProgression.begin(), _captureProgression.end(), _currentTime, compareTime); + if (it != _captureProgression.end()) + nextCaptureTime = *it; - return nextCaptureTime; + return nextCaptureTime; } -const Image ImageSequencer2::getLatestImageForInstrument(const std::string _instrumentID){ - auto it = _latestImages.find(_instrumentID); - if (it != _latestImages.end()) - return _latestImages[_instrumentID]; - else { - Image dummyImage = { 0, 0, "", std::vector(), "", false }; - return dummyImage; - } +const Image ImageSequencer::getLatestImageForInstrument(const std::string _instrumentID){ + auto it = _latestImages.find(_instrumentID); + if (it != _latestImages.end()) + return _latestImages[_instrumentID]; + else { + Image dummyImage = { 0, 0, "", std::vector(), "", false }; + return dummyImage; + } } -std::map ImageSequencer2::getActiveInstruments(){ - // first set all instruments to off - for (auto i : _switchingMap) - _switchingMap[i.first] = false; - // go over the filetranslation map - for (const auto &key : _fileTranslation){ - // for each spice-instrument - for (const auto &instrumentID : key.second->getTranslation()){ - // check if the spice-instrument is active - if (instrumentActive(instrumentID)){ - // go over switching map - for (const auto &instrument : _switchingMap){ - // if instrument is present in switching map - if (instrumentID == instrument.first){ - // set as active - _switchingMap[instrumentID] = true; - } - } - } - } - } - // return entire map, seen in GUI. - return _switchingMap; +std::map ImageSequencer::getActiveInstruments(){ + // first set all instruments to off + for (auto i : _switchingMap) + _switchingMap[i.first] = false; + // go over the filetranslation map + for (const auto &key : _fileTranslation){ + // for each spice-instrument + for (const auto &instrumentID : key.second->getTranslation()){ + // check if the spice-instrument is active + if (instrumentActive(instrumentID)){ + // go over switching map + for (const auto &instrument : _switchingMap){ + // if instrument is present in switching map + if (instrumentID == instrument.first){ + // set as active + _switchingMap[instrumentID] = true; + } + } + } + } + } + // return entire map, seen in GUI. + return _switchingMap; } -bool ImageSequencer2::instrumentActive(std::string instrumentID){ - for (auto i : _instrumentTimes){ - //check if this instrument is in range - if (i.second.inRange(_currentTime)){ - //if so, then get the corresponding spiceID - std::vector spiceIDs = _fileTranslation[i.first]->getTranslation(); - //check which specific subinstrument is firing - for (auto s : spiceIDs){ - if (s == instrumentID){ - return true; - } - } - } - } - return false; +bool ImageSequencer::instrumentActive(std::string instrumentID){ + for (auto i : _instrumentTimes){ + //check if this instrument is in range + if (i.second.inRange(_currentTime)){ + //if so, then get the corresponding spiceID + std::vector spiceIDs = _fileTranslation[i.first]->getTranslation(); + //check which specific subinstrument is firing + for (auto s : spiceIDs){ + if (s == instrumentID){ + return true; + } + } + } + } + return false; } -float ImageSequencer2::instrumentActiveTime(const std::string& instrumentID) const { +float ImageSequencer::instrumentActiveTime(const std::string& instrumentID) const { for (auto i : _instrumentTimes){ //check if this instrument is in range if (i.second.inRange(_currentTime)){ @@ -227,154 +227,154 @@ float ImageSequencer2::instrumentActiveTime(const std::string& instrumentID) con return -1.f; } -bool ImageSequencer2::getImagePaths(std::vector& captures, - std::string projectee, - std::string instrumentRequest){ +bool ImageSequencer::getImagePaths(std::vector& captures, + std::string projectee, + std::string instrumentRequest){ - // check if this instance is either in range or - // a valid candidate to recieve data - if (!instrumentActive(instrumentRequest) && !Time::ref().timeJumped()) return false; + // check if this instance is either in range or + // a valid candidate to recieve data + if (!instrumentActive(instrumentRequest) && !Time::ref().timeJumped()) return false; - //if (!Time::ref().timeJumped() && projectee == getCurrentTarget().second) - if (_subsetMap[projectee]._range.inRange(_currentTime) || - _subsetMap[projectee]._range.inRange(_previousTime)){ - auto compareTime = [](const Image &a, - const Image &b)->bool{ - return a.startTime < b.startTime; - }; - // for readability we store the iterators - auto begin = _subsetMap[projectee]._subset.begin(); - auto end = _subsetMap[projectee]._subset.end(); - - // create temporary storage - std::vector captureTimes; - // what to look for - Image findPrevious, findCurrent; - findPrevious.startTime = _previousTime; - findCurrent.startTime = _currentTime; + //if (!Time::ref().timeJumped() && projectee == getCurrentTarget().second) + if (_subsetMap[projectee]._range.inRange(_currentTime) || + _subsetMap[projectee]._range.inRange(_previousTime)){ + auto compareTime = [](const Image &a, + const Image &b)->bool{ + return a.startTime < b.startTime; + }; + // for readability we store the iterators + auto begin = _subsetMap[projectee]._subset.begin(); + auto end = _subsetMap[projectee]._subset.end(); + + // create temporary storage + std::vector captureTimes; + // what to look for + Image findPrevious, findCurrent; + findPrevious.startTime = _previousTime; + findCurrent.startTime = _currentTime; - // find the two iterators that correspond to the latest time jump - auto curr = std::lower_bound(begin, end, findCurrent , compareTime); - auto prev = std::lower_bound(begin, end, findPrevious, compareTime); - - if (curr != begin && curr != end && prev != begin && prev != end && prev < curr){ + // find the two iterators that correspond to the latest time jump + auto curr = std::lower_bound(begin, end, findCurrent , compareTime); + auto prev = std::lower_bound(begin, end, findPrevious, compareTime); + + if (curr != begin && curr != end && prev != begin && prev != end && prev < curr){ if (curr->startTime >= prev->startTime){ - std::copy_if(prev, curr, back_inserter(captureTimes), - [instrumentRequest](const Image& i) { - return i.activeInstruments[0] == instrumentRequest; - }); + std::copy_if(prev, curr, back_inserter(captureTimes), + [instrumentRequest](const Image& i) { + return i.activeInstruments[0] == instrumentRequest; + }); - //std::reverse(captureTimes.begin(), captureTimes.end()); - captures = captureTimes; + //std::reverse(captureTimes.begin(), captureTimes.end()); + captures = captureTimes; if (!captures.empty()) - _latestImages[captures.back().activeInstruments.front()] = captures.back(); + _latestImages[captures.back().activeInstruments.front()] = captures.back(); - return true; + return true; } - } - } - return false; + } + } + return false; } -void ImageSequencer2::sortData(){ - auto targetComparer = [](const std::pair &a, - const std::pair &b)->bool{ - return a.first < b.first; - }; - auto imageComparer = [](const Image &a, const Image &b)->bool{ - return a.startTime < b.startTime; - }; +void ImageSequencer::sortData(){ + auto targetComparer = [](const std::pair &a, + const std::pair &b)->bool{ + return a.first < b.first; + }; + auto imageComparer = [](const Image &a, const Image &b)->bool{ + return a.startTime < b.startTime; + }; - std::sort(_targetTimes.begin(), _targetTimes.end(), targetComparer); - std::stable_sort(_captureProgression.begin(), _captureProgression.end()); + std::sort(_targetTimes.begin(), _targetTimes.end(), targetComparer); + std::stable_sort(_captureProgression.begin(), _captureProgression.end()); - for (auto sub : _subsetMap){ - std::sort(_subsetMap[sub.first]._subset.begin(), - _subsetMap[sub.first]._subset.end(), imageComparer); - } + for (auto sub : _subsetMap){ + std::sort(_subsetMap[sub.first]._subset.begin(), + _subsetMap[sub.first]._subset.end(), imageComparer); + } } -void ImageSequencer2::runSequenceParser(SequenceParser* parser){ - bool parserComplete = parser->create(); - if (parserComplete){ - // get new data - std::map translations = parser->getTranslation(); // in1 - std::map imageData = parser->getSubsetMap(); // in2 - std::vector> instrumentTimes = parser->getIstrumentTimes(); //in3 - std::vector> targetTimes = parser->getTargetTimes(); //in4 - std::vector captureProgression = parser->getCaptureProgression(); //in5 +void ImageSequencer::runSequenceParser(SequenceParser* parser){ + bool parserComplete = parser->create(); + if (parserComplete){ + // get new data + std::map translations = parser->getTranslation(); // in1 + std::map imageData = parser->getSubsetMap(); // in2 + std::vector> instrumentTimes = parser->getIstrumentTimes(); //in3 + std::vector> targetTimes = parser->getTargetTimes(); //in4 + std::vector captureProgression = parser->getCaptureProgression(); //in5 - // check for sanity - if (translations.empty() || imageData.empty() || instrumentTimes.empty() || targetTimes.empty() || captureProgression.empty()) - return; + // check for sanity + if (translations.empty() || imageData.empty() || instrumentTimes.empty() || targetTimes.empty() || captureProgression.empty()) + return; - // append data - _fileTranslation.insert(translations.begin(), translations.end()); - for (auto it : imageData){ - if (_subsetMap.find(it.first) == _subsetMap.end()) { - // if key not exist yet - add sequence data for key (target) - _subsetMap.insert(it); - } else { - std::string key = it.first; - std::vector &source = it.second._subset; // prediction - std::vector &destination = _subsetMap[key]._subset; // imagery + // append data + _fileTranslation.insert(translations.begin(), translations.end()); + for (auto it : imageData){ + if (_subsetMap.find(it.first) == _subsetMap.end()) { + // if key not exist yet - add sequence data for key (target) + _subsetMap.insert(it); + } else { + std::string key = it.first; + std::vector &source = it.second._subset; // prediction + std::vector &destination = _subsetMap[key]._subset; // imagery - // simple search function - double min = 10; - auto findMin = [&](std::vector &vector)->double{ - for (int i = 1; i < vector.size(); i++){ - double e = abs(vector[i].startTime - vector[i - 1].startTime); - if (e < min){ - min = e; - } - } - return min; - }; - - // find the smallest separation of images in time - double epsilon; - epsilon = findMin(source); - epsilon = findMin(destination); - // set epsilon as 1% smaller than min - epsilon -= min*0.01; - - // IFF images have same time as mission planned capture, erase that event from - // 'predicted event file' (mission-playbook) - std::vector tmp; - for (int i = 0; i < source.size(); i++){ - for (int j = 0; j < destination.size(); j++){ - double diff = abs(source[i].startTime - destination[j].startTime); - if (diff < epsilon){ - source.erase(source.begin() + i); - } - } - } - // pad image data with predictions (ie - where no actual images, add placeholder) - _subsetMap[key]._subset.insert(_subsetMap[key]._subset.end(), source.begin(), source.end()); - } - } + // simple search function + double min = 10; + auto findMin = [&](std::vector &vector)->double{ + for (int i = 1; i < vector.size(); i++){ + double e = abs(vector[i].startTime - vector[i - 1].startTime); + if (e < min){ + min = e; + } + } + return min; + }; + + // find the smallest separation of images in time + double epsilon; + epsilon = findMin(source); + epsilon = findMin(destination); + // set epsilon as 1% smaller than min + epsilon -= min*0.01; + + // IFF images have same time as mission planned capture, erase that event from + // 'predicted event file' (mission-playbook) + std::vector tmp; + for (int i = 0; i < source.size(); i++){ + for (int j = 0; j < destination.size(); j++){ + double diff = abs(source[i].startTime - destination[j].startTime); + if (diff < epsilon){ + source.erase(source.begin() + i); + } + } + } + // pad image data with predictions (ie - where no actual images, add placeholder) + _subsetMap[key]._subset.insert(_subsetMap[key]._subset.end(), source.begin(), source.end()); + } + } - _instrumentTimes.insert(_instrumentTimes.end(), instrumentTimes.begin(), instrumentTimes.end()); - _targetTimes.insert(_targetTimes.end(), targetTimes.begin(), targetTimes.end()); - _captureProgression.insert(_captureProgression.end(), captureProgression.begin(), captureProgression.end()); + _instrumentTimes.insert(_instrumentTimes.end(), instrumentTimes.begin(), instrumentTimes.end()); + _targetTimes.insert(_targetTimes.end(), targetTimes.begin(), targetTimes.end()); + _captureProgression.insert(_captureProgression.end(), captureProgression.begin(), captureProgression.end()); - // sorting of data _not_ optional - sortData(); + // sorting of data _not_ optional + sortData(); - // extract payload from _fileTranslation - for (auto t : _fileTranslation){ - if (t.second->getDecoderType() == "CAMERA" || - t.second->getDecoderType() == "SCANNER"){ - std::vector spiceIDs = t.second->getTranslation(); - for (auto id : spiceIDs){ - _switchingMap[id] = false; - } - } - } - _hasData = true; - } - else - LERROR("One of more sequence loads failed; please check mod files"); + // extract payload from _fileTranslation + for (auto t : _fileTranslation){ + if (t.second->getDecoderType() == "CAMERA" || + t.second->getDecoderType() == "SCANNER"){ + std::vector spiceIDs = t.second->getTranslation(); + for (auto id : spiceIDs){ + _switchingMap[id] = false; + } + } + } + _hasData = true; + } + else + LERROR("One or more sequence loads failed; please check mod files"); } } // namespace openspace diff --git a/modules/newhorizons/util/imagesequencer.h b/modules/newhorizons/util/imagesequencer.h index 8bc8c9d252..d34e1ebd79 100644 --- a/modules/newhorizons/util/imagesequencer.h +++ b/modules/newhorizons/util/imagesequencer.h @@ -22,8 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __ImageSequencer2_H__ -#define __ImageSequencer2_H__ +#ifndef __IMAGESEQUENCER_H__ +#define __IMAGESEQUENCER_H__ // open space includes #include @@ -36,170 +36,170 @@ #include namespace openspace { - /** - * The ImageSequencer singleton main function is to manage the timekeeping and - * distribution of large image data-sets across all openspace renderable instances, - * both for past and future unmanned-spacecraft missions. To load the instance with - * data the client must provide a parser inherited from the abstract base class - * SequenceParser. Hence, there is no restriction imposed on data input, whether its - * data in the form of existing images or in the form of a planned observation schedule. - * Notably, in order for the sequencer to function the client must provide or write a - * parser that fills the ImageSequencers private members. - * \see SequenceParser - * \see ImageSequencer2::runSequenceParser(SequenceParser* parser) - * std::map - */ -class ImageSequencer2 { + /** + * The ImageSequencer singleton main function is to manage the timekeeping and + * distribution of large image data-sets across all openspace renderable instances, + * both for past and future unmanned-spacecraft missions. To load the instance with + * data the client must provide a parser inherited from the abstract base class + * SequenceParser. Hence, there is no restriction imposed on data input, whether its + * data in the form of existing images or in the form of a planned observation schedule. + * Notably, in order for the sequencer to function the client must provide or write a + * parser that fills the ImageSequencers private members. + * \see SequenceParser + * \see ImageSequencer::runSequenceParser(SequenceParser* parser) + * std::map + */ +class ImageSequencer { public: - ImageSequencer2(); - /** - * Singelton instantiation - */ - static ImageSequencer2* _instance; - /** - * Returns the reference to the singleton ImageSequencer object that must have been - * initialized by a call to the initialize method earlier. - * \return The ImageSequencer singleton - */ - static ImageSequencer2& ref(); - /** - * Initializer that initializes the static member. - */ - static void initialize(); - /** - * Deinitializes that deinitializes the static member. - */ - static void deinitialize(); - /** - * Returns true if sequencer has been loaded with data. - */ - bool isReady(); + ImageSequencer(); + /** + * Singelton instantiation + */ + static ImageSequencer* _instance; + /** + * Returns the reference to the singleton ImageSequencer object that must have been + * initialized by a call to the initialize method earlier. + * \return The ImageSequencer singleton + */ + static ImageSequencer& ref(); + /** + * Initializer that initializes the static member. + */ + static void initialize(); + /** + * Deinitializes that deinitializes the static member. + */ + static void deinitialize(); + /** + * Returns true if sequencer has been loaded with data. + */ + bool isReady(); - /** - * Updates sequencer with current time. This is used internally for keeping - * track of both current simulation time and the time of the previously rendered frame. - */ - void updateSequencer(double time); - /** - * Runs parser and recieves the datastructures filled by it. - * \see SequenceParser - */ - void runSequenceParser(SequenceParser* parser); + /** + * Updates sequencer with current time. This is used internally for keeping + * track of both current simulation time and the time of the previously rendered frame. + */ + void updateSequencer(double time); + /** + * Runs parser and recieves the datastructures filled by it. + * \see SequenceParser + */ + void runSequenceParser(SequenceParser* parser); - /** - * Retrieves the next upcoming target in time. - */ - std::pair getNextTarget(); + /** + * Retrieves the next upcoming target in time. + */ + std::pair getNextTarget(); - /** - * Retrieves the most current target in time. - */ - std::pair getCurrentTarget(); + /** + * Retrieves the most current target in time. + */ + std::pair getCurrentTarget(); - /** - * Retrieves current target and (in the list) adjacent targets, the number to retrieve is user set - */ - std::pair> getIncidentTargetList(int range = 2); + /** + * Retrieves current target and (in the list) adjacent targets, the number to retrieve is user set + */ + std::pair> getIncidentTargetList(int range = 2); - /** - * Retrieves the next upcoming time of image capture. - */ - double getNextCaptureTime(); + /** + * Retrieves the next upcoming time of image capture. + */ + double getNextCaptureTime(); - /** - * Retrieves the time interval length between the current time and an upcoming capture. - */ - double getIntervalLength(); + /** + * Retrieves the time interval length between the current time and an upcoming capture. + */ + double getIntervalLength(); - /* - * Returns a map with key instrument names whose value indicate whether - * an instrument is active or not. - */ - std::map getActiveInstruments(); + /* + * Returns a map with key instrument names whose value indicate whether + * an instrument is active or not. + */ + std::map getActiveInstruments(); - /* - * Retrieves the relevant data from a specific subset based on the what instance - * makes the request. If an instance is not registered in the class then the singleton - * returns false and no projections will occur. - */ - bool getImagePaths(std::vector& captures, - std::string projectee, - std::string instrumentRequest); + /* + * Retrieves the relevant data from a specific subset based on the what instance + * makes the request. If an instance is not registered in the class then the singleton + * returns false and no projections will occur. + */ + bool getImagePaths(std::vector& captures, + std::string projectee, + std::string instrumentRequest); - /* - * returns true if instrumentID is within a capture range. - */ - bool instrumentActive(std::string instrumentID); + /* + * returns true if instrumentID is within a capture range. + */ + bool instrumentActive(std::string instrumentID); float instrumentActiveTime(const std::string& instrumentID) const; - /* - * returns latest captured image - */ - const Image getLatestImageForInstrument(const std::string _instrumentID); + /* + * returns latest captured image + */ + const Image getLatestImageForInstrument(const std::string _instrumentID); private: - void sortData(); - - /* - * _fileTranslation handles any types of ambiguities between the data and - * spice/openspace -calls. This map is composed of a key that is a string in - * the data to be translated and a Decoder that holds the corresponding - * translation provided through a modfile. - * \see Decoder - * \see (projection mod files) - */ - std::map _fileTranslation; + void sortData(); + + /* + * _fileTranslation handles any types of ambiguities between the data and + * spice/openspace -calls. This map is composed of a key that is a string in + * the data to be translated and a Decoder that holds the corresponding + * translation provided through a modfile. + * \see Decoder + * \see (projection mod files) + */ + std::map _fileTranslation; - /* - * This is the main container of image data. The key is the target name, - * the value is a subset of images. - * \see SequenceParser - */ - std::map _subsetMap; + /* + * This is the main container of image data. The key is the target name, + * the value is a subset of images. + * \see SequenceParser + */ + std::map _subsetMap; - /* - * In order for the simulation to know when to turn on/off any instrument within - * all instruments in the spacecraft payload, the key is the data-file given - * instrument name. - */ - std::map _switchingMap; + /* + * In order for the simulation to know when to turn on/off any instrument within + * all instruments in the spacecraft payload, the key is the data-file given + * instrument name. + */ + std::map _switchingMap; - /* - * This datastructure holds the specific times when the spacecraft switches from - * observing one inertial body to the next. This happens a lot in such missions - * and the coupling of target with specific time is usually therefore not 1:1. - */ - std::vector> _targetTimes; + /* + * This datastructure holds the specific times when the spacecraft switches from + * observing one inertial body to the next. This happens a lot in such missions + * and the coupling of target with specific time is usually therefore not 1:1. + */ + std::vector> _targetTimes; - /* - * Holds the time ranges of each instruments on and off periods. An instrument - * rendering class may ask the ImageSequencer whether or not it - */ - std::vector> _instrumentTimes; + /* + * Holds the time ranges of each instruments on and off periods. An instrument + * rendering class may ask the ImageSequencer whether or not it + */ + std::vector> _instrumentTimes; - /* - * Each consecutive images capture time, for easier traversal. - */ - std::vector _captureProgression; + /* + * Each consecutive images capture time, for easier traversal. + */ + std::vector _captureProgression; - // current simulation time - double _currentTime; - // simulation time of previous frame - double _previousTime; - // time between current simulation time and an upcoming capture - double _intervalLength; - // next consecutive capture in time - double _nextCapture; - // default capture image - std::string _defaultCaptureImage; + // current simulation time + double _currentTime; + // simulation time of previous frame + double _previousTime; + // time between current simulation time and an upcoming capture + double _intervalLength; + // next consecutive capture in time + double _nextCapture; + // default capture image + std::string _defaultCaptureImage; - std::map _latestImages; - // if no data, no run - bool _hasData; + std::map _latestImages; + // if no data, no run + bool _hasData; }; } // namespace openspace -#endif // __ImageSequencer2_H__ +#endif // __IMAGESEQUENCER_H__ diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index f26fc24f90..c14dbe8565 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -86,7 +86,7 @@ #include "renderengine_lua.inl" namespace { - const std::string _loggerCat = "RenderEngine"; + const std::string _loggerCat = "RenderEngine"; const std::string KeyRenderingMethod = "RenderingMethod"; std::chrono::seconds ScreenLogTimeToLive(15); @@ -97,26 +97,26 @@ namespace { namespace openspace { const std::string RenderEngine::PerformanceMeasurementSharedData = - "OpenSpacePerformanceMeasurementSharedData"; + "OpenSpacePerformanceMeasurementSharedData"; const std::string RenderEngine::KeyFontMono = "Mono"; const std::string RenderEngine::KeyFontLight = "Light"; RenderEngine::RenderEngine() - : _mainCamera(nullptr) - , _sceneGraph(nullptr) - , _renderer(nullptr) + : _mainCamera(nullptr) + , _sceneGraph(nullptr) + , _renderer(nullptr) , _rendererImplementation(RendererImplementation::Invalid) - , _log(nullptr) - , _showInfo(true) - , _showLog(true) - , _takeScreenshot(false) - , _doPerformanceMeasurements(false) - , _performanceMemory(nullptr) - , _globalBlackOutFactor(1.f) - , _fadeDuration(2.f) - , _currentFadeTime(0.f) - , _fadeDirection(0) + , _log(nullptr) + , _showInfo(true) + , _showLog(true) + , _takeScreenshot(false) + , _doPerformanceMeasurements(false) + , _performanceMemory(nullptr) + , _globalBlackOutFactor(1.f) + , _fadeDuration(2.f) + , _currentFadeTime(0.f) + , _fadeDirection(0) // , _sgctRenderStatisticsVisible(false) { _onScreenInformation = { @@ -127,20 +127,20 @@ RenderEngine::RenderEngine() } RenderEngine::~RenderEngine() { - delete _sceneGraph; - _sceneGraph = nullptr; + delete _sceneGraph; + _sceneGraph = nullptr; - delete _mainCamera; - delete _performanceMemory; - delete _raycasterManager; + delete _mainCamera; + delete _performanceMemory; + delete _raycasterManager; - if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData)) - ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); + if (ghoul::SharedMemory::exists(PerformanceMeasurementSharedData)) + ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); } bool RenderEngine::deinitialize() { - _sceneGraph->clearSceneGraph(); - return true; + _sceneGraph->clearSceneGraph(); + return true; } void RenderEngine::setRendererFromString(const std::string& renderingMethod) { @@ -149,7 +149,7 @@ void RenderEngine::setRendererFromString(const std::string& renderingMethod) { std::unique_ptr newRenderer = nullptr; switch (_rendererImplementation) { case RendererImplementation::Framebuffer: - newRenderer = std::make_unique(); + newRenderer = std::make_unique(); break; case RendererImplementation::ABuffer: newRenderer = std::make_unique(); @@ -169,7 +169,7 @@ bool RenderEngine::initialize() { if (OsEng.configurationManager().hasKeyAndValue(KeyRenderingMethod)) { renderingMethod = OsEng.configurationManager().value(KeyRenderingMethod); - } else { + } else { using Version = ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version; // The default rendering method has a requirement of OpenGL 4.3, so if we are @@ -182,13 +182,13 @@ bool RenderEngine::initialize() { _raycasterManager = new RaycasterManager(); - LINFO("Seting renderer from string: " << renderingMethod); - setRendererFromString(renderingMethod); + LINFO("Seting renderer from string: " << renderingMethod); + setRendererFromString(renderingMethod); - // init camera and set temporary position and scaling - _mainCamera = new Camera(); - _mainCamera->setScaling(glm::vec2(1.0, -8.0)); - _mainCamera->setPosition(psc(0.f, 0.f, 1.499823f, 11.f)); + // init camera and set temporary position and scaling + _mainCamera = new Camera(); + _mainCamera->setScaling(glm::vec2(1.0, -8.0)); + _mainCamera->setPosition(psc(0.f, 0.f, 1.499823f, 11.f)); OsEng.interactionHandler().setCamera(_mainCamera); if (_renderer) { @@ -209,15 +209,15 @@ bool RenderEngine::initialize() { ghoul::io::TextureReader::ref().addReader(std::make_shared()); - return true; + return true; } bool RenderEngine::initializeGL() { - // TODO: Fix the power scaled coordinates in such a way that these - // values can be set to more realistic values + // TODO: Fix the power scaled coordinates in such a way that these + // values can be set to more realistic values - // set the close clip plane and the far clip plane to extreme values while in - // development + // set the close clip plane and the far clip plane to extreme values while in + // development OsEng.windowWrapper().setNearFarClippingPlane(0.001f, 1000.f); @@ -241,28 +241,28 @@ bool RenderEngine::initializeGL() { // sgct::Engine::instance()->setNearAndFarClippingPlanes(0.001f, 1000.0f); - // sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f, 30.0f); + // sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f, 30.0f); - // calculating the maximum field of view for the camera, used to - // determine visibility of objects in the scene graph + // calculating the maximum field of view for the camera, used to + // determine visibility of objects in the scene graph /* if (sgct::Engine::instance()->getCurrentRenderTarget() == sgct::Engine::NonLinearBuffer) { - // fisheye mode, looking upwards to the "dome" - glm::vec4 upDirection(0, 1, 0, 0); + // fisheye mode, looking upwards to the "dome" + glm::vec4 upDirection(0, 1, 0, 0); - // get the tilt and rotate the view - const float tilt = wPtr->getFisheyeTilt(); - glm::mat4 tiltMatrix - = glm::rotate(glm::mat4(1.0f), tilt, glm::vec3(1.0f, 0.0f, 0.0f)); - const glm::vec4 viewdir = tiltMatrix * upDirection; + // get the tilt and rotate the view + const float tilt = wPtr->getFisheyeTilt(); + glm::mat4 tiltMatrix + = glm::rotate(glm::mat4(1.0f), tilt, glm::vec3(1.0f, 0.0f, 0.0f)); + const glm::vec4 viewdir = tiltMatrix * upDirection; - // set the tilted view and the FOV - _mainCamera->setCameraDirection(glm::vec3(viewdir[0], viewdir[1], viewdir[2])); - _mainCamera->setMaxFov(wPtr->getFisheyeFOV()); - _mainCamera->setLookUpVector(glm::vec3(0.0, 1.0, 0.0)); - } - else {*/ - // get corner positions, calculating the forth to easily calculate center - + // set the tilted view and the FOV + _mainCamera->setCameraDirection(glm::vec3(viewdir[0], viewdir[1], viewdir[2])); + _mainCamera->setMaxFov(wPtr->getFisheyeFOV()); + _mainCamera->setLookUpVector(glm::vec3(0.0, 1.0, 0.0)); + } + else {*/ + // get corner positions, calculating the forth to easily calculate center + // glm::vec3 corners[4]; // sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getWindowPtr(0); // sgct_core::BaseViewport* vp = wPtr->getViewport(0); @@ -274,36 +274,36 @@ bool RenderEngine::initializeGL() { // corners[3] = glm::vec3(corners[2][0], corners[0][1], corners[2][2]); // // const glm::vec3 center = (corners[0] + corners[1] + corners[2] + corners[3]); - //// - //const glm::vec3 eyePosition = sgct_core::ClusterManager::instance()->getDefaultUserPtr()->getPos(); - ////// get viewdirection, stores the direction in the camera, used for culling - //const glm::vec3 viewdir = glm::normalize(eyePosition - center); + //// + //const glm::vec3 eyePosition = sgct_core::ClusterManager::instance()->getDefaultUserPtr()->getPos(); + ////// get viewdirection, stores the direction in the camera, used for culling + //const glm::vec3 viewdir = glm::normalize(eyePosition - center); //const glm::vec3 upVector = corners[0] - corners[1]; - //_mainCamera->setCameraDirection(glm::normalize(-viewdir)); + //_mainCamera->setCameraDirection(glm::normalize(-viewdir)); _mainCamera->setCameraDirection(glm::vec3(0.f, 0.f, -1.f)); - //_mainCamera->setLookUpVector(glm::normalize(upVector)); + //_mainCamera->setLookUpVector(glm::normalize(upVector)); _mainCamera->setLookUpVector(glm::vec3(0.f, 1.f, 0.f)); - // set the initial fov to be 0.0 which means everything will be culled - //float maxFov = 0.0f; + // set the initial fov to be 0.0 which means everything will be culled + //float maxFov = 0.0f; float maxFov = std::numeric_limits::max(); - //// for each corner - //for (int i = 0; i < 4; ++i) { - // // calculate radians to corner - // glm::vec3 dir = glm::normalize(eyePosition - corners[i]); - // float radsbetween = acos(glm::dot(viewdir, dir)) - // / (glm::length(viewdir) * glm::length(dir)); + //// for each corner + //for (int i = 0; i < 4; ++i) { + // // calculate radians to corner + // glm::vec3 dir = glm::normalize(eyePosition - corners[i]); + // float radsbetween = acos(glm::dot(viewdir, dir)) + // / (glm::length(viewdir) * glm::length(dir)); - // // the angle to a corner is larger than the current maxima - // if (radsbetween > maxFov) { - // maxFov = radsbetween; - // } - //} - _mainCamera->setMaxFov(maxFov); + // // the angle to a corner is larger than the current maxima + // if (radsbetween > maxFov) { + // maxFov = radsbetween; + // } + //} + _mainCamera->setMaxFov(maxFov); //} LINFO("Initializing Log"); @@ -312,128 +312,128 @@ bool RenderEngine::initializeGL() { ghoul::logging::LogManager::ref().addLog(std::move(log)); LINFO("Finished initializing GL"); - return true; + return true; } void RenderEngine::preSynchronization() { - if (_mainCamera) - _mainCamera->preSynchronization(); + if (_mainCamera) + _mainCamera->preSynchronization(); } void RenderEngine::postSynchronizationPreDraw() { - //temporary fade funtionality - if (_fadeDirection != 0) { - if (_currentFadeTime > _fadeDuration){ - _fadeDirection = 0; - _globalBlackOutFactor = fminf(1.f, fmaxf(0.f, _globalBlackOutFactor)); - } - else { - if (_fadeDirection < 0) - _globalBlackOutFactor = glm::smoothstep(1.f, 0.f, _currentFadeTime / _fadeDuration); - else - _globalBlackOutFactor = glm::smoothstep(0.f, 1.f, _currentFadeTime / _fadeDuration); + //temporary fade funtionality + if (_fadeDirection != 0) { + if (_currentFadeTime > _fadeDuration){ + _fadeDirection = 0; + _globalBlackOutFactor = fminf(1.f, fmaxf(0.f, _globalBlackOutFactor)); + } + else { + if (_fadeDirection < 0) + _globalBlackOutFactor = glm::smoothstep(1.f, 0.f, _currentFadeTime / _fadeDuration); + else + _globalBlackOutFactor = glm::smoothstep(0.f, 1.f, _currentFadeTime / _fadeDuration); _currentFadeTime += static_cast(OsEng.windowWrapper().averageDeltaTime()); - } - } + } + } - if (_mainCamera) - _mainCamera->postSynchronizationPreDraw(); + if (_mainCamera) + _mainCamera->postSynchronizationPreDraw(); - bool windowResized = OsEng.windowWrapper().windowHasResized(); + bool windowResized = OsEng.windowWrapper().windowHasResized(); - if (windowResized) { - glm::ivec2 res = OsEng.windowWrapper().currentDrawBufferResolution(); - _renderer->setResolution(res); - ghoul::fontrendering::FontRenderer::defaultRenderer().setWindowSize(glm::vec2(res)); - } + if (windowResized) { + glm::ivec2 res = OsEng.windowWrapper().currentDrawBufferResolution(); + _renderer->setResolution(res); + ghoul::fontrendering::FontRenderer::defaultRenderer().setWindowSize(glm::vec2(res)); + } - // converts the quaternion used to rotation matrices + // converts the quaternion used to rotation matrices if (_mainCamera) _mainCamera->compileViewRotationMatrix(); - // update and evaluate the scene starting from the root node - _sceneGraph->update({ - Time::ref().currentTime(), + // update and evaluate the scene starting from the root node + _sceneGraph->update({ + Time::ref().currentTime(), Time::ref().timeJumped(), - Time::ref().deltaTime(), - _doPerformanceMeasurements - }); - _sceneGraph->evaluate(_mainCamera); + Time::ref().deltaTime(), + _doPerformanceMeasurements + }); + _sceneGraph->evaluate(_mainCamera); - _renderer->update(); + _renderer->update(); - for (auto program : _programs) { - if (program->isDirty()) { - program->rebuildFromFile(); - } - } + for (auto program : _programs) { + if (program->isDirty()) { + program->rebuildFromFile(); + } + } - //Allow focus node to update camera (enables camera-following) - //FIX LATER: THIS CAUSES MASTER NODE TO BE ONE FRAME AHEAD OF SLAVES - //if (const SceneGraphNode* node = OsEng.ref().interactionHandler().focusNode()){ - //node->updateCamera(_mainCamera); - //} + //Allow focus node to update camera (enables camera-following) + //FIX LATER: THIS CAUSES MASTER NODE TO BE ONE FRAME AHEAD OF SLAVES + //if (const SceneGraphNode* node = OsEng.ref().interactionHandler().focusNode()){ + //node->updateCamera(_mainCamera); + //} } void RenderEngine::render(const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix) { - _mainCamera->setViewMatrix(viewMatrix); - _mainCamera->setProjectionMatrix(projectionMatrix); + _mainCamera->setViewMatrix(viewMatrix); + _mainCamera->setProjectionMatrix(projectionMatrix); - if (!(OsEng.isMaster() && _disableMasterRendering)) { + if (!(OsEng.isMaster() && _disableMasterRendering)) { _renderer->render(_globalBlackOutFactor, _doPerformanceMeasurements); - } + } - // Print some useful information on the master viewport - if (OsEng.isMaster() && OsEng.windowWrapper().isSimpleRendering()) { - if (_showInfo) { - renderInformation(); - } - if (_showLog) { - renderScreenLog(); - } - } + // Print some useful information on the master viewport + if (OsEng.isMaster() && OsEng.windowWrapper().isSimpleRendering()) { + if (_showInfo) { + renderInformation(); + } + if (_showLog) { + renderScreenLog(); + } + } } void RenderEngine::postDraw() { if (Time::ref().timeJumped()) Time::ref().setTimeJumped(false); - if (_takeScreenshot) { + if (_takeScreenshot) { OsEng.windowWrapper().takeScreenshot(); - _takeScreenshot = false; - } + _takeScreenshot = false; + } - if (_doPerformanceMeasurements) - storePerformanceMeasurements(); + if (_doPerformanceMeasurements) + storePerformanceMeasurements(); } void RenderEngine::takeScreenshot() { - _takeScreenshot = true; + _takeScreenshot = true; } void RenderEngine::toggleInfoText(bool b) { - _showInfo = b; + _showInfo = b; } Scene* RenderEngine::scene() { - // TODO custom assert (ticket #5) - assert(_sceneGraph); - return _sceneGraph; + // TODO custom assert (ticket #5) + assert(_sceneGraph); + return _sceneGraph; } RaycasterManager& RenderEngine::raycasterManager() { - return *_raycasterManager; + return *_raycasterManager; } void RenderEngine::setSceneGraph(Scene* sceneGraph) { - _sceneGraph = sceneGraph; + _sceneGraph = sceneGraph; } void RenderEngine::serialize(SyncBuffer* syncBuffer) { - if (_mainCamera){ - _mainCamera->serialize(syncBuffer); - } + if (_mainCamera){ + _mainCamera->serialize(syncBuffer); + } syncBuffer->encode(_onScreenInformation._node); @@ -443,9 +443,9 @@ void RenderEngine::serialize(SyncBuffer* syncBuffer) { } void RenderEngine::deserialize(SyncBuffer* syncBuffer) { - if (_mainCamera){ - _mainCamera->deserialize(syncBuffer); - } + if (_mainCamera){ + _mainCamera->deserialize(syncBuffer); + } syncBuffer->decode(_onScreenInformation._node); syncBuffer->decode(_onScreenInformation._position.x); syncBuffer->decode(_onScreenInformation._position.y); @@ -454,11 +454,11 @@ void RenderEngine::deserialize(SyncBuffer* syncBuffer) { } Camera* RenderEngine::camera() const { - return _mainCamera; + return _mainCamera; } Renderer* RenderEngine::renderer() const { - return _renderer.get(); + return _renderer.get(); } RenderEngine::RendererImplementation RenderEngine::rendererImplementation() const { @@ -466,91 +466,91 @@ RenderEngine::RendererImplementation RenderEngine::rendererImplementation() cons } float RenderEngine::globalBlackOutFactor() { - return _globalBlackOutFactor; + return _globalBlackOutFactor; } void RenderEngine::setGlobalBlackOutFactor(float opacity) { - _globalBlackOutFactor = opacity; + _globalBlackOutFactor = opacity; } void RenderEngine::startFading(int direction, float fadeDuration) { - _fadeDirection = direction; - _fadeDuration = fadeDuration; - _currentFadeTime = 0.f; + _fadeDirection = direction; + _fadeDuration = fadeDuration; + _currentFadeTime = 0.f; } /** * Build a program object for rendering with the used renderer */ std::unique_ptr RenderEngine::buildRenderProgram( - std::string name, - std::string vsPath, - std::string fsPath, - const ghoul::Dictionary& data) { + std::string name, + std::string vsPath, + std::string fsPath, + const ghoul::Dictionary& data) { - ghoul::Dictionary dict = data; + ghoul::Dictionary dict = data; // set path to the current renderer's main fragment shader - dict.setValue("rendererData", _rendererData); + dict.setValue("rendererData", _rendererData); // parameterize the main fragment shader program with specific contents. // fsPath should point to a shader file defining a Fragment getFragment() function // instead of a void main() setting glFragColor, glFragDepth, etc. dict.setValue("fragmentPath", fsPath); std::unique_ptr program = ghoul::opengl::ProgramObject::Build( - name, - vsPath, - RenderFsPath, - dict); + name, + vsPath, + RenderFsPath, + dict); if (program) { _programs.push_back(program.get()); } - return program; + return program; } /** * Build a program object for rendering with the used renderer */ std::unique_ptr RenderEngine::buildRenderProgram( - std::string name, - std::string vsPath, - std::string fsPath, - std::string csPath, - const ghoul::Dictionary& data) { + std::string name, + std::string vsPath, + std::string fsPath, + std::string csPath, + const ghoul::Dictionary& data) { - ghoul::Dictionary dict = data; - dict.setValue("rendererData", _rendererData); + ghoul::Dictionary dict = data; + dict.setValue("rendererData", _rendererData); // parameterize the main fragment shader program with specific contents. // fsPath should point to a shader file defining a Fragment getFragment() function // instead of a void main() setting glFragColor, glFragDepth, etc. dict.setValue("fragmentPath", fsPath); - std::unique_ptr program = ghoul::opengl::ProgramObject::Build( - name, - vsPath, - RenderFsPath, - csPath, - dict); + std::unique_ptr program = ghoul::opengl::ProgramObject::Build( + name, + vsPath, + RenderFsPath, + csPath, + dict); if (program) { _programs.push_back(program.get()); } - return program; + return program; } void RenderEngine::removeRenderProgram(const std::unique_ptr& program) { - ghoul::opengl::ProgramObject* ptr = program.get(); + ghoul::opengl::ProgramObject* ptr = program.get(); auto it = std::find( - _programs.begin(), - _programs.end(), - ptr - ); + _programs.begin(), + _programs.end(), + ptr + ); - if (it != _programs.end()) { - _programs.erase(it); - } + if (it != _programs.end()) { + _programs.erase(it); + } } /** @@ -559,120 +559,120 @@ void RenderEngine::removeRenderProgram(const std::unique_ptrdictionary(); - dict.setValue("rendererData", _rendererData); - program->setDictionary(dict); - } + _rendererData = data; + for (auto program : _programs) { + ghoul::Dictionary dict = program->dictionary(); + dict.setValue("rendererData", _rendererData); + program->setDictionary(dict); + } } /** * Set renderer */ void RenderEngine::setRenderer(std::unique_ptr renderer) { - glm::ivec2 res = OsEng.windowWrapper().currentDrawBufferResolution(); + glm::ivec2 res = OsEng.windowWrapper().currentDrawBufferResolution(); - if (_renderer) { - _renderer->deinitialize(); - } + if (_renderer) { + _renderer->deinitialize(); + } - _renderer = std::move(renderer); + _renderer = std::move(renderer); _renderer->setResolution(res); - _renderer->initialize(); + _renderer->initialize(); _renderer->setCamera(_mainCamera); _renderer->setScene(_sceneGraph); } scripting::ScriptEngine::LuaLibrary RenderEngine::luaLibrary() { - return { - "", - { - { - "takeScreenshot", - &luascriptfunctions::takeScreenshot, - "", - "Renders the current image to a file on disk" - }, - { - "setRenderer", - &luascriptfunctions::setRenderer, - "string", - "Sets the renderer (ABuffer or FrameBuffer)" - }, - { - "showRenderInformation", - &luascriptfunctions::showRenderInformation, - "bool", - "Toggles the showing of render information on-screen text" - }, - { - "setPerformanceMeasurement", - &luascriptfunctions::setPerformanceMeasurement, - "bool", - "Sets the performance measurements" - }, - { - "fadeIn", - &luascriptfunctions::fadeIn, - "number", - "", + return { + "", + { + { + "takeScreenshot", + &luascriptfunctions::takeScreenshot, + "", + "Renders the current image to a file on disk" + }, + { + "setRenderer", + &luascriptfunctions::setRenderer, + "string", + "Sets the renderer (ABuffer or FrameBuffer)" + }, + { + "showRenderInformation", + &luascriptfunctions::showRenderInformation, + "bool", + "Toggles the showing of render information on-screen text" + }, + { + "setPerformanceMeasurement", + &luascriptfunctions::setPerformanceMeasurement, + "bool", + "Sets the performance measurements" + }, + { + "fadeIn", + &luascriptfunctions::fadeIn, + "number", + "", true - }, - //also temporary @JK - { - "fadeOut", - &luascriptfunctions::fadeOut, - "number", - "", + }, + //also temporary @JK + { + "fadeOut", + &luascriptfunctions::fadeOut, + "number", + "", true - }, - }, - }; + }, + }, + }; } void RenderEngine::setPerformanceMeasurements(bool performanceMeasurements) { - _doPerformanceMeasurements = performanceMeasurements; + _doPerformanceMeasurements = performanceMeasurements; } bool RenderEngine::doesPerformanceMeasurements() const { - return _doPerformanceMeasurements; + return _doPerformanceMeasurements; } void RenderEngine::storePerformanceMeasurements() { - const int8_t Version = 0; - const int nValues = 250; - const int lengthName = 256; - const int maxValues = 256; + const int8_t Version = 0; + const int nValues = 250; + const int lengthName = 256; + const int maxValues = 256; - struct PerformanceLayout { - int8_t version; - int32_t nValuesPerEntry; - int32_t nEntries; - int32_t maxNameLength; - int32_t maxEntries; + struct PerformanceLayout { + int8_t version; + int32_t nValuesPerEntry; + int32_t nEntries; + int32_t maxNameLength; + int32_t maxEntries; - struct PerformanceLayoutEntry { - char name[lengthName]; - float renderTime[nValues]; - float updateRenderable[nValues]; - float updateEphemeris[nValues]; + struct PerformanceLayoutEntry { + char name[lengthName]; + float renderTime[nValues]; + float updateRenderable[nValues]; + float updateEphemeris[nValues]; - int32_t currentRenderTime; - int32_t currentUpdateRenderable; - int32_t currentUpdateEphemeris; - }; + int32_t currentRenderTime; + int32_t currentUpdateRenderable; + int32_t currentUpdateEphemeris; + }; - PerformanceLayoutEntry entries[maxValues]; - }; + PerformanceLayoutEntry entries[maxValues]; + }; - const int nNodes = static_cast(scene()->allSceneGraphNodes().size()); - if (!_performanceMemory) { + const int nNodes = static_cast(scene()->allSceneGraphNodes().size()); + if (!_performanceMemory) { - // Compute the total size - const int totalSize = sizeof(int8_t) + 4 * sizeof(int32_t) + - maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry); - LINFO("Create shared memory of " << totalSize << " bytes"); + // Compute the total size + const int totalSize = sizeof(int8_t) + 4 * sizeof(int32_t) + + maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry); + LINFO("Create shared memory of " << totalSize << " bytes"); try { ghoul::SharedMemory::remove(PerformanceMeasurementSharedData); @@ -681,52 +681,52 @@ void RenderEngine::storePerformanceMeasurements() { LINFOC(e.component, e.what()); } - ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize); - _performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData); + ghoul::SharedMemory::create(PerformanceMeasurementSharedData, totalSize); + _performanceMemory = new ghoul::SharedMemory(PerformanceMeasurementSharedData); void* ptr = _performanceMemory->memory(); - PerformanceLayout* layout = reinterpret_cast(ptr); - layout->version = Version; - layout->nValuesPerEntry = nValues; - layout->nEntries = nNodes; - layout->maxNameLength = lengthName; - layout->maxEntries = maxValues; + PerformanceLayout* layout = reinterpret_cast(ptr); + layout->version = Version; + layout->nValuesPerEntry = nValues; + layout->nEntries = nNodes; + layout->maxNameLength = lengthName; + layout->maxEntries = maxValues; - memset(layout->entries, 0, maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry)); + memset(layout->entries, 0, maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry)); - for (int i = 0; i < nNodes; ++i) { - SceneGraphNode* node = scene()->allSceneGraphNodes()[i]; + for (int i = 0; i < nNodes; ++i) { + SceneGraphNode* node = scene()->allSceneGraphNodes()[i]; - memset(layout->entries[i].name, 0, lengthName); + memset(layout->entries[i].name, 0, lengthName); #ifdef _MSC_VER strcpy_s(layout->entries[i].name, node->name().length() + 1, node->name().c_str()); #else strcpy(layout->entries[i].name, node->name().c_str()); #endif - layout->entries[i].currentRenderTime = 0; - layout->entries[i].currentUpdateRenderable = 0; - layout->entries[i].currentUpdateEphemeris = 0; - } - } + layout->entries[i].currentRenderTime = 0; + layout->entries[i].currentUpdateRenderable = 0; + layout->entries[i].currentUpdateEphemeris = 0; + } + } void* ptr = _performanceMemory->memory(); - PerformanceLayout* layout = reinterpret_cast(ptr); - _performanceMemory->acquireLock(); - for (int i = 0; i < nNodes; ++i) { - SceneGraphNode* node = scene()->allSceneGraphNodes()[i]; - SceneGraphNode::PerformanceRecord r = node->performanceRecord(); - PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; + PerformanceLayout* layout = reinterpret_cast(ptr); + _performanceMemory->acquireLock(); + for (int i = 0; i < nNodes; ++i) { + SceneGraphNode* node = scene()->allSceneGraphNodes()[i]; + SceneGraphNode::PerformanceRecord r = node->performanceRecord(); + PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i]; - entry.renderTime[entry.currentRenderTime] = r.renderTime / 1000.f; - entry.updateEphemeris[entry.currentUpdateEphemeris] = r.updateTimeEphemeris / 1000.f; - entry.updateRenderable[entry.currentUpdateRenderable] = r.updateTimeRenderable / 1000.f; + entry.renderTime[entry.currentRenderTime] = r.renderTime / 1000.f; + entry.updateEphemeris[entry.currentUpdateEphemeris] = r.updateTimeEphemeris / 1000.f; + entry.updateRenderable[entry.currentUpdateRenderable] = r.updateTimeRenderable / 1000.f; - entry.currentRenderTime = (entry.currentRenderTime + 1) % nValues; - entry.currentUpdateEphemeris = (entry.currentUpdateEphemeris + 1) % nValues; - entry.currentUpdateRenderable = (entry.currentUpdateRenderable + 1) % nValues; - } - _performanceMemory->releaseLock(); + entry.currentRenderTime = (entry.currentRenderTime + 1) % nValues; + entry.currentUpdateEphemeris = (entry.currentUpdateEphemeris + 1) % nValues; + entry.currentUpdateRenderable = (entry.currentUpdateRenderable + 1) % nValues; + } + _performanceMemory->releaseLock(); } // This method is temporary and will be removed once the scalegraph is in effect ---abock @@ -734,52 +734,52 @@ void RenderEngine::changeViewPoint(std::string origin) { SceneGraphNode* solarSystemBarycenterNode = scene()->sceneGraphNode("SolarSystemBarycenter"); SceneGraphNode* plutoBarycenterNode = scene()->sceneGraphNode("PlutoBarycenter"); SceneGraphNode* newHorizonsNode = scene()->sceneGraphNode("NewHorizons"); - SceneGraphNode* newHorizonsPathNodeJ = scene()->sceneGraphNode("NewHorizonsPathJupiter"); - SceneGraphNode* newHorizonsPathNodeP = scene()->sceneGraphNode("NewHorizonsPathPluto"); + SceneGraphNode* newHorizonsPathNodeJ = scene()->sceneGraphNode("NewHorizonsPathJupiter"); + SceneGraphNode* newHorizonsPathNodeP = scene()->sceneGraphNode("NewHorizonsPathPluto"); // SceneGraphNode* cg67pNode = scene()->sceneGraphNode("67P"); // SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta"); - RenderablePath* nhPath; + RenderablePath* nhPath; SceneGraphNode* jupiterBarycenterNode = scene()->sceneGraphNode("JupiterBarycenter"); - //SceneGraphNode* newHorizonsGhostNode = scene()->sceneGraphNode("NewHorizonsGhost"); - //SceneGraphNode* dawnNode = scene()->sceneGraphNode("Dawn"); - //SceneGraphNode* vestaNode = scene()->sceneGraphNode("Vesta"); + //SceneGraphNode* newHorizonsGhostNode = scene()->sceneGraphNode("NewHorizonsGhost"); + //SceneGraphNode* dawnNode = scene()->sceneGraphNode("Dawn"); + //SceneGraphNode* vestaNode = scene()->sceneGraphNode("Vesta"); // if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr || - //jupiterBarycenterNode == nullptr) { - // LERROR("Necessary nodes does not exist"); - //return; + //jupiterBarycenterNode == nullptr) { + // LERROR("Necessary nodes does not exist"); + //return; // } if (origin == "Pluto") { - if (newHorizonsPathNodeP) { - Renderable* R = newHorizonsPathNodeP->renderable(); - newHorizonsPathNodeP->setParent(plutoBarycenterNode); - nhPath = static_cast(R); - nhPath->calculatePath("PLUTO BARYCENTER"); - } + if (newHorizonsPathNodeP) { + Renderable* R = newHorizonsPathNodeP->renderable(); + newHorizonsPathNodeP->setParent(plutoBarycenterNode); + nhPath = static_cast(R); + nhPath->calculatePath("PLUTO BARYCENTER"); + } - plutoBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem")); - plutoBarycenterNode->setEphemeris(new StaticEphemeris); - - solarSystemBarycenterNode->setParent(plutoBarycenterNode); - newHorizonsNode->setParent(plutoBarycenterNode); - //newHorizonsGhostNode->setParent(plutoBarycenterNode); + plutoBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem")); + plutoBarycenterNode->setEphemeris(new StaticEphemeris); + + solarSystemBarycenterNode->setParent(plutoBarycenterNode); + newHorizonsNode->setParent(plutoBarycenterNode); + //newHorizonsGhostNode->setParent(plutoBarycenterNode); - //dawnNode->setParent(plutoBarycenterNode); - //vestaNode->setParent(plutoBarycenterNode); + //dawnNode->setParent(plutoBarycenterNode); + //vestaNode->setParent(plutoBarycenterNode); - //newHorizonsTrailNode->setParent(plutoBarycenterNode); - ghoul::Dictionary solarDictionary = - { - { std::string("Type"), std::string("Spice") }, - { std::string("Body"), std::string("SUN") }, - { std::string("Reference"), std::string("GALACTIC") }, - { std::string("Observer"), std::string("PLUTO BARYCENTER") }, - { std::string("Kernels"), ghoul::Dictionary() } - }; + //newHorizonsTrailNode->setParent(plutoBarycenterNode); + ghoul::Dictionary solarDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("SUN") }, + { std::string("Reference"), std::string("GALACTIC") }, + { std::string("Observer"), std::string("PLUTO BARYCENTER") }, + { std::string("Kernels"), ghoul::Dictionary() } + }; ghoul::Dictionary jupiterDictionary = { @@ -799,13 +799,13 @@ void RenderEngine::changeViewPoint(std::string origin) { { std::string("Kernels"), ghoul::Dictionary() } }; - solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); - jupiterBarycenterNode->setEphemeris(new SpiceEphemeris(jupiterDictionary)); + solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); + jupiterBarycenterNode->setEphemeris(new SpiceEphemeris(jupiterDictionary)); newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); - //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); - //ghoul::Dictionary dawnDictionary = + //ghoul::Dictionary dawnDictionary = //{ // { std::string("Type"), std::string("Spice") }, // { std::string("Body"), std::string("DAWN") }, @@ -814,42 +814,42 @@ void RenderEngine::changeViewPoint(std::string origin) { // { std::string("Kernels"), ghoul::Dictionary() } //}; //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary)); - // - //ghoul::Dictionary vestaDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("VESTA") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("PLUTO BARYCENTER") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary)); + // + //ghoul::Dictionary vestaDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("VESTA") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("PLUTO BARYCENTER") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary)); - - //ghoul::Dictionary newHorizonsGhostDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("NEW HORIZONS") }, - // { std::string("EphmerisGhosting"), std::string("TRUE") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("PLUTO BARYCENTER") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary)); - + + //ghoul::Dictionary newHorizonsGhostDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("NEW HORIZONS") }, + // { std::string("EphmerisGhosting"), std::string("TRUE") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("PLUTO BARYCENTER") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary)); + return; } if (origin == "Sun") { - solarSystemBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem")); + solarSystemBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem")); - plutoBarycenterNode->setParent(solarSystemBarycenterNode); - jupiterBarycenterNode->setParent(solarSystemBarycenterNode); - newHorizonsNode->setParent(solarSystemBarycenterNode); - //newHorizonsGhostNode->setParent(solarSystemBarycenterNode); + plutoBarycenterNode->setParent(solarSystemBarycenterNode); + jupiterBarycenterNode->setParent(solarSystemBarycenterNode); + newHorizonsNode->setParent(solarSystemBarycenterNode); + //newHorizonsGhostNode->setParent(solarSystemBarycenterNode); - //newHorizonsTrailNode->setParent(solarSystemBarycenterNode); - //dawnNode->setParent(solarSystemBarycenterNode); - //vestaNode->setParent(solarSystemBarycenterNode); + //newHorizonsTrailNode->setParent(solarSystemBarycenterNode); + //dawnNode->setParent(solarSystemBarycenterNode); + //vestaNode->setParent(solarSystemBarycenterNode); ghoul::Dictionary plutoDictionary = { @@ -881,232 +881,232 @@ void RenderEngine::changeViewPoint(std::string origin) { { std::string("Kernels"), ghoul::Dictionary() } }; newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); - //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); - //ghoul::Dictionary dawnDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("DAWN") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("SUN") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary)); - // - //ghoul::Dictionary vestaDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("VESTA") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("SUN") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary)); - - - //ghoul::Dictionary newHorizonsGhostDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("NEW HORIZONS") }, - // { std::string("EphmerisGhosting"), std::string("TRUE") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary)); - + //ghoul::Dictionary dawnDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("DAWN") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("SUN") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary)); + // + //ghoul::Dictionary vestaDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("VESTA") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("SUN") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary)); + + + //ghoul::Dictionary newHorizonsGhostDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("NEW HORIZONS") }, + // { std::string("EphmerisGhosting"), std::string("TRUE") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary)); + return; } if (origin == "Jupiter") { - if (newHorizonsPathNodeJ) { - Renderable* R = newHorizonsPathNodeJ->renderable(); - newHorizonsPathNodeJ->setParent(jupiterBarycenterNode); - nhPath = static_cast(R); - nhPath->calculatePath("JUPITER BARYCENTER"); - } + if (newHorizonsPathNodeJ) { + Renderable* R = newHorizonsPathNodeJ->renderable(); + newHorizonsPathNodeJ->setParent(jupiterBarycenterNode); + nhPath = static_cast(R); + nhPath->calculatePath("JUPITER BARYCENTER"); + } - jupiterBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem")); - jupiterBarycenterNode->setEphemeris(new StaticEphemeris); + jupiterBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem")); + jupiterBarycenterNode->setEphemeris(new StaticEphemeris); - solarSystemBarycenterNode->setParent(jupiterBarycenterNode); - newHorizonsNode->setParent(jupiterBarycenterNode); - //newHorizonsTrailNode->setParent(jupiterBarycenterNode); + solarSystemBarycenterNode->setParent(jupiterBarycenterNode); + newHorizonsNode->setParent(jupiterBarycenterNode); + //newHorizonsTrailNode->setParent(jupiterBarycenterNode); - //dawnNode->setParent(jupiterBarycenterNode); - //vestaNode->setParent(jupiterBarycenterNode); + //dawnNode->setParent(jupiterBarycenterNode); + //vestaNode->setParent(jupiterBarycenterNode); - ghoul::Dictionary solarDictionary = - { - { std::string("Type"), std::string("Spice") }, - { std::string("Body"), std::string("SUN") }, - { std::string("Reference"), std::string("GALACTIC") }, - { std::string("Observer"), std::string("JUPITER BARYCENTER") }, - { std::string("Kernels"), ghoul::Dictionary() } - }; + ghoul::Dictionary solarDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("SUN") }, + { std::string("Reference"), std::string("GALACTIC") }, + { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + { std::string("Kernels"), ghoul::Dictionary() } + }; - ghoul::Dictionary plutoDictionary = - { - { std::string("Type"), std::string("Spice") }, - { std::string("Body"), std::string("PlUTO BARYCENTER") }, - { std::string("Reference"), std::string("GALACTIC") }, - { std::string("Observer"), std::string("JUPITER BARYCENTER") }, - { std::string("Kernels"), ghoul::Dictionary() } - }; + ghoul::Dictionary plutoDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("PlUTO BARYCENTER") }, + { std::string("Reference"), std::string("GALACTIC") }, + { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + { std::string("Kernels"), ghoul::Dictionary() } + }; - ghoul::Dictionary newHorizonsDictionary = - { - { std::string("Type"), std::string("Spice") }, - { std::string("Body"), std::string("NEW HORIZONS") }, - { std::string("Reference"), std::string("GALACTIC") }, - { std::string("Observer"), std::string("JUPITER BARYCENTER") }, - { std::string("Kernels"), ghoul::Dictionary() } - }; - solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); - plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary)); - newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); - //newHorizonsGhostNode->setParent(jupiterBarycenterNode); - //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + ghoul::Dictionary newHorizonsDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("NEW HORIZONS") }, + { std::string("Reference"), std::string("GALACTIC") }, + { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + { std::string("Kernels"), ghoul::Dictionary() } + }; + solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); + plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary)); + newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + //newHorizonsGhostNode->setParent(jupiterBarycenterNode); + //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); - //ghoul::Dictionary dawnDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("DAWN") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary)); - // - //ghoul::Dictionary vestaDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("VESTA") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary)); + //ghoul::Dictionary dawnDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("DAWN") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary)); + // + //ghoul::Dictionary vestaDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("VESTA") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary)); - - //ghoul::Dictionary newHorizonsGhostDictionary = - //{ - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("NEW HORIZONS") }, - // { std::string("EphmerisGhosting"), std::string("TRUE") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, - // { std::string("Kernels"), ghoul::Dictionary() } - //}; - //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary)); - //newHorizonsGhostNode->setParent(jupiterBarycenterNode); + + //ghoul::Dictionary newHorizonsGhostDictionary = + //{ + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("NEW HORIZONS") }, + // { std::string("EphmerisGhosting"), std::string("TRUE") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + // { std::string("Kernels"), ghoul::Dictionary() } + //}; + //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary)); + //newHorizonsGhostNode->setParent(jupiterBarycenterNode); - + return; } - //if (origin == "Vesta") { - // - // vestaNode->setParent(scene()->sceneGraphNode("SolarSystem")); - // vestaNode->setEphemeris(new StaticEphemeris); - // - // solarSystemBarycenterNode->setParent(vestaNode); - // newHorizonsNode->setParent(vestaNode); - // - // dawnNode->setParent(vestaNode); - // plutoBarycenterNode->setParent(vestaNode); - // - // - // ghoul::Dictionary plutoDictionary = - // { - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("PLUTO BARYCENTER") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("VESTA") }, - // { std::string("Kernels"), ghoul::Dictionary() } - // }; - // ghoul::Dictionary solarDictionary = - // { - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("SUN") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("VESTA") }, - // { std::string("Kernels"), ghoul::Dictionary() } - // }; - // - // ghoul::Dictionary jupiterDictionary = - // { - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("JUPITER BARYCENTER") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("VESTA") }, - // { std::string("Kernels"), ghoul::Dictionary() } - // }; - // - // solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); - // plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary)); - // jupiterBarycenterNode->setEphemeris(new SpiceEphemeris(jupiterDictionary)); - // - // ghoul::Dictionary newHorizonsDictionary = - // { - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("NEW HORIZONS") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("VESTA") }, - // { std::string("Kernels"), ghoul::Dictionary() } - // }; - // newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); - // - // ghoul::Dictionary dawnDictionary = - // { - // { std::string("Type"), std::string("Spice") }, - // { std::string("Body"), std::string("DAWN") }, - // { std::string("Reference"), std::string("GALACTIC") }, - // { std::string("Observer"), std::string("VESTA") }, - // { std::string("Kernels"), ghoul::Dictionary() } - // }; - // dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary)); - // vestaNode->setEphemeris(new StaticEphemeris); - // - // return; - //} + //if (origin == "Vesta") { + // + // vestaNode->setParent(scene()->sceneGraphNode("SolarSystem")); + // vestaNode->setEphemeris(new StaticEphemeris); + // + // solarSystemBarycenterNode->setParent(vestaNode); + // newHorizonsNode->setParent(vestaNode); + // + // dawnNode->setParent(vestaNode); + // plutoBarycenterNode->setParent(vestaNode); + // + // + // ghoul::Dictionary plutoDictionary = + // { + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("PLUTO BARYCENTER") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("VESTA") }, + // { std::string("Kernels"), ghoul::Dictionary() } + // }; + // ghoul::Dictionary solarDictionary = + // { + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("SUN") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("VESTA") }, + // { std::string("Kernels"), ghoul::Dictionary() } + // }; + // + // ghoul::Dictionary jupiterDictionary = + // { + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("JUPITER BARYCENTER") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("VESTA") }, + // { std::string("Kernels"), ghoul::Dictionary() } + // }; + // + // solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); + // plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary)); + // jupiterBarycenterNode->setEphemeris(new SpiceEphemeris(jupiterDictionary)); + // + // ghoul::Dictionary newHorizonsDictionary = + // { + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("NEW HORIZONS") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("VESTA") }, + // { std::string("Kernels"), ghoul::Dictionary() } + // }; + // newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + // + // ghoul::Dictionary dawnDictionary = + // { + // { std::string("Type"), std::string("Spice") }, + // { std::string("Body"), std::string("DAWN") }, + // { std::string("Reference"), std::string("GALACTIC") }, + // { std::string("Observer"), std::string("VESTA") }, + // { std::string("Kernels"), ghoul::Dictionary() } + // }; + // dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary)); + // vestaNode->setEphemeris(new StaticEphemeris); + // + // return; + //} - if (origin == "67P") { - SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta"); - SceneGraphNode* cgNode = scene()->sceneGraphNode("67P"); - //jupiterBarycenterNode->setParent(solarSystemBarycenterNode); - //plutoBarycenterNode->setParent(solarSystemBarycenterNode); - solarSystemBarycenterNode->setParent(cgNode); - rosettaNode->setParent(cgNode); - - ghoul::Dictionary solarDictionary = - { - { std::string("Type"), std::string("Spice") }, - { std::string("Body"), std::string("SUN") }, - { std::string("Reference"), std::string("GALACTIC") }, - { std::string("Observer"), std::string("CHURYUMOV-GERASIMENKO") }, - { std::string("Kernels"), ghoul::Dictionary() } - }; - solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); - - ghoul::Dictionary rosettaDictionary = - { - { std::string("Type"), std::string("Spice") }, - { std::string("Body"), std::string("ROSETTA") }, - { std::string("Reference"), std::string("GALACTIC") }, - { std::string("Observer"), std::string("CHURYUMOV-GERASIMENKO") }, - { std::string("Kernels"), ghoul::Dictionary() } - }; - - cgNode->setParent(scene()->sceneGraphNode("SolarSystem")); - rosettaNode->setEphemeris(new SpiceEphemeris(rosettaDictionary)); - cgNode->setEphemeris(new StaticEphemeris); - - return; - - } + if (origin == "67P") { + SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta"); + SceneGraphNode* cgNode = scene()->sceneGraphNode("67P"); + //jupiterBarycenterNode->setParent(solarSystemBarycenterNode); + //plutoBarycenterNode->setParent(solarSystemBarycenterNode); + solarSystemBarycenterNode->setParent(cgNode); + rosettaNode->setParent(cgNode); + + ghoul::Dictionary solarDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("SUN") }, + { std::string("Reference"), std::string("GALACTIC") }, + { std::string("Observer"), std::string("CHURYUMOV-GERASIMENKO") }, + { std::string("Kernels"), ghoul::Dictionary() } + }; + solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary)); + + ghoul::Dictionary rosettaDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("ROSETTA") }, + { std::string("Reference"), std::string("GALACTIC") }, + { std::string("Observer"), std::string("CHURYUMOV-GERASIMENKO") }, + { std::string("Kernels"), ghoul::Dictionary() } + }; + + cgNode->setParent(scene()->sceneGraphNode("SolarSystem")); + rosettaNode->setEphemeris(new SpiceEphemeris(rosettaDictionary)); + cgNode->setEphemeris(new StaticEphemeris); + + return; + + } LFATAL("This function is being misused with an argument of '" << origin << "'"); } @@ -1128,46 +1128,46 @@ RenderEngine::RendererImplementation RenderEngine::rendererFromString(const std: } void RenderEngine::renderInformation() { - // TODO: Adjust font_size properly when using retina screen - const float fontSizeMono = 10.f; - const float fontSizeTime = 15.f; + // TODO: Adjust font_size properly when using retina screen + const float fontSizeMono = 10.f; + const float fontSizeTime = 15.f; - using Font = ghoul::fontrendering::Font; - using ghoul::fontrendering::RenderFont; + using Font = ghoul::fontrendering::Font; + using ghoul::fontrendering::RenderFont; - if (_showInfo && _fontDate && _fontInfo) { - double currentTime = Time::ref().currentTime(); + if (_showInfo && _fontDate && _fontInfo) { + double currentTime = Time::ref().currentTime(); - glm::vec2 penPosition = glm::vec2( - 10.f, - OsEng.windowWrapper().viewportPixelCoordinates().w - ); - penPosition.y -= _fontDate->height(); + glm::vec2 penPosition = glm::vec2( + 10.f, + OsEng.windowWrapper().viewportPixelCoordinates().w + ); + penPosition.y -= _fontDate->height(); - RenderFontCr(*_fontDate, - penPosition, - "Date: %s", - Time::ref().currentTimeUTC().c_str() - ); + RenderFontCr(*_fontDate, + penPosition, + "Date: %s", + Time::ref().currentTimeUTC().c_str() + ); - RenderFontCr(*_fontInfo, - penPosition, - "Simulation increment (s): %.0f", - Time::ref().deltaTime() - ); + RenderFontCr(*_fontInfo, + penPosition, + "Simulation increment (s): %.0f", + Time::ref().deltaTime() + ); - RenderFontCr(*_fontInfo, - penPosition, - "Avg. Frametime: %.5f", - OsEng.windowWrapper().averageDeltaTime() - ); + RenderFontCr(*_fontInfo, + penPosition, + "Avg. Frametime: %.5f", + OsEng.windowWrapper().averageDeltaTime() + ); #ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED - if (openspace::ImageSequencer2::ref().isReady()) { - penPosition.y -= 25.f; + if (openspace::ImageSequencer::ref().isReady()) { + penPosition.y -= 25.f; - glm::vec4 targetColor(0.00, 0.75, 1.00, 1); + glm::vec4 targetColor(0.00, 0.75, 1.00, 1); try { double lt; @@ -1192,243 +1192,243 @@ void RenderEngine::renderInformation() { } catch (...) {} - double remaining = openspace::ImageSequencer2::ref().getNextCaptureTime() - currentTime; - float t = static_cast(1.0 - remaining / openspace::ImageSequencer2::ref().getIntervalLength()); - std::string progress = "|"; - int g = static_cast((t * 24) + 1); - g = std::max(g, 0); - for (int i = 0; i < g; i++) - progress.append("-"); - progress.append(">"); - for (int i = 0; i < 25 - g; i++) - progress.append(" "); + double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - currentTime; + float t = static_cast(1.0 - remaining / openspace::ImageSequencer::ref().getIntervalLength()); + std::string progress = "|"; + int g = static_cast((t * 24) + 1); + g = std::max(g, 0); + for (int i = 0; i < g; i++) + progress.append("-"); + progress.append(">"); + for (int i = 0; i < 25 - g; i++) + progress.append(" "); - std::string str = SpiceManager::ref().dateFromEphemerisTime( - ImageSequencer2::ref().getNextCaptureTime(), - "YYYY MON DD HR:MN:SC" - ); + std::string str = SpiceManager::ref().dateFromEphemerisTime( + ImageSequencer::ref().getNextCaptureTime(), + "YYYY MON DD HR:MN:SC" + ); - glm::vec4 active(0.6, 1, 0.00, 1); - glm::vec4 brigther_active(0.9, 1, 0.75, 1); + glm::vec4 active(0.6, 1, 0.00, 1); + glm::vec4 brigther_active(0.9, 1, 0.75, 1); - progress.append("|"); - if (remaining > 0) { - brigther_active *= (1 - t); + progress.append("|"); + if (remaining > 0) { + brigther_active *= (1 - t); - RenderFontCr(*_fontInfo, - penPosition, - active * t + brigther_active, - "Next instrument activity:" - ); + RenderFontCr(*_fontInfo, + penPosition, + active * t + brigther_active, + "Next instrument activity:" + ); - RenderFontCr(*_fontInfo, - penPosition, - active * t + brigther_active, - "%.0f s %s %.1f %%", - remaining, progress.c_str(), t * 100 - ); + RenderFontCr(*_fontInfo, + penPosition, + active * t + brigther_active, + "%.0f s %s %.1f %%", + remaining, progress.c_str(), t * 100 + ); - RenderFontCr(*_fontInfo, - penPosition, - active, - "Data acquisition time: %s", - str.c_str() - ); - } - std::pair nextTarget = ImageSequencer2::ref().getNextTarget(); - std::pair currentTarget = ImageSequencer2::ref().getCurrentTarget(); + RenderFontCr(*_fontInfo, + penPosition, + active, + "Data acquisition time: %s", + str.c_str() + ); + } + std::pair nextTarget = ImageSequencer::ref().getNextTarget(); + std::pair currentTarget = ImageSequencer::ref().getCurrentTarget(); - if (currentTarget.first > 0.0) { - int timeleft = static_cast(nextTarget.first - currentTime); + if (currentTarget.first > 0.0) { + int timeleft = static_cast(nextTarget.first - currentTime); - int hour = timeleft / 3600; - int second = timeleft % 3600; - int minute = second / 60; - second = second % 60; + int hour = timeleft / 3600; + int second = timeleft % 3600; + int minute = second / 60; + second = second % 60; - std::string hh, mm, ss, coundtown; + std::string hh, mm, ss, coundtown; - if (hour < 10) hh.append("0"); - if (minute < 10) mm.append("0"); - if (second < 10) ss.append("0"); + if (hour < 10) hh.append("0"); + if (minute < 10) mm.append("0"); + if (second < 10) ss.append("0"); - hh.append(std::to_string(hour)); - mm.append(std::to_string(minute)); - ss.append(std::to_string(second)); + hh.append(std::to_string(hour)); + mm.append(std::to_string(minute)); + ss.append(std::to_string(second)); - RenderFontCr(*_fontInfo, - penPosition, - targetColor, - "Data acquisition adjacency: [%s:%s:%s]", - hh.c_str(), mm.c_str(), ss.c_str() - ); + RenderFontCr(*_fontInfo, + penPosition, + targetColor, + "Data acquisition adjacency: [%s:%s:%s]", + hh.c_str(), mm.c_str(), ss.c_str() + ); - std::pair> incidentTargets = ImageSequencer2::ref().getIncidentTargetList(2); - std::string space; - glm::vec4 color; - size_t isize = incidentTargets.second.size(); - for (size_t p = 0; p < isize; p++) { - double t = static_cast(p + 1) / static_cast(isize + 1); - t = (p > isize / 2) ? 1 - t : t; - t += 0.3; - color = (p == isize / 2) ? targetColor : glm::vec4(t, t, t, 1); + std::pair> incidentTargets = ImageSequencer::ref().getIncidentTargetList(2); + std::string space; + glm::vec4 color; + size_t isize = incidentTargets.second.size(); + for (size_t p = 0; p < isize; p++) { + double t = static_cast(p + 1) / static_cast(isize + 1); + t = (p > isize / 2) ? 1 - t : t; + t += 0.3; + color = (p == isize / 2) ? targetColor : glm::vec4(t, t, t, 1); - RenderFont(*_fontInfo, - penPosition, - color, - "%s%s", - space.c_str(), incidentTargets.second[p].c_str() - ); + RenderFont(*_fontInfo, + penPosition, + color, + "%s%s", + space.c_str(), incidentTargets.second[p].c_str() + ); - for (int k = 0; k < incidentTargets.second[p].size() + 2; k++) - space += " "; - } - penPosition.y -= _fontInfo->height(); + for (int k = 0; k < incidentTargets.second[p].size() + 2; k++) + space += " "; + } + penPosition.y -= _fontInfo->height(); - std::map activeMap = ImageSequencer2::ref().getActiveInstruments(); - glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1); - glm::vec4 notFiring(0.5, 0.5, 0.5, 1); + std::map activeMap = ImageSequencer::ref().getActiveInstruments(); + glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1); + glm::vec4 notFiring(0.5, 0.5, 0.5, 1); - RenderFontCr(*_fontInfo, - penPosition, - active, - "Active Instruments:" - ); + RenderFontCr(*_fontInfo, + penPosition, + active, + "Active Instruments:" + ); - for (auto t : activeMap) { - if (t.second == false) { - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - "| |" - ); - RenderFontCr(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - " %5s", - t.first.c_str() - ); + for (auto t : activeMap) { + if (t.second == false) { + RenderFont(*_fontInfo, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + "| |" + ); + RenderFontCr(*_fontInfo, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + " %5s", + t.first.c_str() + ); - } - else { - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - "|" - ); - if (t.first == "NH_LORRI") { - RenderFont(*_fontInfo, - penPosition, - firing, - " + " - ); - } - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - " |" - ); - RenderFontCr(*_fontInfo, - penPosition, - active, - " %5s", - t.first.c_str() - ); - } - } - } - } + } + else { + RenderFont(*_fontInfo, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + "|" + ); + if (t.first == "NH_LORRI") { + RenderFont(*_fontInfo, + penPosition, + firing, + " + " + ); + } + RenderFont(*_fontInfo, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + " |" + ); + RenderFontCr(*_fontInfo, + penPosition, + active, + " %5s", + t.first.c_str() + ); + } + } + } + } #endif - } + } } void RenderEngine::renderScreenLog() { - _log->removeExpiredEntries(); + _log->removeExpiredEntries(); - const int max = 10; - const int category_length = 20; - const int msg_length = 140; - std::chrono::seconds fade(5); + const int max = 10; + const int category_length = 20; + const int msg_length = 140; + std::chrono::seconds fade(5); - auto entries = _log->entries(); - auto lastEntries = entries.size() > max ? std::make_pair(entries.rbegin(), entries.rbegin() + max) : std::make_pair(entries.rbegin(), entries.rend()); + auto entries = _log->entries(); + auto lastEntries = entries.size() > max ? std::make_pair(entries.rbegin(), entries.rbegin() + max) : std::make_pair(entries.rbegin(), entries.rend()); - // if (entries.size() > max) + // if (entries.size() > max) - //ScreenLog::const_range ScreenLog::last(size_t n) { - // if (_entries.size() > n) { - // return std::make_pair(_entries.rbegin(), _entries.rbegin() + n); - // } else { - // return std::make_pair(_entries.rbegin(), _entries.rend()); - // } - //} + //ScreenLog::const_range ScreenLog::last(size_t n) { + // if (_entries.size() > n) { + // return std::make_pair(_entries.rbegin(), _entries.rbegin() + n); + // } else { + // return std::make_pair(_entries.rbegin(), _entries.rend()); + // } + //} - // auto entries = _log->last(max); + // auto entries = _log->last(max); - const glm::vec4 white(0.9, 0.9, 0.9, 1); - const glm::vec4 red(1, 0, 0, 1); - const glm::vec4 yellow(1, 1, 0, 1); - const glm::vec4 green(0, 1, 0, 1); - const glm::vec4 blue(0, 0, 1, 1); + const glm::vec4 white(0.9, 0.9, 0.9, 1); + const glm::vec4 red(1, 0, 0, 1); + const glm::vec4 yellow(1, 1, 0, 1); + const glm::vec4 green(0, 1, 0, 1); + const glm::vec4 blue(0, 0, 1, 1); - size_t nr = 1; - auto now = std::chrono::steady_clock::now(); - for (auto& it = lastEntries.first; it != lastEntries.second; ++it) { - const ScreenLog::LogEntry* e = &(*it); + size_t nr = 1; + auto now = std::chrono::steady_clock::now(); + for (auto& it = lastEntries.first; it != lastEntries.second; ++it) { + const ScreenLog::LogEntry* e = &(*it); - std::chrono::duration diff = now - e->timeStamp; + std::chrono::duration diff = now - e->timeStamp; - float alpha = 1; - std::chrono::duration ttf = ScreenLogTimeToLive - fade; - if (diff > ttf) { - auto d = (diff - ttf).count(); - auto t = static_cast(d) / static_cast(fade.count()); - float p = 0.8f - t; - alpha = (p <= 0.f) ? 0.f : pow(p, 0.3f); - } + float alpha = 1; + std::chrono::duration ttf = ScreenLogTimeToLive - fade; + if (diff > ttf) { + auto d = (diff - ttf).count(); + auto t = static_cast(d) / static_cast(fade.count()); + float p = 0.8f - t; + alpha = (p <= 0.f) ? 0.f : pow(p, 0.3f); + } - // Since all log entries are ordered, once one exceeds alpha, all have - if (alpha <= 0.0) - break; + // Since all log entries are ordered, once one exceeds alpha, all have + if (alpha <= 0.0) + break; - const std::string lvl = "(" + ghoul::logging::LogManager::stringFromLevel(e->level) + ")"; - const std::string& message = e->message.substr(0, msg_length); - nr += std::count(message.begin(), message.end(), '\n'); + const std::string lvl = "(" + ghoul::logging::LogManager::stringFromLevel(e->level) + ")"; + const std::string& message = e->message.substr(0, msg_length); + nr += std::count(message.begin(), message.end(), '\n'); - RenderFont(*_fontLog, - glm::vec2(10.f, _fontLog->pointSize() * nr * 2), - white * alpha, - "%-14s %s%s", // Format - e->timeString.c_str(), // Time string - e->category.substr(0, category_length).c_str(), // Category string (up to category_length) - e->category.length() > 20 ? "..." : ""); // Pad category with "..." if exceeds category_length + RenderFont(*_fontLog, + glm::vec2(10.f, _fontLog->pointSize() * nr * 2), + white * alpha, + "%-14s %s%s", // Format + e->timeString.c_str(), // Time string + e->category.substr(0, category_length).c_str(), // Category string (up to category_length) + e->category.length() > 20 ? "..." : ""); // Pad category with "..." if exceeds category_length - glm::vec4 color = white; - if (e->level == ghoul::logging::LogManager::LogLevel::Debug) - color = green; - if (e->level == ghoul::logging::LogManager::LogLevel::Warning) - color = yellow; - if (e->level == ghoul::logging::LogManager::LogLevel::Error) - color = red; - if (e->level == ghoul::logging::LogManager::LogLevel::Fatal) - color = blue; + glm::vec4 color = white; + if (e->level == ghoul::logging::LogManager::LogLevel::Debug) + color = green; + if (e->level == ghoul::logging::LogManager::LogLevel::Warning) + color = yellow; + if (e->level == ghoul::logging::LogManager::LogLevel::Error) + color = red; + if (e->level == ghoul::logging::LogManager::LogLevel::Fatal) + color = blue; - // const float font_with_light = 5; - RenderFont(*_fontLog, - glm::vec2(static_cast(10 + 39 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), - color * alpha, - "%s", // Format - lvl.c_str()); // Pad category with "..." if exceeds category_length + // const float font_with_light = 5; + RenderFont(*_fontLog, + glm::vec2(static_cast(10 + 39 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), + color * alpha, + "%s", // Format + lvl.c_str()); // Pad category with "..." if exceeds category_length - RenderFont(*_fontLog, - glm::vec2(static_cast(10 + 53 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), - white * alpha, - "%s", // Format - message.c_str()); // Pad category with "..." if exceeds category_length - ++nr; - } + RenderFont(*_fontLog, + glm::vec2(static_cast(10 + 53 * _fontLog->pointSize()), _fontLog->pointSize() * nr * 2), + white * alpha, + "%s", // Format + message.c_str()); // Pad category with "..." if exceeds category_length + ++nr; + } } }// namespace openspace From a21c9538b620a68bdabd78c16332880d3ae9dcbe Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 15:15:30 +0200 Subject: [PATCH 35/38] Untabify more files --- apps/Launcher/main.cpp | 8 +- apps/Launcher/mainwindow.cpp | 32 +- apps/OpenSpace/main.cpp | 6 +- .../openspace/engine/configurationmanager.h | 4 +- include/openspace/rendering/renderengine.h | 76 ++-- modules/base/rendering/renderableplanet.cpp | 150 +++--- modules/newhorizons/util/labelparser.cpp | 430 +++++++++--------- src/engine/configurationmanager.cpp | 56 +-- src/scene/scenegraphnode.cpp | 128 +++--- src/util/spicemanager.cpp | 176 +++---- 10 files changed, 533 insertions(+), 533 deletions(-) diff --git a/apps/Launcher/main.cpp b/apps/Launcher/main.cpp index 2a2b819bdf..c802f468cc 100644 --- a/apps/Launcher/main.cpp +++ b/apps/Launcher/main.cpp @@ -166,11 +166,11 @@ QScrollBar::add-page, QScrollBar::sub-page { )style"; int main(int argc, char** argv) { - QApplication app(argc, argv); + QApplication app(argc, argv); app.setStyleSheet(style); - MainWindow window; - window.show(); + MainWindow window; + window.show(); - return app.exec(); + return app.exec(); } diff --git a/apps/Launcher/mainwindow.cpp b/apps/Launcher/mainwindow.cpp index c2b125f018..77d61a51d2 100644 --- a/apps/Launcher/mainwindow.cpp +++ b/apps/Launcher/mainwindow.cpp @@ -104,58 +104,58 @@ MainWindow::MainWindow() QWidget* container = new QWidget; { - QGridLayout* layout = new QGridLayout; + QGridLayout* innerLayout = new QGridLayout; QLabel* shortcutLabel = new QLabel("Keyboard Shortcuts:"); - layout->addWidget(shortcutLabel, 0, 0); + innerLayout->addWidget(shortcutLabel, 0, 0); QPushButton* shortcutButton = new QPushButton("Open..."); QObject::connect(shortcutButton, SIGNAL(clicked(bool)), this, SLOT(shortcutButtonPressed()) ); - layout->addWidget(shortcutButton, 0, 1); + innerLayout->addWidget(shortcutButton, 0, 1); - layout->setRowStretch(1, 10); + innerLayout->setRowStretch(1, 10); QLabel* configurationSelectionLabel = new QLabel("Configuration:"); - layout->addWidget(configurationSelectionLabel, 2, 0); + innerLayout->addWidget(configurationSelectionLabel, 2, 0); _configurations = new QComboBox; - layout->addWidget(_configurations, 2, 1); + innerLayout->addWidget(_configurations, 2, 1); QLabel* sceneSelectionLabel = new QLabel("Scenes:"); - layout->addWidget(sceneSelectionLabel, 3, 0); + innerLayout->addWidget(sceneSelectionLabel, 3, 0); _scenes = new QComboBox; - layout->addWidget(_scenes, 3, 1); + innerLayout->addWidget(_scenes, 3, 1); - container->setLayout(layout); + container->setLayout(innerLayout); } layout->addWidget(container, 1, 1); container = new QWidget; { - QBoxLayout* layout = new QHBoxLayout; + QBoxLayout* innerLayout = new QHBoxLayout; QPushButton* cancelButton = new QPushButton("Cancel"); QObject::connect( cancelButton, SIGNAL(clicked(bool)), QApplication::instance(), SLOT(quit()) ); - layout->addWidget(cancelButton); + innerLayout->addWidget(cancelButton); QPushButton* syncButton = new QPushButton("Sync"); QObject::connect( syncButton, SIGNAL(clicked(bool)), this, SLOT(syncButtonPressed()) ); - layout->addWidget(syncButton); + innerLayout->addWidget(syncButton); QPushButton* startButton = new QPushButton("Start"); QObject::connect( startButton, SIGNAL(clicked(bool)), this, SLOT(startButtonPressed()) ); - layout->addWidget(startButton); + innerLayout->addWidget(startButton); - container->setLayout(layout); + container->setLayout(innerLayout); } layout->addWidget(container, 2, 1); @@ -257,8 +257,8 @@ void MainWindow::newsNetworkError() { } void MainWindow::newsReadyRead() { - QByteArray data = _newsReply->readAll(); - QString news = QString::fromLatin1(data); + QByteArray arrayData = _newsReply->readAll(); + QString news = QString::fromLatin1(arrayData); _informationWidget->setText(news); _newsReply->deleteLater(); } diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 4dcf2495ef..0eba15f18b 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -167,9 +167,9 @@ int main(int argc, char** argv) { LDEBUG("Starting rendering loop"); _sgctEngine->render(); - //clear function bindings to avoid crash after destroying the OpenSpace Engine - sgct::MessageHandler::instance()->setLogToCallback(false); - sgct::MessageHandler::instance()->setLogCallback(nullptr); + //clear function bindings to avoid crash after destroying the OpenSpace Engine + sgct::MessageHandler::instance()->setLogToCallback(false); + sgct::MessageHandler::instance()->setLogCallback(nullptr); LDEBUG("Destroying OpenSpaceEngine"); openspace::OpenSpaceEngine::destroy(); diff --git a/include/openspace/engine/configurationmanager.h b/include/openspace/engine/configurationmanager.h index 7b5ff621ae..c82ecb07fa 100644 --- a/include/openspace/engine/configurationmanager.h +++ b/include/openspace/engine/configurationmanager.h @@ -116,7 +116,7 @@ public: * configuration file * \pre \p filename must not be empty */ - void loadFromFile(const std::string& filename); + void loadFromFile(const std::string& filename); private: /** @@ -126,7 +126,7 @@ private: * \return true if the configuration file was complete; * false otherwise */ - bool checkCompleteness() const; + bool checkCompleteness() const; }; } // namespace openspace diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 3265817389..27f0acc6b4 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -60,16 +60,16 @@ public: Invalid }; - static const std::string PerformanceMeasurementSharedData; + static const std::string PerformanceMeasurementSharedData; static const std::string KeyFontMono; static const std::string KeyFontLight; - RenderEngine(); - ~RenderEngine(); - - bool initialize(); - bool deinitialize(); + RenderEngine(); + ~RenderEngine(); + + bool initialize(); + bool deinitialize(); void setSceneGraph(Scene* sceneGraph); Scene* scene(); @@ -79,24 +79,24 @@ public: RendererImplementation rendererImplementation() const; RaycasterManager& raycasterManager(); - // sgct wrapped functions + // sgct wrapped functions bool initializeGL(); void postSynchronizationPreDraw(); - void preSynchronization(); - void render(const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix); + void preSynchronization(); + void render(const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix); void postDraw(); - void takeScreenshot(); - void toggleInfoText(bool b); + void takeScreenshot(); + void toggleInfoText(bool b); - void setPerformanceMeasurements(bool performanceMeasurements); - bool doesPerformanceMeasurements() const; + void setPerformanceMeasurements(bool performanceMeasurements); + bool doesPerformanceMeasurements() const; - void serialize(SyncBuffer* syncBuffer); - void deserialize(SyncBuffer* syncBuffer); + void serialize(SyncBuffer* syncBuffer); + void deserialize(SyncBuffer* syncBuffer); - float globalBlackOutFactor(); - void setGlobalBlackOutFactor(float factor); + float globalBlackOutFactor(); + void setGlobalBlackOutFactor(float factor); void setDisableRenderingOnMaster(bool enabled); @@ -122,18 +122,18 @@ public: * as a 'rendererData' variable in the dictionary. */ void setRendererData(const ghoul::Dictionary& renderer); - - /** - * Returns the Lua library that contains all Lua functions available to affect the - * rendering. - */ - static scripting::ScriptEngine::LuaLibrary luaLibrary(); + + /** + * Returns the Lua library that contains all Lua functions available to affect the + * rendering. + */ + static scripting::ScriptEngine::LuaLibrary luaLibrary(); // This is a temporary method to change the origin of the coordinate system ---abock void changeViewPoint(std::string origin); - // Temporary fade functionality - void startFading(int direction, float fadeDuration); + // Temporary fade functionality + void startFading(int direction, float fadeDuration); // This is temporary until a proper screenspace solution is found ---abock struct { @@ -145,30 +145,30 @@ public: private: void setRenderer(std::unique_ptr renderer); RendererImplementation rendererFromString(const std::string& method); - void storePerformanceMeasurements(); + void storePerformanceMeasurements(); void renderInformation(); void renderScreenLog(); - Camera* _mainCamera; - Scene* _sceneGraph; + Camera* _mainCamera; + Scene* _sceneGraph; RaycasterManager* _raycasterManager; std::unique_ptr _renderer; RendererImplementation _rendererImplementation; ghoul::Dictionary _rendererData; - ScreenLog* _log; + ScreenLog* _log; - bool _showInfo; - bool _showLog; - bool _takeScreenshot; + bool _showInfo; + bool _showLog; + bool _takeScreenshot; - bool _doPerformanceMeasurements; - ghoul::SharedMemory* _performanceMemory; + bool _doPerformanceMeasurements; + ghoul::SharedMemory* _performanceMemory; - float _globalBlackOutFactor; - float _fadeDuration; - float _currentFadeTime; - int _fadeDirection; + float _globalBlackOutFactor; + float _fadeDuration; + float _currentFadeTime; + int _fadeDirection; std::vector _programs; diff --git a/modules/base/rendering/renderableplanet.cpp b/modules/base/rendering/renderableplanet.cpp index 25f4c201b4..3f91eb1d81 100644 --- a/modules/base/rendering/renderableplanet.cpp +++ b/modules/base/rendering/renderableplanet.cpp @@ -57,20 +57,20 @@ namespace openspace { RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary) : Renderable(dictionary) - , _colorTexturePath("colorTexture", "Color Texture") + , _colorTexturePath("colorTexture", "Color Texture") , _programObject(nullptr) , _texture(nullptr) - , _nightTexture(nullptr) + , _nightTexture(nullptr) , _geometry(nullptr) , _performShading("performShading", "Perform Shading", true) - , _rotation("rotation", "Rotation", 0, 0, 360) - , _alpha(1.f) + , _rotation("rotation", "Rotation", 0, 0, 360) + , _alpha(1.f) , _nightTexturePath("") , _hasNightTexture(false) { - std::string name; - bool success = dictionary.getValue(SceneGraphNode::KeyName, name); - ghoul_assert(success, + std::string name; + bool success = dictionary.getValue(SceneGraphNode::KeyName, name); + ghoul_assert(success, "RenderablePlanet need the '" << SceneGraphNode::KeyName<<"' be specified"); //std::string path; @@ -80,35 +80,35 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary) ghoul::Dictionary geometryDictionary; success = dictionary.getValue(keyGeometry, geometryDictionary); - if (success) { - geometryDictionary.setValue(SceneGraphNode::KeyName, name); + if (success) { + geometryDictionary.setValue(SceneGraphNode::KeyName, name); //geometryDictionary.setValue(constants::scenegraph::keyPathModule, path); _geometry = planetgeometry::PlanetGeometry::createFromDictionary(geometryDictionary); - } + } - dictionary.getValue(keyFrame, _frame); - dictionary.getValue(keyBody, _target); - if (_target != "") - setBody(_target); + dictionary.getValue(keyFrame, _frame); + dictionary.getValue(keyBody, _target); + if (_target != "") + setBody(_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) + success = dictionary.getValue("Textures.Color", texturePath); + if (success) _colorTexturePath = absPath(texturePath); - std::string nightTexturePath = ""; - dictionary.getValue("Textures.Night", nightTexturePath); - - if (nightTexturePath != ""){ - _hasNightTexture = true; - _nightTexturePath = absPath(nightTexturePath); - } + std::string nightTexturePath = ""; + dictionary.getValue("Textures.Night", nightTexturePath); + + if (nightTexturePath != ""){ + _hasNightTexture = true; + _nightTexturePath = absPath(nightTexturePath); + } - addPropertySubOwner(_geometry); + addPropertySubOwner(_geometry); - addProperty(_colorTexturePath); + addProperty(_colorTexturePath); _colorTexturePath.onChange(std::bind(&RenderablePlanet::loadTexture, this)); if (dictionary.hasKeyAndValue(keyShading)) { @@ -118,8 +118,8 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary) } addProperty(_performShading); - // Mainly for debugging purposes @AA - addProperty(_rotation); + // Mainly for debugging purposes @AA + addProperty(_rotation); } RenderablePlanet::~RenderablePlanet() { @@ -167,7 +167,7 @@ bool RenderablePlanet::deinitialize() { _geometry = nullptr; _texture = nullptr; - _nightTexture = nullptr; + _nightTexture = nullptr; return true; } @@ -176,7 +176,7 @@ bool RenderablePlanet::isReady() const { ready &= (_programObject != nullptr); ready &= (_texture != nullptr); ready &= (_geometry != nullptr); - return ready; + return ready; } void RenderablePlanet::render(const RenderData& data) @@ -186,50 +186,50 @@ void RenderablePlanet::render(const RenderData& data) // scale the planet to appropriate size since the planet is a unit sphere glm::mat4 transform = glm::mat4(1); - - //earth needs to be rotated for that to work. - glm::mat4 rot = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(1, 0, 0)); - glm::mat4 roty = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(0, -1, 0)); - glm::mat4 rotProp = glm::rotate(transform, glm::radians(static_cast(_rotation)), glm::vec3(0, 1, 0)); + + //earth needs to be rotated for that to work. + glm::mat4 rot = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(1, 0, 0)); + glm::mat4 roty = glm::rotate(transform, static_cast(M_PI_2), glm::vec3(0, -1, 0)); + glm::mat4 rotProp = glm::rotate(transform, glm::radians(static_cast(_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(_stateMatrix[i][j]); - } - } - transform = transform * rot * roty * rotProp; - - //glm::mat4 modelview = data.camera.viewMatrix()*data.camera.modelMatrix(); - //glm::vec3 camSpaceEye = (-(modelview*data.position.vec4())).xyz; + for (int i = 0; i < 3; i++){ + for (int j = 0; j < 3; j++){ + transform[i][j] = static_cast(_stateMatrix[i][j]); + } + } + transform = transform * rot * roty * rotProp; + + //glm::mat4 modelview = data.camera.viewMatrix()*data.camera.modelMatrix(); + //glm::vec3 camSpaceEye = (-(modelview*data.position.vec4())).xyz; - - double lt; + + double lt; glm::dvec3 p = SpiceManager::ref().targetPosition("SUN", _target, "GALACTIC", {}, _time, lt); psc sun_pos = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); // setup the data to the shader // _programObject->setUniform("camdir", camSpaceEye); - _programObject->setUniform("transparency", _alpha); - _programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); - _programObject->setUniform("ModelTransform", transform); - setPscUniforms(*_programObject.get(), data.camera, data.position); - + _programObject->setUniform("transparency", _alpha); + _programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); + _programObject->setUniform("ModelTransform", transform); + setPscUniforms(*_programObject.get(), data.camera, data.position); + _programObject->setUniform("_performShading", _performShading); // Bind texture - ghoul::opengl::TextureUnit dayUnit; - dayUnit.activate(); + ghoul::opengl::TextureUnit dayUnit; + dayUnit.activate(); _texture->bind(); - _programObject->setUniform("texture1", dayUnit); + _programObject->setUniform("texture1", dayUnit); - // Bind possible night texture - if (_hasNightTexture) { - ghoul::opengl::TextureUnit nightUnit; - nightUnit.activate(); - _nightTexture->bind(); - _programObject->setUniform("nightTex", nightUnit); - } + // Bind possible night texture + if (_hasNightTexture) { + ghoul::opengl::TextureUnit nightUnit; + nightUnit.activate(); + _nightTexture->bind(); + _programObject->setUniform("nightTex", nightUnit); + } glEnable(GL_CULL_FACE); glCullFace(GL_BACK); @@ -242,37 +242,37 @@ void RenderablePlanet::render(const RenderData& data) } void RenderablePlanet::update(const UpdateData& data){ - // set spice-orientation in accordance to timestamp + // set spice-orientation in accordance to timestamp _stateMatrix = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time); - _time = data.time; + _time = data.time; } void RenderablePlanet::loadTexture() { _texture = nullptr; - if (_colorTexturePath.value() != "") { + if (_colorTexturePath.value() != "") { _texture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath))); if (_texture) { LDEBUG("Loaded texture from '" << _colorTexturePath << "'"); - _texture->uploadTexture(); + _texture->uploadTexture(); - // Textures of planets looks much smoother with AnisotropicMipMap rather than linear + // Textures of planets looks much smoother with AnisotropicMipMap rather than linear // TODO: AnisotropicMipMap crashes on ATI cards ---abock //_texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); _texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); } } - if (_hasNightTexture) { - _nightTexture = nullptr; - if (_nightTexturePath != "") { + if (_hasNightTexture) { + _nightTexture = nullptr; + if (_nightTexturePath != "") { _nightTexture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_nightTexturePath))); - if (_nightTexture) { - LDEBUG("Loaded texture from '" << _nightTexturePath << "'"); - _nightTexture->uploadTexture(); + if (_nightTexture) { + LDEBUG("Loaded texture from '" << _nightTexturePath << "'"); + _nightTexture->uploadTexture(); _nightTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - //_nightTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); - } - } - } + //_nightTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + } + } + } } } // namespace openspace diff --git a/modules/newhorizons/util/labelparser.cpp b/modules/newhorizons/util/labelparser.cpp index 86bbf50f8d..e50f6b6dfa 100644 --- a/modules/newhorizons/util/labelparser.cpp +++ b/modules/newhorizons/util/labelparser.cpp @@ -36,9 +36,9 @@ #include namespace { - const std::string _loggerCat = "LabelParser"; - const std::string keySpecs = "Read"; - const std::string keyConvert = "Convert"; + const std::string _loggerCat = "LabelParser"; + const std::string keySpecs = "Read"; + const std::string keyConvert = "Convert"; const std::string PlaybookIdentifierName = "LabelParser"; } @@ -50,170 +50,170 @@ LabelParser::LabelParser(std::string name, const std::string& fileName, : _name(std::move(name)) , _badDecoding(false) { - _fileName = fileName; - //get the different instrument types - const std::vector& decoders = translationDictionary.keys(); - //for each decoder (assuming might have more if hong makes changes) - for (int i = 0; i < decoders.size(); i++){ - ghoul::Dictionary typeDictionary; - translationDictionary.getValue(decoders[i], typeDictionary); + _fileName = fileName; + //get the different instrument types + const std::vector& decoders = translationDictionary.keys(); + //for each decoder (assuming might have more if hong makes changes) + for (int i = 0; i < decoders.size(); i++){ + ghoul::Dictionary typeDictionary; + translationDictionary.getValue(decoders[i], typeDictionary); - //create dictionary containing all {playbookKeys , spice IDs} - if (decoders[i] == "Instrument"){ - //for each playbook call -> create a Decoder object - const std::vector& keys = typeDictionary.keys(); - for (int j = 0; j < keys.size(); j++){ - std::string currentKey = decoders[i] + "." + keys[j]; + //create dictionary containing all {playbookKeys , spice IDs} + if (decoders[i] == "Instrument"){ + //for each playbook call -> create a Decoder object + const std::vector& keys = typeDictionary.keys(); + for (int j = 0; j < keys.size(); j++){ + std::string currentKey = decoders[i] + "." + keys[j]; - ghoul::Dictionary decoderDictionary; - translationDictionary.getValue(currentKey, decoderDictionary); + ghoul::Dictionary decoderDictionary; + translationDictionary.getValue(currentKey, decoderDictionary); - Decoder *decoder = Decoder::createFromDictionary(decoderDictionary, decoders[i]); - //insert decoder to map - this will be used in the parser to determine - //behavioral characteristics of each instrument - _fileTranslation[keys[j]] = decoder; - } - } - if (decoders[i] == "Target"){ - ghoul::Dictionary specsOfInterestDictionary; - typeDictionary.getValue(keySpecs, specsOfInterestDictionary); + Decoder *decoder = Decoder::createFromDictionary(decoderDictionary, decoders[i]); + //insert decoder to map - this will be used in the parser to determine + //behavioral characteristics of each instrument + _fileTranslation[keys[j]] = decoder; + } + } + if (decoders[i] == "Target"){ + ghoul::Dictionary specsOfInterestDictionary; + typeDictionary.getValue(keySpecs, specsOfInterestDictionary); - _specsOfInterest.resize(specsOfInterestDictionary.size()); - for (int n = 0; n < _specsOfInterest.size(); ++n) { - std::string readMe; - specsOfInterestDictionary.getValue(std::to_string(n + 1), readMe); - _specsOfInterest[n] = readMe; - } - ghoul::Dictionary convertDictionary; - typeDictionary.getValue(keyConvert, convertDictionary); + _specsOfInterest.resize(specsOfInterestDictionary.size()); + for (int n = 0; n < _specsOfInterest.size(); ++n) { + std::string readMe; + specsOfInterestDictionary.getValue(std::to_string(n + 1), readMe); + _specsOfInterest[n] = readMe; + } + ghoul::Dictionary convertDictionary; + typeDictionary.getValue(keyConvert, convertDictionary); - const std::vector& keys = convertDictionary.keys(); - for (int j = 0; j < keys.size(); j++){ - ghoul::Dictionary itemDictionary; - convertDictionary.getValue(keys[j], itemDictionary); - Decoder *decoder = Decoder::createFromDictionary(itemDictionary, decoders[i]); - //insert decoder to map - this will be used in the parser to determine - //behavioral characteristics of each instrument - _fileTranslation[keys[j]] = decoder; - }; - } - } + const std::vector& keys = convertDictionary.keys(); + for (int j = 0; j < keys.size(); j++){ + ghoul::Dictionary itemDictionary; + convertDictionary.getValue(keys[j], itemDictionary); + Decoder *decoder = Decoder::createFromDictionary(itemDictionary, decoders[i]); + //insert decoder to map - this will be used in the parser to determine + //behavioral characteristics of each instrument + _fileTranslation[keys[j]] = decoder; + }; + } + } } std::string LabelParser::decode(std::string line){ - for (auto key : _fileTranslation){ - std::size_t value = line.find(key.first); - if (value != std::string::npos){ - std::string toTranslate = line.substr(value); - - //if (_fileTranslation.find(toTranslate) == _fileTranslation.end()) { - // // not found - // _badDecoding = true; - // LERROR("Could not fins '" << toTranslate << "' in translation map." << - // "\nPlease check label files"); - // return ""; - //} - return _fileTranslation[toTranslate]->getTranslation()[0]; //lbls always 1:1 -> single value return + for (auto key : _fileTranslation){ + std::size_t value = line.find(key.first); + if (value != std::string::npos){ + std::string toTranslate = line.substr(value); + + //if (_fileTranslation.find(toTranslate) == _fileTranslation.end()) { + // // not found + // _badDecoding = true; + // LERROR("Could not fins '" << toTranslate << "' in translation map." << + // "\nPlease check label files"); + // return ""; + //} + return _fileTranslation[toTranslate]->getTranslation()[0]; //lbls always 1:1 -> single value return - } - } - return ""; + } + } + return ""; } std::string LabelParser::encode(std::string line) { - for (auto key : _fileTranslation) { - std::size_t value = line.find(key.first); - if (value != std::string::npos) { - return line.substr(value); - } - } - return ""; + for (auto key : _fileTranslation) { + std::size_t value = line.find(key.first); + if (value != std::string::npos) { + return line.substr(value); + } + } + return ""; } bool LabelParser::create() { - auto imageComparer = [](const Image &a, const Image &b)->bool{ - return a.startTime < b.startTime; - }; - auto targetComparer = [](const std::pair &a, - const std::pair &b)->bool{ - return a.first < b.first; - }; - std::string previousTarget; - std::string lblName = ""; + auto imageComparer = [](const Image &a, const Image &b)->bool{ + return a.startTime < b.startTime; + }; + auto targetComparer = [](const std::pair &a, + const std::pair &b)->bool{ + return a.first < b.first; + }; + std::string previousTarget; + std::string lblName = ""; using RawPath = ghoul::filesystem::Directory::RawPath; - ghoul::filesystem::Directory sequenceDir(_fileName, RawPath::Yes); + ghoul::filesystem::Directory sequenceDir(_fileName, RawPath::Yes); if (!FileSys.directoryExists(sequenceDir)) { LERROR("Could not load Label Directory '" << sequenceDir.path() << "'"); return false; } using Recursive = ghoul::filesystem::Directory::Recursive; using Sort = ghoul::filesystem::Directory::Sort; - std::vector sequencePaths = sequenceDir.read(Recursive::Yes, Sort::No); - for (auto path : sequencePaths){ - if (size_t position = path.find_last_of(".") + 1){ - if (position != std::string::npos){ - ghoul::filesystem::File currentFile(path); - std::string extension = currentFile.fileExtension(); - if (extension == "lbl" || extension == "LBL"){ // discovered header file - std::ifstream file(currentFile.path()); + std::vector sequencePaths = sequenceDir.read(Recursive::Yes, Sort::No); + for (auto path : sequencePaths){ + if (size_t position = path.find_last_of(".") + 1){ + if (position != std::string::npos){ + ghoul::filesystem::File currentFile(path); + std::string extension = currentFile.fileExtension(); + if (extension == "lbl" || extension == "LBL"){ // discovered header file + std::ifstream file(currentFile.path()); - if (!file.good()){ - LERROR("Failed to open label file '" << currentFile.path() << "'"); - return false; - } - - int count = 0; + if (!file.good()){ + LERROR("Failed to open label file '" << currentFile.path() << "'"); + return false; + } + + int count = 0; - // open up label files - std::string line = ""; - std::string previousSequence; - TimeRange instrumentRange; + // open up label files + std::string line = ""; + std::string previousSequence; + TimeRange instrumentRange; - do { - std::getline(file, line); + do { + std::getline(file, line); - std::string read = line.substr(0, line.find_first_of(" ")); + std::string read = line.substr(0, line.find_first_of(" ")); - line.erase(std::remove(line.begin(), line.end(), '"'), line.end()); - line.erase(std::remove(line.begin(), line.end(), ' '), line.end()); + line.erase(std::remove(line.begin(), line.end(), '"'), line.end()); + line.erase(std::remove(line.begin(), line.end(), ' '), line.end()); line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); - _detectorType = "CAMERA"; //default value + _detectorType = "CAMERA"; //default value - /* Add more */ - if (read == "TARGET_NAME"){ - _target = decode(line); - count++; - } - if (read == "INSTRUMENT_HOST_NAME"){ - _instrumentHostID = decode(line); - count++; - } - if (read == "INSTRUMENT_ID"){ - _instrumentID = decode(line); - lblName = encode(line); - count++; - } - if (read == "DETECTOR_TYPE"){ - _detectorType = decode(line); - count++; - } - // if (_badDecoding){ - // LERROR("Please examine file: '" << currentFile.path() << "'"); - // return false; - // } + /* Add more */ + if (read == "TARGET_NAME"){ + _target = decode(line); + count++; + } + if (read == "INSTRUMENT_HOST_NAME"){ + _instrumentHostID = decode(line); + count++; + } + if (read == "INSTRUMENT_ID"){ + _instrumentID = decode(line); + lblName = encode(line); + count++; + } + if (read == "DETECTOR_TYPE"){ + _detectorType = decode(line); + count++; + } + // if (_badDecoding){ + // LERROR("Please examine file: '" << currentFile.path() << "'"); + // return false; + // } - if (read == "START_TIME"){ - std::string start = line.substr(line.find("=") + 2); - start.erase(std::remove(start.begin(), start.end(), ' '), start.end()); + if (read == "START_TIME"){ + std::string start = line.substr(line.find("=") + 2); + start.erase(std::remove(start.begin(), start.end(), ' '), start.end()); _startTime = SpiceManager::ref().ephemerisTimeFromDate(start); - count++; + count++; - getline(file, line); - read = line.substr(0, line.find_first_of(" ")); - if (read == "STOP_TIME"){ - std::string stop = line.substr(line.find("=") + 2); + getline(file, line); + read = line.substr(0, line.find_first_of(" ")); + if (read == "STOP_TIME"){ + std::string stop = line.substr(line.find("=") + 2); stop.erase( std::remove_if( stop.begin(), @@ -223,98 +223,98 @@ bool LabelParser::create() { stop.end() ); _stopTime = SpiceManager::ref().ephemerisTimeFromDate(stop); - count++; - } - else{ - LERROR("Label file " + currentFile.path() + " deviates from generic standard!"); - LINFO("Please make sure input data adheres to format https://pds.jpl.nasa.gov/documents/qs/labels.html"); - } - } - if (count == _specsOfInterest.size()){ - count = 0; - std::string ext = "jpg"; - path.replace(path.begin() + position, path.end(), ext); - bool fileExists = FileSys.fileExists(path); - if (!fileExists) { - ext = "JPG"; - path.replace(path.begin() + position, path.end(), ext); - fileExists = FileSys.fileExists(path); - } - if (fileExists) { - Image image; - std::vector spiceInstrument; - spiceInstrument.push_back(_instrumentID); - createImage(image, _startTime, _startTime, spiceInstrument, _target, path); - - _subsetMap[image.target]._subset.push_back(image); - _subsetMap[image.target]._range.setRange(_startTime); + count++; + } + else{ + LERROR("Label file " + currentFile.path() + " deviates from generic standard!"); + LINFO("Please make sure input data adheres to format https://pds.jpl.nasa.gov/documents/qs/labels.html"); + } + } + if (count == _specsOfInterest.size()){ + count = 0; + std::string ext = "jpg"; + path.replace(path.begin() + position, path.end(), ext); + bool fileExists = FileSys.fileExists(path); + if (!fileExists) { + ext = "JPG"; + path.replace(path.begin() + position, path.end(), ext); + fileExists = FileSys.fileExists(path); + } + if (fileExists) { + Image image; + std::vector spiceInstrument; + spiceInstrument.push_back(_instrumentID); + createImage(image, _startTime, _startTime, spiceInstrument, _target, path); + + _subsetMap[image.target]._subset.push_back(image); + _subsetMap[image.target]._range.setRange(_startTime); - _captureProgression.push_back(_startTime); - std::stable_sort(_captureProgression.begin(), _captureProgression.end()); - } - - } - } while (!file.eof()); - } - } - } - } - - std::vector tmp; - for (auto key : _subsetMap){ - for (auto image : key.second._subset){ - tmp.push_back(image); - } - } - std::sort(tmp.begin(), tmp.end(), imageComparer); + _captureProgression.push_back(_startTime); + std::stable_sort(_captureProgression.begin(), _captureProgression.end()); + } + + } + } while (!file.eof()); + } + } + } + } + + std::vector tmp; + for (auto key : _subsetMap){ + for (auto image : key.second._subset){ + tmp.push_back(image); + } + } + std::sort(tmp.begin(), tmp.end(), imageComparer); - for (auto image : tmp){ - if (previousTarget != image.target){ - previousTarget = image.target; - std::pair v_target = std::make_pair(image.startTime, image.target); - _targetTimes.push_back(v_target); - std::sort(_targetTimes.begin(), _targetTimes.end(), targetComparer); - } - } + for (auto image : tmp){ + if (previousTarget != image.target){ + previousTarget = image.target; + std::pair v_target = std::make_pair(image.startTime, image.target); + _targetTimes.push_back(v_target); + std::sort(_targetTimes.begin(), _targetTimes.end(), targetComparer); + } + } - for (auto target : _subsetMap){ - _instrumentTimes.push_back(std::make_pair(lblName, _subsetMap[target.first]._range)); + for (auto target : _subsetMap){ + _instrumentTimes.push_back(std::make_pair(lblName, _subsetMap[target.first]._range)); - // std::string min, max; - // SpiceManager::ref().getDateFromET(target.second._range._min, min); - // SpiceManager::ref().getDateFromET(target.second._range._max, max); + // std::string min, max; + // SpiceManager::ref().getDateFromET(target.second._range._min, min); + // SpiceManager::ref().getDateFromET(target.second._range._max, max); - // myfile << std::endl; - // for (auto image : target.second._subset){ - // std::string time_beg; - // std::string time_end; - // SpiceManager::ref().getDateFromET(image.startTime, time_beg); - // SpiceManager::ref().getDateFromET(image.stopTime, time_end); + // myfile << std::endl; + // for (auto image : target.second._subset){ + // std::string time_beg; + // std::string time_end; + // SpiceManager::ref().getDateFromET(image.startTime, time_beg); + // SpiceManager::ref().getDateFromET(image.stopTime, time_end); - // myfile << std::fixed - // << " " << time_beg - // << "-->" << time_end - // << " [ " << image.startTime - // << " ] " << image.target << std::setw(10); - // for (auto instrument : image.activeInstruments){ - // myfile << " " << instrument; - // } - // myfile << std::endl; - // } - } + // myfile << std::fixed + // << " " << time_beg + // << "-->" << time_end + // << " [ " << image.startTime + // << " ] " << image.target << std::setw(10); + // for (auto instrument : image.activeInstruments){ + // myfile << " " << instrument; + // } + // myfile << std::endl; + // } + } sendPlaybookInformation(PlaybookIdentifierName); - return true; + return true; } void LabelParser::createImage(Image& image, double startTime, double stopTime, std::vector instr, std::string targ, std::string pot) { - image.startTime = startTime; - image.stopTime = stopTime; - image.path = pot; - for (int i = 0; i < instr.size(); i++){ - image.activeInstruments.push_back(instr[i]); - } - image.target = targ; - image.projected = false; + image.startTime = startTime; + image.stopTime = stopTime; + image.path = pot; + for (int i = 0; i < instr.size(); i++){ + image.activeInstruments.push_back(instr[i]); + } + image.target = targ; + image.projected = false; } } \ No newline at end of file diff --git a/src/engine/configurationmanager.cpp b/src/engine/configurationmanager.cpp index 1d7605de6d..30e21f1ea6 100644 --- a/src/engine/configurationmanager.cpp +++ b/src/engine/configurationmanager.cpp @@ -34,7 +34,7 @@ using std::string; namespace { const string _configurationFile = "openspace.cfg"; - const string _keyBasePath = "BASE_PATH"; + const string _keyBasePath = "BASE_PATH"; } namespace openspace { @@ -91,24 +91,24 @@ string ConfigurationManager::findConfiguration(const string& filename) { } void ConfigurationManager::loadFromFile(const string& filename) { - using ghoul::filesystem::FileSystem; + using ghoul::filesystem::FileSystem; if (!FileSys.fileExists(filename)) throw ghoul::FileNotFoundError(filename, "ConfigurationManager"); - // ${BASE_PATH} - string basePathToken = FileSystem::TokenOpeningBraces + _keyBasePath + // ${BASE_PATH} + string basePathToken = FileSystem::TokenOpeningBraces + _keyBasePath + FileSystem::TokenClosingBraces; - // Retrieving the directory in which the configuration file lies + // Retrieving the directory in which the configuration file lies string absolutePath = FileSys.absolutePath(filename); - string basePath = ghoul::filesystem::File(absolutePath).directoryName(); - FileSys.registerPathToken(basePathToken, basePath); + string basePath = ghoul::filesystem::File(absolutePath).directoryName(); + FileSys.registerPathToken(basePathToken, basePath); - // Loading the configuration file into ourselves + // Loading the configuration file into ourselves ghoul::lua::loadDictionaryFromFile(filename, *this); - // Register all the paths + // Register all the paths ghoul::Dictionary dictionary = value(KeyPaths); std::vector pathKeys = dictionary.keys(); @@ -118,8 +118,8 @@ void ConfigurationManager::loadFromFile(const string& filename) { std::string fullKey = FileSystem::TokenOpeningBraces + key + FileSystem::TokenClosingBraces; LDEBUGC("ConfigurationManager", "Registering path " << fullKey << ": " << p); - - bool override = (basePathToken == fullKey); + + bool override = (basePathToken == fullKey); if (override) LINFOC("ConfigurationManager", "Overriding base path with '" << p << "'"); @@ -132,7 +132,7 @@ void ConfigurationManager::loadFromFile(const string& filename) { } } - bool complete = checkCompleteness(); + bool complete = checkCompleteness(); if (!complete) { throw ghoul::RuntimeError( "Configuration file '" + filename + "' was not complete", @@ -140,34 +140,34 @@ void ConfigurationManager::loadFromFile(const string& filename) { ); } - // Remove the Paths dictionary from the configuration manager as those paths might - // change later and we don't want to be forced to keep our local copy up to date - removeKey(KeyPaths); + // Remove the Paths dictionary from the configuration manager as those paths might + // change later and we don't want to be forced to keep our local copy up to date + removeKey(KeyPaths); } bool ConfigurationManager::checkCompleteness() const { - std::vector requiredTokens = { - KeyPaths, - KeyPaths + "." + KeyCache, - KeyFonts, - KeyConfigSgct - }; + std::vector requiredTokens = { + KeyPaths, + KeyPaths + "." + KeyCache, + KeyFonts, + KeyConfigSgct + }; - bool totalSuccess = true; - for (const std::string& token : requiredTokens) { - bool success = hasKey(token); + bool totalSuccess = true; + for (const std::string& token : requiredTokens) { + bool success = hasKey(token); if (!success) { - LFATALC( + LFATALC( "ConfigurationManager", "Configuration file did not contain required key '" << token << "'" ); } - totalSuccess &= success; - } + totalSuccess &= success; + } - return totalSuccess; + return totalSuccess; } } // namespace openspace diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index 5f88de541d..2f8d0fa86c 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -71,7 +71,7 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di ghoul::Dictionary renderableDictionary; dictionary.getValue(KeyRenderable, renderableDictionary); - renderableDictionary.setValue(KeyName, name); + renderableDictionary.setValue(KeyName, name); result->_renderable = Renderable::createFromDictionary(renderableDictionary); if (result->_renderable == nullptr) { @@ -80,7 +80,7 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di delete result; return nullptr; } - result->addPropertySubOwner(result->_renderable); + result->addPropertySubOwner(result->_renderable); LDEBUG("Successfully create renderable for '" << result->name() << "'"); } @@ -95,7 +95,7 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di delete result; return nullptr; } - //result->addPropertySubOwner(result->_ephemeris); + //result->addPropertySubOwner(result->_ephemeris); LDEBUG("Successfully create ephemeris for '" << result->name() << "'"); } @@ -147,18 +147,18 @@ bool SceneGraphNode::deinitialize() { LDEBUG("Deinitialize: " << name()); if (_renderable) { - _renderable->deinitialize(); + _renderable->deinitialize(); delete _renderable; - _renderable = nullptr; - } + _renderable = nullptr; + } delete _ephemeris; _ephemeris = nullptr; // for (SceneGraphNode* child : _children) { - // child->deinitialize(); - // delete child; - //} + // child->deinitialize(); + // delete child; + //} _children.clear(); // reset variables @@ -171,35 +171,35 @@ bool SceneGraphNode::deinitialize() { } void SceneGraphNode::update(const UpdateData& data) { - if (_ephemeris) { - if (data.doPerformanceMeasurement) { - glFinish(); + if (_ephemeris) { + if (data.doPerformanceMeasurement) { + glFinish(); auto start = std::chrono::high_resolution_clock::now(); - _ephemeris->update(data); + _ephemeris->update(data); - glFinish(); - auto end = std::chrono::high_resolution_clock::now(); - _performanceRecord.updateTimeEphemeris = (end - start).count(); - } - else - _ephemeris->update(data); - } + glFinish(); + auto end = std::chrono::high_resolution_clock::now(); + _performanceRecord.updateTimeEphemeris = (end - start).count(); + } + else + _ephemeris->update(data); + } - if (_renderable && _renderable->isReady()) { - if (data.doPerformanceMeasurement) { - glFinish(); - auto start = std::chrono::high_resolution_clock::now(); + if (_renderable && _renderable->isReady()) { + if (data.doPerformanceMeasurement) { + glFinish(); + auto start = std::chrono::high_resolution_clock::now(); - _renderable->update(data); + _renderable->update(data); - glFinish(); - auto end = std::chrono::high_resolution_clock::now(); - _performanceRecord.updateTimeRenderable = (end - start).count(); - } - else - _renderable->update(data); - } + glFinish(); + auto end = std::chrono::high_resolution_clock::now(); + _performanceRecord.updateTimeRenderable = (end - start).count(); + } + else + _renderable->update(data); + } } void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) { @@ -222,7 +222,7 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) { return; } } - */ + */ #endif // inside boudningsphere or parts of the sphere is visible, individual @@ -245,22 +245,22 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) { void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) { const psc thisPosition = worldPosition(); - RenderData newData = {data.camera, thisPosition, data.doPerformanceMeasurement}; + RenderData newData = {data.camera, thisPosition, data.doPerformanceMeasurement}; - _performanceRecord.renderTime = 0; + _performanceRecord.renderTime = 0; if (_renderableVisible && _renderable->isVisible() && _renderable->isReady() && _renderable->isEnabled()) { - if (data.doPerformanceMeasurement) { - glFinish(); - auto start = std::chrono::high_resolution_clock::now(); + if (data.doPerformanceMeasurement) { + glFinish(); + auto start = std::chrono::high_resolution_clock::now(); - _renderable->render(newData, tasks); + _renderable->render(newData, tasks); - glFinish(); - auto end = std::chrono::high_resolution_clock::now(); - _performanceRecord.renderTime = (end - start).count(); - } - else - _renderable->render(newData, tasks); + glFinish(); + auto end = std::chrono::high_resolution_clock::now(); + _performanceRecord.renderTime = (end - start).count(); + } + else + _renderable->render(newData, tasks); } // evaluate all the children, tail-recursive function(?) @@ -326,8 +326,8 @@ const std::vector& SceneGraphNode::children() const{ // bounding sphere PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){ // set the bounding sphere to 0.0 - _boundingSphere = 0.0; - + _boundingSphere = 0.0; + if (!_children.empty()) { // node PowerScaledScalar maxChild; @@ -338,7 +338,7 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){ // position //PowerScaledScalar child = _children.at(i)->position().length() // + _children.at(i)->calculateBoundingSphere(); - PowerScaledScalar child = _children.at(i)->calculateBoundingSphere(); + PowerScaledScalar child = _children.at(i)->calculateBoundingSphere(); if (child > maxChild) { maxChild = child; } @@ -352,8 +352,8 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){ if(renderableBS > _boundingSphere) _boundingSphere = renderableBS; } - //LINFO("Bounding Sphere of '" << name() << "': " << _boundingSphere); - + //LINFO("Bounding Sphere of '" << name() << "': " << _boundingSphere); + return _boundingSphere; } @@ -372,7 +372,7 @@ const Renderable* SceneGraphNode::renderable() const } Renderable* SceneGraphNode::renderable() { - return _renderable; + return _renderable; } // private helper methods @@ -422,21 +422,21 @@ SceneGraphNode* SceneGraphNode::childNode(const std::string& name) void SceneGraphNode::updateCamera(Camera* camera) const{ - psc origin = worldPosition(); - //int i = 0; - // the camera position - - psc relative = camera->position(); - psc focus = camera->focusPosition(); - psc relative_focus = relative - focus; + psc origin = worldPosition(); + //int i = 0; + // the camera position + + psc relative = camera->position(); + psc focus = camera->focusPosition(); + psc relative_focus = relative - focus; - psc target = origin + relative_focus; - - camera->setPosition(target); - camera->setFocusPosition(origin); + psc target = origin + relative_focus; + + camera->setPosition(target); + camera->setFocusPosition(origin); - //printf("target: %f, %f, %f, %f\n", target.vec4().x, target.vec4().y, target.vec4().z, target.vec4().w); - + //printf("target: %f, %f, %f, %f\n", target.vec4().x, target.vec4().y, target.vec4().z, target.vec4().w); + } } // namespace openspace diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index bf57fc843c..a212f752d0 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -35,7 +35,7 @@ #include namespace { - const std::string _loggerCat = "SpiceManager"; + const std::string _loggerCat = "SpiceManager"; // The value comes from // http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/getmsg_c.html @@ -189,7 +189,7 @@ SpiceManager::KernelHandle SpiceManager::loadKernel(string filePath) { ) ); - string path = absPath(filePath); + string path = absPath(filePath); auto it = std::find_if( _loadedKernels.begin(), _loadedKernels.end(), @@ -213,11 +213,11 @@ SpiceManager::KernelHandle SpiceManager::loadKernel(string filePath) { ghoul::filesystem::Directory currentDirectory = FileSys.currentDirectory(); using RawPath = ghoul::filesystem::File::RawPath; string fileDirectory = ghoul::filesystem::File(path, RawPath::Yes).directoryName(); - FileSys.setCurrentDirectory(fileDirectory); + FileSys.setCurrentDirectory(fileDirectory); LINFO("Loading SPICE kernel '" << path << "'"); // Load the kernel - furnsh_c(path.c_str()); + furnsh_c(path.c_str()); // Reset the current directory to the previous one FileSys.setCurrentDirectory(currentDirectory); @@ -226,9 +226,9 @@ SpiceManager::KernelHandle SpiceManager::loadKernel(string filePath) { string fileExtension = ghoul::filesystem::File(path, RawPath::Yes).fileExtension(); if (fileExtension == "bc" || fileExtension == "BC") - findCkCoverage(path); // binary ck kernel - else if (fileExtension == "bsp" || fileExtension == "BSP") - findSpkCoverage(path); // binary spk kernel + findCkCoverage(path); // binary ck kernel + else if (fileExtension == "bsp" || fileExtension == "BSP") + findSpkCoverage(path); // binary spk kernel KernelHandle kernelId = ++_lastAssignedKernel; ghoul_assert(kernelId != 0, fmt::format("Kernel Handle wrapped around to 0")); @@ -240,23 +240,23 @@ void SpiceManager::unloadKernel(KernelHandle kernelId) { ghoul_assert(kernelId <= _lastAssignedKernel, "Invalid unassigned kernel"); ghoul_assert(kernelId != KernelHandle(0), "Invalid zero handle"); - auto it = std::find_if(_loadedKernels.begin(), _loadedKernels.end(), - [&kernelId](const KernelInformation& info) { return info.id == kernelId; }); + auto it = std::find_if(_loadedKernels.begin(), _loadedKernels.end(), + [&kernelId](const KernelInformation& info) { return info.id == kernelId; }); - if (it != _loadedKernels.end()) { + if (it != _loadedKernels.end()) { // If there was only one part interested in the kernel, we can unload it if (it->refCount == 1) { - // No need to check for errors as we do not allow empty path names + // No need to check for errors as we do not allow empty path names LINFO(format("Unloading SPICE kernel '{}'", it->path)); - unload_c(it->path.c_str()); - _loadedKernels.erase(it); + unload_c(it->path.c_str()); + _loadedKernels.erase(it); } // Otherwise, we hold on to it, but reduce the reference counter by 1 else { it->refCount--; LDEBUG(format("Reducing reference counter to: {}", it->refCount)); } - } + } } void SpiceManager::unloadKernel(std::string filePath) { @@ -264,15 +264,15 @@ void SpiceManager::unloadKernel(std::string filePath) { string path = absPath(filePath); - auto it = std::find_if(_loadedKernels.begin(), _loadedKernels.end(), - [&path](const KernelInformation& info) { return info.path == path; }); + auto it = std::find_if(_loadedKernels.begin(), _loadedKernels.end(), + [&path](const KernelInformation& info) { return info.path == path; }); if (it == _loadedKernels.end()) { throw SpiceException( format("'{}' did not correspond to a loaded kernel", path) ); } - else { + else { // If there was only one part interested in the kernel, we can unload it if (it->refCount == 1) { LINFO(format("Unloading SPICE kernel '{}'", path)); @@ -284,7 +284,7 @@ void SpiceManager::unloadKernel(std::string filePath) { it->refCount--; LDEBUG(format("Reducing reference counter to: {}", it->refCount)); } - } + } } bool SpiceManager::hasSpkCoverage(const string& target, double et) const { @@ -319,14 +319,14 @@ bool SpiceManager::hasCkCoverage(const string& frame, double et) const { } bool SpiceManager::hasValue(int naifId, const std::string& item) const { - return bodfnd_c(naifId, item.c_str()); + return bodfnd_c(naifId, item.c_str()); } bool SpiceManager::hasValue(const std::string& body, const std::string& item) const { ghoul_assert(!body.empty(), "Empty body"); ghoul_assert(!item.empty(), "Empty item"); - int id = naifId(body); + int id = naifId(body); return hasValue(id, item); } @@ -370,14 +370,14 @@ bool SpiceManager::hasFrameId(const std::string& frame) const { } void getValueInternal(const std::string& body, const std::string& value, int size, - double* v) + double* v) { ghoul_assert(!body.empty(), "Empty body"); ghoul_assert(!value.empty(), "Empty value"); ghoul_assert(v != nullptr, "Empty value pointer"); - SpiceInt n; - bodvrd_c(body.c_str(), value.c_str(), size, &n, v); + SpiceInt n; + bodvrd_c(body.c_str(), value.c_str(), size, &n, v); throwOnSpiceError( format("Error getting value '{}' for body '{}'", @@ -390,7 +390,7 @@ void getValueInternal(const std::string& body, const std::string& value, int siz void SpiceManager::getValue(const std::string& body, const std::string& value, double& v) const { - getValueInternal(body, value, 1, &v); + getValueInternal(body, value, 1, &v); } void SpiceManager::getValue(const std::string& body, const std::string& value, @@ -402,17 +402,17 @@ void SpiceManager::getValue(const std::string& body, const std::string& value, void SpiceManager::getValue(const std::string& body, const std::string& value, glm::dvec3& v) const { - getValueInternal(body, value, 3, glm::value_ptr(v)); + getValueInternal(body, value, 3, glm::value_ptr(v)); } void SpiceManager::getValue(const std::string& body, const std::string& value, - glm::dvec4& v) const + glm::dvec4& v) const { - getValueInternal(body, value, 4, glm::value_ptr(v)); + getValueInternal(body, value, 4, glm::value_ptr(v)); } void SpiceManager::getValue(const std::string& body, const std::string& value, - std::vector& v) const + std::vector& v) const { ghoul_assert(!v.empty(), "Array for values has to be preallocaed"); @@ -424,19 +424,19 @@ double SpiceManager::spacecraftClockToET(const std::string& craft, double craftT int craftId = naifId(craft); double et; - sct2e_c(craftId, craftTicks, &et); + sct2e_c(craftId, craftTicks, &et); throwOnSpiceError(format( "Error transforming spacecraft clock of '{}' at time {}", craft, craftTicks) ); - return et; + return et; } double SpiceManager::ephemerisTimeFromDate(const std::string& timeString) const { ghoul_assert(!timeString.empty(), "Empty timeString"); double et; - str2et_c(timeString.c_str(), &et); + str2et_c(timeString.c_str(), &et); throwOnSpiceError(format("Error converting date '{}'", timeString)); return et; } @@ -469,26 +469,26 @@ glm::dvec3 SpiceManager::targetPosition(const std::string& target, ghoul_assert(!observer.empty(), "Observer is not empty"); ghoul_assert(!referenceFrame.empty(), "Reference frame is not empty"); - bool targetHasCoverage = hasSpkCoverage(target, ephemerisTime); - bool observerHasCoverage = hasSpkCoverage(observer, ephemerisTime); - if (!targetHasCoverage && !observerHasCoverage){ + bool targetHasCoverage = hasSpkCoverage(target, ephemerisTime); + bool observerHasCoverage = hasSpkCoverage(observer, ephemerisTime); + if (!targetHasCoverage && !observerHasCoverage){ throw SpiceException( format("Neither the target '{}' nor observer '{}' has SPK coverage", target, observer ) ); - } - else if (targetHasCoverage && observerHasCoverage) { + } + else if (targetHasCoverage && observerHasCoverage) { glm::dvec3 position; - spkpos_c( + spkpos_c( target.c_str(), ephemerisTime, referenceFrame.c_str(), aberrationCorrection, observer.c_str(), glm::value_ptr(position), - &lightTime + &lightTime ); throwOnSpiceError(format( "Error getting target position from '{}' to '{}' in reference frame '{}", @@ -497,7 +497,7 @@ glm::dvec3 SpiceManager::targetPosition(const std::string& target, referenceFrame )); return position; - } + } else if (targetHasCoverage) { // observer has no coverage return getEstimatedPosition( @@ -531,13 +531,13 @@ glm::dmat3 SpiceManager::frameTransformationMatrix(const std::string& from, // get rotation matrix from frame A - frame B glm::dmat3 transform; - pxform_c( + pxform_c( from.c_str(), to.c_str(), ephemerisTime, reinterpret_cast(glm::value_ptr(transform)) ); - + throwOnSpiceError( format("Error converting from frame '{}' to frame '{}' at time '{}'", from, to, ephemerisTime @@ -601,8 +601,8 @@ bool SpiceManager::isTargetInFieldOfView(const std::string& target, ghoul_assert(!referenceFrame.empty(), "Reference frame must not be empty"); ghoul_assert(!instrument.empty(), "Instrument must not be empty"); - int visible; - fovtrg_c(instrument.c_str(), + int visible; + fovtrg_c(instrument.c_str(), target.c_str(), toString(method), referenceFrame.c_str(), @@ -617,7 +617,7 @@ bool SpiceManager::isTargetInFieldOfView(const std::string& target, target, instrument )); - return visible == SPICETRUE; + return visible == SPICETRUE; } bool SpiceManager::isTargetInFieldOfView(const std::string& target, @@ -648,7 +648,7 @@ SpiceManager::TargetStateResult SpiceManager::targetState(const std::string& tar double buffer[6]; - spkezr_c( + spkezr_c( target.c_str(), ephemerisTime, referenceFrame.c_str(), @@ -676,7 +676,7 @@ SpiceManager::TransformMatrix SpiceManager::stateTransformMatrix(const string& f ghoul_assert(!toFrame.empty(), "toFrame must not be empty"); TransformMatrix m; - sxform_c( + sxform_c( fromFrame.c_str(), toFrame.c_str(), ephemerisTime, @@ -697,7 +697,7 @@ glm::dmat3 SpiceManager::positionTransformMatrix(const std::string& fromFrame, ghoul_assert(!toFrame.empty(), "toFrame must not be empty"); glm::dmat3 result; - pxform_c( + pxform_c( fromFrame.c_str(), toFrame.c_str(), ephemerisTime, @@ -705,11 +705,11 @@ glm::dmat3 SpiceManager::positionTransformMatrix(const std::string& fromFrame, ); throwOnSpiceError(""); - SpiceBoolean success = !(failed_c()); + SpiceBoolean success = !(failed_c()); reset_c(); bool estimated = false; - if (!success) - result = getEstimatedTransformMatrix(fromFrame, toFrame, ephemerisTime); + if (!success) + result = getEstimatedTransformMatrix(fromFrame, toFrame, ephemerisTime); return glm::transpose(result); } @@ -722,7 +722,7 @@ glm::dmat3 SpiceManager::positionTransformMatrix(const std::string& fromFrame, glm::dmat3 result; - pxfrm2_c( + pxfrm2_c( fromFrame.c_str(), toFrame.c_str(), ephemerisTimeFrom, @@ -745,24 +745,24 @@ SpiceManager::fieldOfView(const std::string& instrument) const } SpiceManager::FieldOfViewResult SpiceManager::fieldOfView(int instrument) const { - static const int MaxBoundsSize = 64; - static const int BufferSize = 128; + static const int MaxBoundsSize = 64; + static const int BufferSize = 128; FieldOfViewResult res; - SpiceInt nrReturned; - double boundsArr[MaxBoundsSize][3]; + SpiceInt nrReturned; + double boundsArr[MaxBoundsSize][3]; char fovShapeBuffer[BufferSize]; char frameNameBuffer[BufferSize]; - getfov_c(instrument, // instrument id + getfov_c(instrument, // instrument id MaxBoundsSize, // maximum size for the bounds vector BufferSize, // maximum size for the fov shape buffer - BufferSize, // maximum size for the frame name buffer - fovShapeBuffer, // the fov shape buffer - frameNameBuffer, // the frame name buffer - glm::value_ptr(res.boresightVector), // the boresight vector - &nrReturned, // the number of returned array values - boundsArr // the bounds + BufferSize, // maximum size for the frame name buffer + fovShapeBuffer, // the fov shape buffer + frameNameBuffer, // the frame name buffer + glm::value_ptr(res.boresightVector), // the boresight vector + &nrReturned, // the number of returned array values + boundsArr // the bounds ); throwOnSpiceError(format( @@ -770,7 +770,7 @@ SpiceManager::FieldOfViewResult SpiceManager::fieldOfView(int instrument) const )); res.bounds.reserve(nrReturned); - for (int i = 0; i < nrReturned; ++i) + for (int i = 0; i < nrReturned; ++i) res.bounds.emplace_back(boundsArr[i][0], boundsArr[i][1], boundsArr[i][2]); string shape = string(fovShapeBuffer); @@ -783,7 +783,7 @@ SpiceManager::FieldOfViewResult SpiceManager::fieldOfView(int instrument) const res.shape = Map.at(shape); res.frameName = string(frameNameBuffer); - return res; + return res; } SpiceManager::TerminatorEllipseResult SpiceManager::terminatorEllipse( @@ -803,24 +803,24 @@ SpiceManager::TerminatorEllipseResult SpiceManager::terminatorEllipse( // Warning: This assumes std::vector to have all values memory contiguous res.terminatorPoints.resize(numberOfTerminatorPoints); - edterm_c(toString(terminatorType), - lightSource.c_str(), - target.c_str(), - ephemerisTime, - frame.c_str(), - aberrationCorrection, - observer.c_str(), - numberOfTerminatorPoints, - &res.targetEphemerisTime, - glm::value_ptr(res.observerPosition), - (double(*)[3])res.terminatorPoints.data() + edterm_c(toString(terminatorType), + lightSource.c_str(), + target.c_str(), + ephemerisTime, + frame.c_str(), + aberrationCorrection, + observer.c_str(), + numberOfTerminatorPoints, + &res.targetEphemerisTime, + glm::value_ptr(res.observerPosition), + (double(*)[3])res.terminatorPoints.data() ); throwOnSpiceError(format( "Error getting terminator ellipse for target '{}' from observer '{}' in frame " "'{}' with light source '{}' at time '{}'", target, observer, frame, lightSource, ephemerisTime )); - return res; + return res; } bool SpiceManager::addFrame(std::string body, std::string frame) { @@ -833,21 +833,21 @@ bool SpiceManager::addFrame(std::string body, std::string frame) { } std::string SpiceManager::frameFromBody(const std::string& body) const { - for (auto pair : _frameByBody) { - if (pair.first == body) { - return pair.second; - } - } + for (auto pair : _frameByBody) { + if (pair.first == body) { + return pair.second; + } + } - std::string unionPrefix = "IAU_"; - std::string frame = ""; + std::string unionPrefix = "IAU_"; + std::string frame = ""; - if (body.find(unionPrefix) == std::string::npos) - frame = unionPrefix + body; - else - frame = body; + if (body.find(unionPrefix) == std::string::npos) + frame = unionPrefix + body; + else + frame = body; - return frame; + return frame; } void SpiceManager::findCkCoverage(const std::string& path) { From a59a1bd758182b412ec5421bee3ac86681a8d31f Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 15:15:42 +0200 Subject: [PATCH 36/38] Turn off logging flush for increased performance --- openspace.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openspace.cfg b/openspace.cfg index 7cfefd58bd..976fb70dd9 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -39,7 +39,7 @@ return { }, Logging = { LogLevel = "Debug", - ImmediateFlush = true, + ImmediateFlush = false, Logs = { { Type = "HTML", FileName = "${BASE_PATH}/log.html", Append = false } }, From 6c6555bbcefea23c6f49ce28dd5f9571b206c285 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 16:44:44 +0200 Subject: [PATCH 37/38] Print out the number of warnings, errors, and fatal errors that happened during initialization and each frame after Updated to new Ghoul version --- ext/ghoul | 2 +- src/engine/openspaceengine.cpp | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index f3c46149dd..a1556e0497 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit f3c46149dd6e224f565a8fced5e3eeff003828bc +Subproject commit a1556e04976dc66225614a2435a6576e3ff6eecf diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index b4c4aa6405..a473c8048d 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -652,6 +652,22 @@ void OpenSpaceEngine::postSynchronizationPreDraw() { _gui->startFrame(static_cast(dt), glm::vec2(drawBufferResolution), mousePosition, mouseButtons); } + + // Testing this every frame has minimal impact on the performance --- abock + // Debug build: 1-2 us ; Release build: <= 1 us + using ghoul::logging::LogManager; + int warningCounter = LogMgr.messageCounter(LogManager::LogLevel::Warning); + int errorCounter = LogMgr.messageCounter(LogManager::LogLevel::Error); + int fatalCounter = LogMgr.messageCounter(LogManager::LogLevel::Fatal); + + if (warningCounter > 0) + LWARNINGC("Logging", "Number of Warnings raised: " << warningCounter); + if (errorCounter > 0) + LWARNINGC("Logging", "Number of Errors raised: " << errorCounter); + if (fatalCounter > 0) + LWARNINGC("Logging", "Number of Fatals raised: " << fatalCounter); + + LogMgr.resetMessageCounters(); } void OpenSpaceEngine::render(const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix) { From 248014b6c2584a597307cca3d29e0d51863f527b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 18 Apr 2016 20:06:48 +0200 Subject: [PATCH 38/38] Add Python script that converts tabs into spaces --- support/coding/convert_tabs.py | 107 +++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 support/coding/convert_tabs.py diff --git a/support/coding/convert_tabs.py b/support/coding/convert_tabs.py new file mode 100644 index 0000000000..7ee74f1cf1 --- /dev/null +++ b/support/coding/convert_tabs.py @@ -0,0 +1,107 @@ +""" +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. + + +This script traverses the file tree of OpenSpace and converts all tabs into spaces. +If this script is executed from the base directory of OpenSpace, no arguments need to +be passed, otherwise the first and only argument has to point to the base directory. +Thus, the default value of the first argument is '.' +""" + +import glob +import sys + +basePath = './' +if len(sys.argv) > 1: + basePath = sys.argv[1] + '/' + + +positivePathList = [ + 'src/**/*.cpp', + 'include/**/*.h', + 'include/**/*.inl', + 'apps/**/*.cpp', + 'apps/**/*.h', + 'apps/**/*.inl', + 'modules/**/*.cpp', + 'modules/**/*.h', + 'modules/**/*.inl', + 'modules/**/*.glsl', + 'ext/ghoul/src/**/*.cpp', + 'ext/ghoul/include/**/*.h', + 'ext/ghoul/include/**/*.inl', + 'shaders/**/*.glsl', + 'shaders/**/*.hglsl', + 'shaders/**/*.vert', + 'shaders/**/*.gs', + 'shaders/**/*.frag' +] + +negativePathList = [ + 'modules/**/ext/**', + 'apps/**/ext/**' +] + +def convertFile(file): + result = False + with open(file, 'r+') as f: + lines = f.readlines() + for l in lines: + if l.find('\t') != -1: + result = True + break + + if result: + lines[:] = [l.replace('\t', ' ') for l in lines] + # print(lines) + + f.seek(0) + f.writelines(lines) + f.truncate() + + return result + +# Collect all the files that we might apply this script to +files = [] +for p in positivePathList: + f = glob.glob(basePath + p, recursive=True) + files = files + f + +# Collect all files that we want to remove from the full list +# These are mostly the external directories from modules +negativeFiles = [] +for p in negativePathList: + f = glob.glob(basePath + p, recursive=True) + negativeFiles = negativeFiles + f + +# Actually remove the negative files from the positive ones +files = [f for f in files if f not in negativeFiles] + +totalNumber = 0 +for f in files: + hasChanged = convertFile(f) + if hasChanged: + print("Changed tabs to spaces in " + f) + totalNumber = totalNumber + 1 + +print("Total number of changed files: " + str(totalNumber)) +sys.exit(totalNumber) \ No newline at end of file